Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt Widgets Alignment
Forum Updated to NodeBB v4.3 + New Features

Qt Widgets Alignment

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 4 Posters 586 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SWest
    wrote on last edited by
    #1

    Hi. I have a question about widgets and layout alignment.
    I have a QDialog, where I put one external Widget, containing QLabel and QLineEdit.
    Next I want to put my own Widget and align it to QLineEdit inside external Widget.
    I added picture, where you can see imaginary green alignment line.
    6b2230a4-2789-4855-b349-59a27ef66ec7-image.png
    So the code without layouts is like this:

    #include <QDialog>
    #include <QCheckBox>
    #include "ExternalWidget.h"
    public MyDialog : QDialog { 
    public:
    MyDialog() {
      auto *external = new ExternalWidget(); // widget with QLabel and QLineEdit
      auto *myWidget = new QCheckBox();
    // how to align myWidget by second widget in external?
    }
    }
    

    Using QFormLayout didn't work out, but may be I'm missing something.
    Please help, thank you.

    Pl45m4P 1 Reply Last reply
    0
    • B Offline
      B Offline
      Bonnie
      wrote on last edited by Bonnie
      #6

      Well I think you have to monitor the size change of the label. So consider using event filter, but that will require you to save the pointers as member variables.
      Here's what I've tried:

      MyDialog() {
         ...
          label->installEventFilter(this);
          auto margins = hBox->contentsMargins();
          margins.setLeft(external->layout()->contentsMargins().left());
          // make hBox's left margin the same as external's layout
          hBox->setContentsMargins(margins);
          // also try to make hBox having the spacing, but somehow seem not working, still need to add the spacing value in eventFilter
          hBox->setSpacing(external->layout()->spacing());
      }
      protected:
      bool eventFilter(QObject *watched, QEvent *event) {
          if(event->type() == QEvent::Resize && watched == label) {
              QResizeEvent* re = (QResizeEvent*)event;
              spacer->changeSize(re->size().width() + external->layout()->spacing(), 0, QSizePolicy::Fixed, QSizePolicy::Ignored);
          }
          return QDialog::eventFilter(obj, event);
      }
      

      Or don't use a spacer, just set the hBox's left margin:

      MyDialog() {
         ...
          label->installEventFilter(this);
      }
      protected:
      bool eventFilter(QObject *watched, QEvent *event) {
          if(event->type() == QEvent::Resize && watched == label) {
              QResizeEvent* re = (QResizeEvent*)event;
              auto margins = hBox->contentsMargins();
              margins.setLeft(external->layout()->contentsMargins().left() + re->size().width() + external->layout()->spacing());
              hBox->setContentsMargins(margins);
          }
          return QDialog::eventFilter(obj, event);
      }
      

      I also tried only adding myWidget without a QHBoxLayout, but it seems that contentsMargins is not working on QCheckBox.

      1 Reply Last reply
      1
      • S SWest

        Hi. I have a question about widgets and layout alignment.
        I have a QDialog, where I put one external Widget, containing QLabel and QLineEdit.
        Next I want to put my own Widget and align it to QLineEdit inside external Widget.
        I added picture, where you can see imaginary green alignment line.
        6b2230a4-2789-4855-b349-59a27ef66ec7-image.png
        So the code without layouts is like this:

        #include <QDialog>
        #include <QCheckBox>
        #include "ExternalWidget.h"
        public MyDialog : QDialog { 
        public:
        MyDialog() {
          auto *external = new ExternalWidget(); // widget with QLabel and QLineEdit
          auto *myWidget = new QCheckBox();
        // how to align myWidget by second widget in external?
        }
        }
        

        Using QFormLayout didn't work out, but may be I'm missing something.
        Please help, thank you.

        Pl45m4P Offline
        Pl45m4P Offline
        Pl45m4
        wrote on last edited by Pl45m4
        #2

        Hi and welcome to the forum :)

        @SWest said in Qt Widgets Alignment:

        Next I want to put my own Widget and align it to QLineEdit inside external Widget.
        I added picture, where you can see imaginary green alignment line.

        The line is not straight :))
        (but I think it's clear what you mean)

        It's not that easy, because your ExternalWidget has margins and the layout items of ExternalWidget's own layout are treated different from these which are one layer above them (your QCheckBox a.k.a myWidget)

        From the top of my head:
        You can try to put everything in a vertical (QVBoxLayout) layout and then let your myWidget only populate half of the row.
        Or you can place myWidget in a layout with a spacer to which you assign the same sizePolicy as the label in ExernalWidget and then check the result.

        Maybe there's an even easier way I cannot think about right now


        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

        ~E. W. Dijkstra

        1 Reply Last reply
        2
        • S Offline
          S Offline
          SWest
          wrote on last edited by SWest
          #3

          @Pl45m4
          Thank you very much for your answer.
          First suggestion with half of the row is not suitable in my case.
          But second with spacer is interesting. I tried to add spacer as in the following code:

          MyDialog() {
             auto *main = new QVBoxLayout(this);
             auto *external = new ExternalWidget();
             main->addWidget(external);
             auto *hBox = new QHBoxLayout();
             main->addLayout(hBox);
             QLabel *label = external->label(); // let's assume this method exists
             QSizePolicy labelPolicy = label->sizePolicy();
             auto *spacer = new QSpacerItem(label->width(), label->height(), labelPolicy.horizontalPolicy(), labelPolicy.verticalPolicy());
             hBox->addItem(spacer);
             auto *myWidget = new QCheckBox();
             hBox->addWidget(myWidget);
          }
          

          But it didn't work accurate. It aligned with some spacing before myWidget. Also it expanded dialog, but this is not important.
          f779742a-2769-4b71-8d55-e5ae96ae9dc1-image.png
          May be I did something incorrectly?
          Also I tried to:

             hBox->setSpacing(0);
             int spacing = externalWidget->layout()->spacing();
             auto *spacer = new QSpacerItem(label->width() - spacing, label->height(), labelPolicy.horizontalPolicy(), labelPolicy.verticalPolicy());
          

          It somehow changed nothing

          JonBJ 1 Reply Last reply
          0
          • S SWest

            @Pl45m4
            Thank you very much for your answer.
            First suggestion with half of the row is not suitable in my case.
            But second with spacer is interesting. I tried to add spacer as in the following code:

            MyDialog() {
               auto *main = new QVBoxLayout(this);
               auto *external = new ExternalWidget();
               main->addWidget(external);
               auto *hBox = new QHBoxLayout();
               main->addLayout(hBox);
               QLabel *label = external->label(); // let's assume this method exists
               QSizePolicy labelPolicy = label->sizePolicy();
               auto *spacer = new QSpacerItem(label->width(), label->height(), labelPolicy.horizontalPolicy(), labelPolicy.verticalPolicy());
               hBox->addItem(spacer);
               auto *myWidget = new QCheckBox();
               hBox->addWidget(myWidget);
            }
            

            But it didn't work accurate. It aligned with some spacing before myWidget. Also it expanded dialog, but this is not important.
            f779742a-2769-4b71-8d55-e5ae96ae9dc1-image.png
            May be I did something incorrectly?
            Also I tried to:

               hBox->setSpacing(0);
               int spacing = externalWidget->layout()->spacing();
               auto *spacer = new QSpacerItem(label->width() - spacing, label->height(), labelPolicy.horizontalPolicy(), labelPolicy.verticalPolicy());
            

            It somehow changed nothing

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #4

            @SWest
            I presume you are aware it will always be tricky to align robustly because you want to treat the label and widget separately for your purpose while it is supplied to you as a single composite widget holding both of these in a layout, which really is not designed for you to do what you want here. If you could handle them separately, or even (entirely depending on what the implementation of that widget does) pull out the label and lineedit from it and place them yourself it would be much easier to align.

            S 1 Reply Last reply
            0
            • JonBJ JonB

              @SWest
              I presume you are aware it will always be tricky to align robustly because you want to treat the label and widget separately for your purpose while it is supplied to you as a single composite widget holding both of these in a layout, which really is not designed for you to do what you want here. If you could handle them separately, or even (entirely depending on what the implementation of that widget does) pull out the label and lineedit from it and place them yourself it would be much easier to align.

              S Offline
              S Offline
              SWest
              wrote on last edited by
              #5

              @JonB Yes, it's tricky, I agree with this. I'm here to just see some new good ideas. Unfortunately I can't take them out of External Widget, because they should not be reparented.

              1 Reply Last reply
              0
              • B Offline
                B Offline
                Bonnie
                wrote on last edited by Bonnie
                #6

                Well I think you have to monitor the size change of the label. So consider using event filter, but that will require you to save the pointers as member variables.
                Here's what I've tried:

                MyDialog() {
                   ...
                    label->installEventFilter(this);
                    auto margins = hBox->contentsMargins();
                    margins.setLeft(external->layout()->contentsMargins().left());
                    // make hBox's left margin the same as external's layout
                    hBox->setContentsMargins(margins);
                    // also try to make hBox having the spacing, but somehow seem not working, still need to add the spacing value in eventFilter
                    hBox->setSpacing(external->layout()->spacing());
                }
                protected:
                bool eventFilter(QObject *watched, QEvent *event) {
                    if(event->type() == QEvent::Resize && watched == label) {
                        QResizeEvent* re = (QResizeEvent*)event;
                        spacer->changeSize(re->size().width() + external->layout()->spacing(), 0, QSizePolicy::Fixed, QSizePolicy::Ignored);
                    }
                    return QDialog::eventFilter(obj, event);
                }
                

                Or don't use a spacer, just set the hBox's left margin:

                MyDialog() {
                   ...
                    label->installEventFilter(this);
                }
                protected:
                bool eventFilter(QObject *watched, QEvent *event) {
                    if(event->type() == QEvent::Resize && watched == label) {
                        QResizeEvent* re = (QResizeEvent*)event;
                        auto margins = hBox->contentsMargins();
                        margins.setLeft(external->layout()->contentsMargins().left() + re->size().width() + external->layout()->spacing());
                        hBox->setContentsMargins(margins);
                    }
                    return QDialog::eventFilter(obj, event);
                }
                

                I also tried only adding myWidget without a QHBoxLayout, but it seems that contentsMargins is not working on QCheckBox.

                1 Reply Last reply
                1
                • S Offline
                  S Offline
                  SWest
                  wrote on last edited by
                  #7

                  @Bonnie Thank you.
                  This code actually do what I need

                  B 1 Reply Last reply
                  0
                  • S SWest has marked this topic as solved on
                  • S SWest

                    @Bonnie Thank you.
                    This code actually do what I need

                    B Offline
                    B Offline
                    Bonnie
                    wrote on last edited by Bonnie
                    #8

                    @SWest It just occured to me that monitoring the lineEdit's move event would be easier, no need to add left margin, width and spacing any more. (If you can also get the pointer of the lineEdit, and it needs to be the direct child widget of the external widget.)

                    MyDialog() {
                       ...
                        external->lineEdit()->installEventFilter(this);
                    }
                    protected:
                    bool eventFilter(QObject *watched, QEvent *event) {
                        if(event->type() == QEvent::Move && watched == external->lineEdit()) {
                            QMoveEvent* me = (QMoveEvent*)event;
                            auto margins = hBox->contentsMargins();
                            margins.setLeft(me->pos().x());
                            hBox->setContentsMargins(margins);
                        }
                        return QDialog::eventFilter(obj, event);
                    }
                    
                    1 Reply Last reply
                    1

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved