Fixed width inside a QVBoxLayout?



    1. I have a VBoxLayout.
    2. I add a number of QPushButtons, with varying length text, onto it.
    3. At present that gives me varying width buttons.
    4. I would like them all to be the same width.
    5. I would like to achieve this with "minimal code", e.g. I'd prefer not to have to do anything to each button.

    So, can I set something on the VBoxLayout which would cause the buttons to expand to its width? (I'd be prepared to add a VBoxFrame, if that would make any difference.) I'd like the container to tell the button contents to all expand to same width.

    [I think I can see this achieved on other pages in the 32K-lines of code I've inherited, but it gets so complicated to figure how they are achieving it but this page is not.]



  • This is very strange. if you don't insert spacers or hand code the maximum size of the button this shouldn't be possible.

    You could try the below but I doubt it will work.
    Can you show a snippet of how you add those buttons to the layout?
    are you calling QPushButton::setMaximumSize or QPushButton::setMaximumWidth?

    for(int i=0;i<layout->count();++i){
    QWidget* const currWid = layout->itemAt(i)->widget();
    if(!currWid) continue;
    currWid->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
    }
    


  • @JonB said in Fixed width inside a QVBoxLayout?:

    but it gets so complicated to figure how they are achieving it

    Simple snippet that shows it working

    #include <QApplication>
    #include <QWidget>
    #include <QVBoxLayout>
    #include <QPushButton>
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget mainWid;
        QVBoxLayout* mainLay=new QVBoxLayout(&mainWid);
        for(int i=0;i<5;++i){
            const QString randomString((rand()%20)+1,QChar('a'));
            QPushButton* button =new QPushButton(randomString,&mainWid);
            mainLay->addWidget(button);
        }
        mainWid.show();
        return a.exec();
    
    }
    


  • @VRonin
    I will have to investigate the exact code. Trouble is, there's loads on the pages that don't work, and loads on the pages that do!

    No calls to set size at all.

    Your suggestion(?) of code is exactly what I would like not to do, as it makes a call of setSizePolicy() on each widget/button. I am hoping I can set something on the container only, and the child widgets will expand to fit.

    [EDIT: @VRonin So, you are stating that the default(?) behaviour of a QPushButton placed on a QVBoxLayout is already that it should expand width to size of QVBoxLayout, rather than adopt (minimum) width corresponding to button's text? Please make that clear to me, one way or the other, thanks.]



  • @JonB said in Fixed width inside a QVBoxLayout?:

    So, you are stating that the default(?) behaviour of a QPushButton placed on a QVBoxLayout is already that it should expand width to size of QVBoxLayout, rather than adopt (minimum) width corresponding to button's text?

    Yes indeed. and not just QPushButton, any widget. It's actually very hard to achieve the opposite



  • @VRonin
    I will have to investigate this and get back to you, perhaps tomorrow.

    But I'm still "surprised" at what you say is default behaviour. In a VBoxLayout, I thought that meant Qt lays out each child widget that is added vertically one after the other, but not that it would stretch the widget horizontally to width while doing so. Is that indeed the case? (Well I guess it is because you're saying so, but just seeking to confirm, because I assumed child widgets would only take up their own horizontal width...)



  • @JonB said in Fixed width inside a QVBoxLayout?:

    Is that indeed the case?

    Yes. Proof in the source

     case TopToBottom:
                    box->item->setGeometry(QRect(s.x(), a.at(i).pos, s.width(), a.at(i).size));
    break;
    

    the s.width() sets the width of every item in the layout to the width of the layout (minus the margins)



  • @VRonin
    Well, today is Thursday, and it does indeed now set the widths of all child widgets to the same as one another. Yesterday I had them only taking up their own individual widths. Does Qt source code have a check for day-of-week for its behaviour?

    I have learnt that QVBoxLayout's child widgets are stretched to fill the width.
    You wrote:

    It's actually very hard to achieve the opposite

    If elsewhere I do want that behaviour --- use the QVBoxLayout to arrange children vertically but have each child only take up its natural width --- how would I achieve that then? Use a QHBoxLayout for each one??

    I'm also struggling to understand whether there is "consistency" in the handling of children of QHBoxLayout versus QVBoxLayout. If QVBoxLayout "widens" children to match widest, why is it that (if I, say, make one button's text multi-line vertical or I use setMinimumHeight()) QHboxLayout does not "heighten" other children to match??



  • @JonB said in Fixed width inside a QVBoxLayout?:

    Does Qt source code have a check for day-of-week for its behaviour?

    LOL

    Use a QHBoxLayout for each one?

    Yes but not only. you also have to add a spacer (layout->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Preferred)); or layout->addStretch()) to the left, right or both (depending how you want it aligned)

    I'm also struggling to understand whether there is "consistency" in the handling of children of QHBoxLayout versus QVBoxLayout.

    They are the exact same class basically. The only difference is a small internal variable that tells them the direction of the layout, the real code is in their base class QBoxLayout

    if I, say, make one button's text multi-line vertical or I use setMinimumHeight() QHboxLayout does not "heighten" other children to match??

    That's because of QPushButton's size policy being QSizePolicy::Fixed for the height. Just add button->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); to make it expand



  • @VRonin

    1. Yes but not only. you also have to add a spacer

    Ah ha! Thanks. Very useful.

    1. That's because of QPushButton's size policy being QSizePolicy::Fixed for the height.

    Ah ha, again! That would also answer a question I was about to ask: why is it that QPushButton::setMaximumHeight() causes button to occupy maximum height when it does not need it?

    Now then: Looking at the docs I see no mention that a QPushButton/QAbstractButton etc. has such a size policy. And I program in Python, so I have no desire to download Qt's source code or flip between Python/C++ IDEs to examine it all the time. So now I'm wondering: how many other widget types have undocumented QSizePolicys? I was spending ages trying to understand that QPushButton behaviour.... :(

    P.S.
    I'm about to start a separate thread on setting sizes & QCSS. I hope you'll look at that too, as your answers are always prompt & correct!



  • @JonB said in Fixed width inside a QVBoxLayout?:

    I have no desire to download Qt's source code or flip between Python/C++ IDEs to examine it all the time

    That's why I find https://code.woboq.org/qt5/ so convenient

    how many other widget types have undocumented QSizePolicys?

    All of them I think. they use the size policy that achieves the more natural behaviour (i.e. the one that most apps adopt)



  • @VRonin
    I take your point about being able to view Qt source on-line, and have bookmarked your link, thank you.

    The issue really is that potentially I need to look at the source code in addition to the documentation every time I want to use anything from Qt in case there is important undocumented behaviour like this. I feel it would be helpful if the docs decided to mention what non-default sizing each widget uses. But at least I know where I am in this case.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.