How to extend Widgets length within a QScrollArea?

4

I'm looking to build a question form in Qt. As there are several questions to be answered, it is necessary to allow the scrolling of the form, so I used a QScrollArea . The questions are all answered in a Likert scale, so I adjusted the alignment of the layout that contains them to the left and spaced out the options manually. That is, everything is left aligned . I've also implemented an alternate colored style, just to make it more enjoyable for the user to differentiate questions by scrolling through the form.

Here is an image of the MCVE that I have prepared (and is below). The main problem is that I can not get this "zebra" to extend to the end of the form (on the right, indicated in the blue box in the image). There is also the space that looks like a margin on the left (indicated in the red box).

Tosolvethemainproblem,I'vetriedtochangethesizeconstraintsofchildlayouts(usingsetSizeConstraint)andevenaddastretch(stretch)afterthelastoptionnoteinthelineofcodemarkedwithcomment),butnoneoftheseoptionsworks.Andforthesecondaryproblem,well,I'vetriedtochangethemarginsviastylesheet(asitisinthecode)andevenusethesetMarginmethodoftheQWidgetclassitself,butnothingworks.

Whatworksforthemainproblemistosetaminimumorfixedsizefortheoptionscontainer(theobjectinpRow),butIcannotusethisoptionbecausethewindowcanhavethesizesetbytheuserdependingonthescreendimensionsavailabletoit).Alsobecauseitdoesnotsolvethesecondaryproblem,andIwouldnotwanttocaptureresizingeventfromthewindowtoadjustthesizemanually-sincethenIlosetheadvantageofusinglayouts.

Anysuggestions?

MCVECode

#include<QApplication>#include<QWidget>#include<QRadioButton>#include<QVBoxLayout>#include<QHBoxLayout>#include<QFrame>#include<QLabel>#include<QRadioButton>#include<QScrollArea>#defineSTYLE_SHEET"                               \
                    QWidget#plainArea               \
                    {                               \
                        background-color: #ffffff;  \
                        padding: 0px 0px 0px 0px;   \
                        margin: 0px 0px 0px 0px;    \
                        border-width: 0px;          \
                    }                               \
                                                    \
                    QLabel#headerTitle              \
                    {                               \
                        font-size: 25px; }          \
                    }                               \
                                                    \
                    QLabel#questionTitle            \
                    {                               \
                        font-size: 20px;            \
                    }                               \
                                                    \
                    QRadioButton#optionTitle        \
                    {                               \
                        font-size: 16px;            \
                    }                               \
                                                    \
                    QWidget#highlightedrow          \
                    {                               \
                        background-color: #efd3d2;  \
                    }                               \
                    "

QWidget* createQuestionnaire(QWidget *pParent)
{
    QWidget *pQuestionnaire = new QWidget(pParent);
    pQuestionnaire->setObjectName("plainArea");
    pQuestionnaire->setLayout(new QVBoxLayout());
    pQuestionnaire->layout()->setAlignment(Qt::AlignTop);

    // Cabeçalho
    QLabel *pTitle = new QLabel("Por favor, responda às perguntas a seguir.", pQuestionnaire);
    pTitle->setObjectName("headerTitle");
    pQuestionnaire->layout()->addWidget(pTitle);

    QFrame *pLine = new QFrame(pQuestionnaire);
    pLine->setFrameStyle(QFrame::HLine);
    pLine->setLineWidth(4);
    pQuestionnaire->layout()->addWidget(pLine);
    static_cast<QBoxLayout*>(pQuestionnaire->layout())->addSpacing(10);

    // Scroll Area
    QScrollArea *pScroll = new QScrollArea(pQuestionnaire);
    pScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    pScroll->setObjectName("plainArea");
    pScroll->setLayout(new QVBoxLayout());
    pQuestionnaire->layout()->addWidget(pScroll);

    QWidget *pArea = new QWidget(pQuestionnaire);
    pArea->setObjectName("plainArea");
    pArea->setLayout(new QVBoxLayout());
    pArea->layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);

    pScroll->setWidget(pArea);

    // Questões
    QStringList lFruits = {
        "Abacate", "Amora", "Ameixa", "Acerola", "Abacaxi", "Açaí",
        "Banana", "Bacuri", "Buriti", "Butiá", "Bacaba", "Carambola",
        "Cajá", "Caju", "Cereja", "Cacau", "Caqui", "Cupuaçu", "Damasco",
        "Figo", "Framboesa", "Fruta Pão", "Graviola", "Goiaba", "Goiaba Branca",
        "Groselha", "Guaraná", "Grumixama", "Guariroba", "Ingá", "Ibapó",
        "Itu", "Ingá Dedo", "Ingá Branco", "Jaca", "Jabuticaba", "Jambo",
        "Jenipapo", "Jatobá", "Kiwi", "Laranja", "Limão", "Lima Doce",
        "Lixia", "Melancia", "Mamão", "Melão", "Maracujá", "Manga",
        "Macadâmia", "Maçã", "Mangaba", "Mexerica", "Nectarina", "Noz",
        "Nêspera", "Olho-De-Boi", "Pera", "Pêssego", "Pitaya", "Pitanga",
        "Pinha", "Pinhão", "Pitomba", "Pocã", "Quina", "Rabutan", "Romã",
        "Sapoti", "Sapucaia", "Salok", "Saputá", "Tangerina", "Tomate",
        "Tamarindo", "Toranja", "Taiúva", "Uva", "Uxi", "Uvaia", "Umbu",
        "Veludo", "Wampi", "Xixá"
    };

    QStringList lOptions = { "detesto", "gosto pouco", "gosto", "gosto muito", "adoro" };

    for(int i = 0; i < lFruits.size(); i++)
    {
        QWidget *pRow = new QWidget(pQuestionnaire);
        pArea->layout()->addWidget(pRow);

        if(i % 2)
            pRow->setObjectName("highlightedrow");

        pRow->setLayout(new QVBoxLayout());
        QLabel *pQuestion = new QLabel(QString("%1 - Você gosta de %2?").arg(i+1).arg(lFruits.at(i)), pRow);
        pQuestion->setObjectName("questionTitle");
        pRow->layout()->addWidget(pQuestion);

        QWidget *pOptions = new QWidget(pRow);
        pRow->layout()->addWidget(pOptions);
        pOptions->setLayout(new QHBoxLayout());
        pOptions->layout()->setAlignment(Qt::AlignLeft);

        static_cast<QBoxLayout*>(pOptions->layout())->addSpacing(60);
        foreach(QString sOption, lOptions)
        {
            QRadioButton *pButton = new QRadioButton(sOption, pOptions);
            pButton->setCursor(Qt::PointingHandCursor);
            pButton->setObjectName("optionTitle");
            pOptions->layout()->addWidget(pButton);
            static_cast<QBoxLayout*>(pOptions->layout())->addSpacing(20);
        }
        static_cast<QBoxLayout*>(pOptions->layout())->addStretch(); // <--- Stretch não funciona!
    }

    return pQuestionnaire;
}

int main(int argc, char** argv)
{
    QApplication oApp(argc, argv);

    QWidget *pWindow = new QWidget();
    pWindow->setObjectName("plainArea");
    pWindow->setStyleSheet(STYLE_SHEET);
    pWindow->setWindowTitle("MCVE para o SOPT");

    pWindow->setLayout(new QVBoxLayout());
    pWindow->layout()->addWidget(createQuestionnaire(pWindow));

    pWindow->show();
    pWindow->resize(800, 600);
    return oApp.exec();
}

Q: Ah, how I hate Qt% with Qt, saw. rs

    
asked by anonymous 22.08.2016 / 21:13

1 answer

5

I've figured out how to solve both of these problems.

The main problem is that QScrollArea does not work well with an internal widget that contains child widgets arranged in layout if the scroll widget is not allowed to adjust its size automatically. To do this, just set the value of the true property to% / p>

The cool thing is that is not at all clear main description of the documentation. The documentation includes only the following:

  

The view can be made resizable with the setWidgetResizable () function.

While reading this I imagined that a resizable widget would be ... resizable and porting would not need Scroll! (after all, as the documentation example is for images, I figured they would be staggered to the viewport size instead of to display the scrollbars). But no, this property is what allows the widget to grow and shrink as it decides. Honestly, I did not understand the reason why someone needs to use this property as false and use a scrolling area, but anyway ...

For the secondary problem, it was simply easier to set the margins to 0 for all components via code with the% method of the layout class, not via style sheet.

The final code, which results in the following screen, is shown below.

Screen:

Code:

#include<QApplication>#include<QWidget>#include<QRadioButton>#include<QVBoxLayout>#include<QHBoxLayout>#include<QFrame>#include<QLabel>#include<QRadioButton>#include<QScrollArea>#defineSTYLE_SHEET"                               \
                    QWidget#plainArea               \
                    {                               \
                        background-color: #ffffff;  \
                    }                               \
                                                    \
                    QLabel#headerTitle              \
                    {                               \
                        font-size: 25px; }          \
                    }                               \
                                                    \
                    QLabel#questionTitle            \
                    {                               \
                        font-size: 20px;            \
                    }                               \
                                                    \
                    QRadioButton#optionTitle        \
                    {                               \
                        font-size: 16px;            \
                    }                               \
                                                    \
                    QWidget#highlightedrow          \
                    {                               \
                        background-color: #efd3d2;  \
                    }                               \
                    "

QWidget* createQuestionnaire(QWidget *pParent)
{
    QWidget *pQuestionnaire = new QWidget(pParent);
    pQuestionnaire->setObjectName("plainArea");
    pQuestionnaire->setLayout(new QVBoxLayout());
    pQuestionnaire->layout()->setAlignment(Qt::AlignTop);
    pQuestionnaire->layout()->setMargin(0);

    // Cabeçalho
    QLabel *pTitle = new QLabel("Por favor, responda às perguntas a seguir.", pQuestionnaire);
    pTitle->setObjectName("headerTitle");
    pQuestionnaire->layout()->addWidget(pTitle);

    QFrame *pLine = new QFrame(pQuestionnaire);
    pLine->setFrameStyle(QFrame::HLine);
    pLine->setLineWidth(4);
    pQuestionnaire->layout()->addWidget(pLine);
    static_cast<QBoxLayout*>(pQuestionnaire->layout())->addSpacing(10);

    // Scroll Area
    QScrollArea *pScroll = new QScrollArea(pQuestionnaire);
    pScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    pScroll->setObjectName("plainArea");
    pScroll->setLayout(new QVBoxLayout());
    pQuestionnaire->layout()->addWidget(pScroll);

    QWidget *pArea = new QWidget(pQuestionnaire);
    pArea->setObjectName("plainArea");
    pArea->setLayout(new QVBoxLayout());
    pArea->layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);
    pArea->layout()->setMargin(0);

    pScroll->setWidget(pArea);
    pScroll->setWidgetResizable(true);

    // Questões
    QStringList lFruits = {
        "Abacate", "Amora", "Ameixa", "Acerola", "Abacaxi", "Açaí",
        "Banana", "Bacuri", "Buriti", "Butiá", "Bacaba", "Carambola",
        "Cajá", "Caju", "Cereja", "Cacau", "Caqui", "Cupuaçu", "Damasco",
        "Figo", "Framboesa", "Fruta Pão", "Graviola", "Goiaba", "Goiaba Branca",
        "Groselha", "Guaraná", "Grumixama", "Guariroba", "Ingá", "Ibapó",
        "Itu", "Ingá Dedo", "Ingá Branco", "Jaca", "Jabuticaba", "Jambo",
        "Jenipapo", "Jatobá", "Kiwi", "Laranja", "Limão", "Lima Doce",
        "Lixia", "Melancia", "Mamão", "Melão", "Maracujá", "Manga",
        "Macadâmia", "Maçã", "Mangaba", "Mexerica", "Nectarina", "Noz",
        "Nêspera", "Olho-De-Boi", "Pera", "Pêssego", "Pitaya", "Pitanga",
        "Pinha", "Pinhão", "Pitomba", "Pocã", "Quina", "Rabutan", "Romã",
        "Sapoti", "Sapucaia", "Salok", "Saputá", "Tangerina", "Tomate",
        "Tamarindo", "Toranja", "Taiúva", "Uva", "Uxi", "Uvaia", "Umbu",
        "Veludo", "Wampi", "Xixá"
    };

    QStringList lOptions = { "detesto", "gosto pouco", "gosto", "gosto muito", "adoro" };

    for(int i = 0; i < lFruits.size(); i++)
    {
        QWidget *pRow = new QWidget(pQuestionnaire);
        pArea->layout()->addWidget(pRow);

        if(i % 2)
            pRow->setObjectName("highlightedrow");

        pRow->setLayout(new QVBoxLayout());
        QLabel *pQuestion = new QLabel(QString("%1 - Você gosta de %2?").arg(i+1).arg(lFruits.at(i)), pRow);
        pQuestion->setObjectName("questionTitle");
        pRow->layout()->addWidget(pQuestion);

        QWidget *pOptions = new QWidget(pRow);
        pRow->layout()->addWidget(pOptions);
        pOptions->setLayout(new QHBoxLayout());
        pOptions->layout()->setAlignment(Qt::AlignLeft);

        static_cast<QBoxLayout*>(pOptions->layout())->addSpacing(60);
        foreach(QString sOption, lOptions)
        {
            QRadioButton *pButton = new QRadioButton(sOption, pOptions);
            pButton->setCursor(Qt::PointingHandCursor);
            pButton->setObjectName("optionTitle");
            pOptions->layout()->addWidget(pButton);
            static_cast<QBoxLayout*>(pOptions->layout())->addSpacing(20);
        }
    }

    return pQuestionnaire;
}

int main(int argc, char** argv)
{
    QApplication oApp(argc, argv);

    QWidget *pWindow = new QWidget();
    pWindow->setObjectName("plainArea");
    pWindow->setStyleSheet(STYLE_SHEET);
    pWindow->setWindowTitle("MCVE para o SOPT");

    pWindow->setLayout(new QVBoxLayout());
    pWindow->layout()->addWidget(createQuestionnaire(pWindow));
    pWindow->layout()->setMargin(0);

    pWindow->show();
    pWindow->resize(800, 600);
    return oApp.exec();
}
    
22.08.2016 / 23:13