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. How to update entire window on change in QProxyStyle?
QtWS25 Last Chance

How to update entire window on change in QProxyStyle?

Scheduled Pinned Locked Moved Unsolved General and Desktop
qproxystyleqpushbuttonqwidgetpainting issues
16 Posts 3 Posters 1.7k Views
  • 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.
  • C Offline
    C Offline
    CJha
    wrote on 19 Oct 2021, 13:34 last edited by CJha
    #1

    When the QPushButton has a long text it looks something like this:
    ButtonWithLongText.PNG
    and what I wanted it to look like is this:
    ButtonWithLongText2.PNG

    To achieve this, I subclassed QProxyStyle and reimplemented the sizeFromContents() function. To test this new method I created a new project, with the UI in preview mode:

    DemoUI.PNG
    Where the spinbox name is btnBorder_spin, button with text "Button 1: 0" has an object name btn_1 and button with text "Button 2: 0" has object name btn_2, button with text "Button 3: Demo" has object name btn_3.

    the mainwindow.h

    inline int minBtnBorder{10};
    
    class ProxyStyle : public QProxyStyle
    {
    public:
        QSize sizeFromContents(ContentsType ct, const QStyleOption* opt, const QSize& csz, const QWidget* widget = 0) const
        {
            QSize sz = QProxyStyle::sizeFromContents(ct, opt, csz, widget);
    	if(ct == CT_PushButton) {
    	    const auto optionPtr = qstyleoption_cast<const QStyleOptionButton*>(opt);
    	    QStyleOptionButton customOption = *optionPtr;
    	    auto btn = qobject_cast<QPushButton*>(customOption.styleObject);
    	    if(!btn->text().isEmpty()) {
    	        QFontMetrics fm = opt->fontMetrics;
    		int strWidth = fm.boundingRect(btn->text()).width();
    		int diffBtnWidth = sz.rwidth() - strWidth;
    		if(diffBtnWidth < (2 * minBtnBorder))
    			sz.rwidth() = strWidth + (2 * minBtnBorder);
    		}
    	}
    	return sz;
        }
    };
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = Q_NULLPTR);
    
    private:
        Ui::MainWindowClass UI;
        int btnCount_1{0};
        int btnCount_2{0};
    
    protected:
        void showEvent(QShowEvent* event) override;
    
    private slots:
        void on_btnBorder_spin_valueChanged(int val);
        void on_btn_1_clicked();
        void on_btn_2_clicked();
        void on_btn_3_clicked();
    };
    

    and mainwindow.cpp

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        auto proxyStyle = new ProxyStyle;
        proxyStyle->setBaseStyle(QStyleFactory::create("Fusion"));
        qApp->setStyle(proxyStyle);
        qApp->setFont(QFont("Verdana", 10));
        ui.setupUi(this);
    }
    
    void MainWindow::showEvent(QShowEvent* event)
    {
        setFixedSize(this->layout()->minimumSize());
    }
    
    void MainWindow::on_btnBorder_spin_valueChanged(int val)
    {
        minBtnBorder = val;
        update();
    }
    
    void MainWindow::on_btn_1_clicked()
    {
        ++btnCount_1;
        ui.btn_1->setText(QString("Button 1: ").append(QString::number(btnCount_1)));
    }
    
    void MainWindow::on_btn_2_clicked()
    {
        ++btnCount_2;
        ui.btn_2->setText(QString("Button 2: ").append(QString::number(btnCount_2)));
    }
    
    void MainWindow::on_btn_3_clicked()
    {
        qDebug() << "Button 3 Clicked";
    }
    

    Each time btn_1 is clicked btnCount_1 is incremented and the text on the button is changed, same thing happens with btn_2. When the value of btnBorder_spin is changed the minBtnBorder global variable is set to the new value and a call to update is issued. When btn_3 is clicked only a debug message saying "Button 3 Clicked" is generated.

    When I run my code, the window appears normally and I see a border of around 10 px on the sides of the button:

    Running_1.PNG

    If I change the value in the spinbox to 100 px then nothing changes:

    Running_2.PNG

    Now if I click on btn_1 then it changes the size of btn_1 accordingly while btn_2 and btn_3 remains fixed at the same previous size:

    Running_3.PNG

    Only if I click on btn_2 then its size also changes:

    Running_4.PNG

    Clicking on btn_3 prints the debug output, but its size never changes.

    I tried using update() , repaint(), hide() then show() after the value of minBtnBorder is changed but the new value is never visible immediately. It is only visible after I change the text on a button, and the change is only applied to the button whose text has changed. How can I make the changes appear immediately after I change the value of minBtnBorder for all buttons?

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 19 Oct 2021, 14:02 last edited by
      #2

      Hi
      It might be due being in a layout ?
      Did you try calling updateGeometry() on the buttons ?

      C 1 Reply Last reply 19 Oct 2021, 14:06
      0
      • M mrjj
        19 Oct 2021, 14:02

        Hi
        It might be due being in a layout ?
        Did you try calling updateGeometry() on the buttons ?

        C Offline
        C Offline
        CJha
        wrote on 19 Oct 2021, 14:06 last edited by
        #3

        @mrjj Hi, I did just now but it doesn't work.

        void MainWindow::on_btnBorder_spin_valueChanged(int val)
        {
            minBtnBorder = val;
            ui.btn_1->updateGeometry();
            ui.btn_2->updateGeometry();
            ui.btn_3->updateGeometry();
            update();
        }
        
        M 1 Reply Last reply 19 Oct 2021, 14:10
        0
        • C CJha
          19 Oct 2021, 14:06

          @mrjj Hi, I did just now but it doesn't work.

          void MainWindow::on_btnBorder_spin_valueChanged(int val)
          {
              minBtnBorder = val;
              ui.btn_1->updateGeometry();
              ui.btn_2->updateGeometry();
              ui.btn_3->updateGeometry();
              update();
          }
          
          M Offline
          M Offline
          mrjj
          Lifetime Qt Champion
          wrote on 19 Oct 2021, 14:10 last edited by
          #4

          @CJha

          Hi
          Ok. that is odd since it will resize when clicked. updateGeometry() should make layout recalc.

          Is the proxy complete so I can just add 3 buttons to a layout and see myself ?

          C 1 Reply Last reply 19 Oct 2021, 14:11
          0
          • M mrjj
            19 Oct 2021, 14:10

            @CJha

            Hi
            Ok. that is odd since it will resize when clicked. updateGeometry() should make layout recalc.

            Is the proxy complete so I can just add 3 buttons to a layout and see myself ?

            C Offline
            C Offline
            CJha
            wrote on 19 Oct 2021, 14:11 last edited by
            #5

            @mrjj Yes, it is complete. You just have to include the relevant files.

            M 1 Reply Last reply 19 Oct 2021, 15:19
            1
            • C CJha
              19 Oct 2021, 14:11

              @mrjj Yes, it is complete. You just have to include the relevant files.

              M Offline
              M Offline
              mrjj
              Lifetime Qt Champion
              wrote on 19 Oct 2021, 15:19 last edited by
              #6

              @CJha

              hi
              I cannot make it scale/update at all.

              What type of layout did you use ?

              C 1 Reply Last reply 19 Oct 2021, 15:25
              0
              • M mrjj
                19 Oct 2021, 15:19

                @CJha

                hi
                I cannot make it scale/update at all.

                What type of layout did you use ?

                C Offline
                C Offline
                CJha
                wrote on 19 Oct 2021, 15:25 last edited by CJha
                #7

                @mrjj Hi, that is strange. I used a normal layout in Qt Designer. Here is an image:

                LayoutReq.PNG

                I didn't change anything about the layout, I just put it there and that is all.

                M 1 Reply Last reply 19 Oct 2021, 15:30
                0
                • C CJha
                  19 Oct 2021, 15:25

                  @mrjj Hi, that is strange. I used a normal layout in Qt Designer. Here is an image:

                  LayoutReq.PNG

                  I didn't change anything about the layout, I just put it there and that is all.

                  M Offline
                  M Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on 19 Oct 2021, 15:30 last edited by mrjj
                  #8

                  @CJha
                  and buttons have default sizePolizy ?

                  Could you post the UI file content ?

                  M C 2 Replies Last reply 19 Oct 2021, 15:34
                  0
                  • M mrjj
                    19 Oct 2021, 15:30

                    @CJha
                    and buttons have default sizePolizy ?

                    Could you post the UI file content ?

                    M Offline
                    M Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on 19 Oct 2021, 15:34 last edited by
                    #9

                    @mrjj

                    Ok, got it now.

                    C 1 Reply Last reply 19 Oct 2021, 15:38
                    1
                    • M mrjj
                      19 Oct 2021, 15:30

                      @CJha
                      and buttons have default sizePolizy ?

                      Could you post the UI file content ?

                      C Offline
                      C Offline
                      CJha
                      wrote on 19 Oct 2021, 15:34 last edited by
                      #10

                      @mrjj Yes, the sizePolicy, min and max size, etc is all default. All I did was change the text on the buttons.

                      Here is the UI file content:

                      /********************************************************************************
                      ** Form generated from reading UI file 'mainwindowggYFGS.ui'
                      **
                      ** Created by: Qt User Interface Compiler version 5.15.2
                      **
                      ** WARNING! All changes made in this file will be lost when recompiling UI file!
                      ********************************************************************************/
                      
                      #ifndef MAINWINDOWGGYFGS_H
                      #define MAINWINDOWGGYFGS_H
                      
                      #include <QtCore/QVariant>
                      #include <QtWidgets/QApplication>
                      #include <QtWidgets/QHBoxLayout>
                      #include <QtWidgets/QLabel>
                      #include <QtWidgets/QMainWindow>
                      #include <QtWidgets/QPushButton>
                      #include <QtWidgets/QSpacerItem>
                      #include <QtWidgets/QSpinBox>
                      #include <QtWidgets/QVBoxLayout>
                      #include <QtWidgets/QWidget>
                      
                      QT_BEGIN_NAMESPACE
                      
                      class Ui_MainWindowClass
                      {
                      public:
                          QWidget *centralWidget;
                          QVBoxLayout *verticalLayout;
                          QHBoxLayout *horizontalLayout;
                          QLabel *label;
                          QSpinBox *btnBorder_spin;
                          QSpacerItem *horizontalSpacer;
                          QHBoxLayout *horizontalLayout_2;
                          QPushButton *btn_1;
                          QSpacerItem *horizontalSpacer_2;
                          QPushButton *btn_2;
                          QSpacerItem *horizontalSpacer_3;
                          QPushButton *btn_3;
                      
                          void setupUi(QMainWindow *MainWindowClass)
                          {
                              if (MainWindowClass->objectName().isEmpty())
                                  MainWindowClass->setObjectName(QString::fromUtf8("MainWindowClass"));
                              MainWindowClass->resize(311, 73);
                              centralWidget = new QWidget(MainWindowClass);
                              centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
                              verticalLayout = new QVBoxLayout(centralWidget);
                              verticalLayout->setSpacing(6);
                              verticalLayout->setContentsMargins(11, 11, 11, 11);
                              verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
                              horizontalLayout = new QHBoxLayout();
                              horizontalLayout->setSpacing(6);
                              horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
                              label = new QLabel(centralWidget);
                              label->setObjectName(QString::fromUtf8("label"));
                      
                              horizontalLayout->addWidget(label);
                      
                              btnBorder_spin = new QSpinBox(centralWidget);
                              btnBorder_spin->setObjectName(QString::fromUtf8("btnBorder_spin"));
                              btnBorder_spin->setMaximum(999);
                              btnBorder_spin->setValue(10);
                      
                              horizontalLayout->addWidget(btnBorder_spin);
                      
                              horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
                      
                              horizontalLayout->addItem(horizontalSpacer);
                      
                      
                              verticalLayout->addLayout(horizontalLayout);
                      
                              horizontalLayout_2 = new QHBoxLayout();
                              horizontalLayout_2->setSpacing(6);
                              horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
                              btn_1 = new QPushButton(centralWidget);
                              btn_1->setObjectName(QString::fromUtf8("btn_1"));
                      
                              horizontalLayout_2->addWidget(btn_1);
                      
                              horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
                      
                              horizontalLayout_2->addItem(horizontalSpacer_2);
                      
                              btn_2 = new QPushButton(centralWidget);
                              btn_2->setObjectName(QString::fromUtf8("btn_2"));
                      
                              horizontalLayout_2->addWidget(btn_2);
                      
                              horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
                      
                              horizontalLayout_2->addItem(horizontalSpacer_3);
                      
                              btn_3 = new QPushButton(centralWidget);
                              btn_3->setObjectName(QString::fromUtf8("btn_3"));
                      
                              horizontalLayout_2->addWidget(btn_3);
                      
                      
                              verticalLayout->addLayout(horizontalLayout_2);
                      
                              MainWindowClass->setCentralWidget(centralWidget);
                      
                              retranslateUi(MainWindowClass);
                      
                              QMetaObject::connectSlotsByName(MainWindowClass);
                          } // setupUi
                      
                          void retranslateUi(QMainWindow *MainWindowClass)
                          {
                              MainWindowClass->setWindowTitle(QCoreApplication::translate("MainWindowClass", "MainWindow", nullptr));
                              label->setText(QCoreApplication::translate("MainWindowClass", "Button Side Borders:", nullptr));
                              btnBorder_spin->setSuffix(QCoreApplication::translate("MainWindowClass", " px", nullptr));
                              btn_1->setText(QCoreApplication::translate("MainWindowClass", "Button 1: 0", nullptr));
                              btn_2->setText(QCoreApplication::translate("MainWindowClass", "Button 2: 0", nullptr));
                              btn_3->setText(QCoreApplication::translate("MainWindowClass", "Button 3: Demo", nullptr));
                          } // retranslateUi
                      
                      };
                      
                      namespace Ui {
                          class MainWindowClass: public Ui_MainWindowClass {};
                      } // namespace Ui
                      
                      QT_END_NAMESPACE
                      
                      #endif // MAINWINDOWGGYFGS_H
                      
                      1 Reply Last reply
                      1
                      • M mrjj
                        19 Oct 2021, 15:34

                        @mrjj

                        Ok, got it now.

                        C Offline
                        C Offline
                        CJha
                        wrote on 19 Oct 2021, 15:38 last edited by
                        #11

                        @mrjj I found a way around, by recreating a new ProxyStyle object each time the value of minBtnBorder is changed and then applying this to the qApp.

                        void MainWindow::on_btnBorder_spin_valueChanged(int val)
                        {
                           minBtnBorder = val;
                           auto proxyStyle = new ProxyStyle;
                           proxyStyle->setBaseStyle(QStyleFactory::create("Fusion"));
                           qApp->setStyle(proxyStyle);
                           hide();
                           show();
                        }
                        

                        It is a workaround at best though.

                        M 1 Reply Last reply 19 Oct 2021, 15:43
                        1
                        • C CJha
                          19 Oct 2021, 15:38

                          @mrjj I found a way around, by recreating a new ProxyStyle object each time the value of minBtnBorder is changed and then applying this to the qApp.

                          void MainWindow::on_btnBorder_spin_valueChanged(int val)
                          {
                             minBtnBorder = val;
                             auto proxyStyle = new ProxyStyle;
                             proxyStyle->setBaseStyle(QStyleFactory::create("Fusion"));
                             qApp->setStyle(proxyStyle);
                             hide();
                             show();
                          }
                          

                          It is a workaround at best though.

                          M Offline
                          M Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on 19 Oct 2021, 15:43 last edited by
                          #12

                          @CJha
                          Good. at least we have a "fix"

                          The odd thing is that setText

                          void QAbstractButton::setText(const QString &text)
                          {
                              Q_D(QAbstractButton);
                              if (d->text == text)
                                  return;
                              d->text = text;
                          #ifndef QT_NO_SHORTCUT
                              QKeySequence newMnemonic = QKeySequence::mnemonic(text);
                              setShortcut(newMnemonic);
                          #endif
                              d->sizeHint = QSize();
                              update();
                              updateGeometry();
                          #ifndef QT_NO_ACCESSIBILITY
                              QAccessibleEvent event(this, QAccessible::NameChanged);
                              QAccessible::updateAccessibility(&event);
                          #endif
                          }
                          

                          just calls
                          update();
                          updateGeometry();

                          C Christian EhrlicherC 2 Replies Last reply 19 Oct 2021, 15:50
                          1
                          • M mrjj
                            19 Oct 2021, 15:43

                            @CJha
                            Good. at least we have a "fix"

                            The odd thing is that setText

                            void QAbstractButton::setText(const QString &text)
                            {
                                Q_D(QAbstractButton);
                                if (d->text == text)
                                    return;
                                d->text = text;
                            #ifndef QT_NO_SHORTCUT
                                QKeySequence newMnemonic = QKeySequence::mnemonic(text);
                                setShortcut(newMnemonic);
                            #endif
                                d->sizeHint = QSize();
                                update();
                                updateGeometry();
                            #ifndef QT_NO_ACCESSIBILITY
                                QAccessibleEvent event(this, QAccessible::NameChanged);
                                QAccessible::updateAccessibility(&event);
                            #endif
                            }
                            

                            just calls
                            update();
                            updateGeometry();

                            C Offline
                            C Offline
                            CJha
                            wrote on 19 Oct 2021, 15:50 last edited by
                            #13

                            @mrjj Yeah, that is very odd. Maybe something else is going on in the background that we are unable to get to!? Although, the code for setText() seems complete.

                            M 1 Reply Last reply 19 Oct 2021, 15:51
                            0
                            • C CJha
                              19 Oct 2021, 15:50

                              @mrjj Yeah, that is very odd. Maybe something else is going on in the background that we are unable to get to!? Although, the code for setText() seems complete.

                              M Offline
                              M Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on 19 Oct 2021, 15:51 last edited by
                              #14

                              @CJha

                              well i think it might be related to sizeHint() but I have no proof yet :)

                              1 Reply Last reply
                              1
                              • M mrjj
                                19 Oct 2021, 15:43

                                @CJha
                                Good. at least we have a "fix"

                                The odd thing is that setText

                                void QAbstractButton::setText(const QString &text)
                                {
                                    Q_D(QAbstractButton);
                                    if (d->text == text)
                                        return;
                                    d->text = text;
                                #ifndef QT_NO_SHORTCUT
                                    QKeySequence newMnemonic = QKeySequence::mnemonic(text);
                                    setShortcut(newMnemonic);
                                #endif
                                    d->sizeHint = QSize();
                                    update();
                                    updateGeometry();
                                #ifndef QT_NO_ACCESSIBILITY
                                    QAccessibleEvent event(this, QAccessible::NameChanged);
                                    QAccessible::updateAccessibility(&event);
                                #endif
                                }
                                

                                just calls
                                update();
                                updateGeometry();

                                Christian EhrlicherC Offline
                                Christian EhrlicherC Offline
                                Christian Ehrlicher
                                Lifetime Qt Champion
                                wrote on 19 Oct 2021, 15:52 last edited by
                                #15

                                @mrjj said in How to update entire window on change in QProxyStyle?:

                                d->sizeHint = QSize();

                                I think this may be the reason. I would guess sizeFromContents() is only called when sizeHint is invalid. Simply set a breakpoint at ProxyStyle ::sizeFromContents() and take a look from where it is called (and why).

                                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                Visit the Qt Academy at https://academy.qt.io/catalog

                                M 1 Reply Last reply 19 Oct 2021, 16:56
                                3
                                • Christian EhrlicherC Christian Ehrlicher
                                  19 Oct 2021, 15:52

                                  @mrjj said in How to update entire window on change in QProxyStyle?:

                                  d->sizeHint = QSize();

                                  I think this may be the reason. I would guess sizeFromContents() is only called when sizeHint is invalid. Simply set a breakpoint at ProxyStyle ::sizeFromContents() and take a look from where it is called (and why).

                                  M Offline
                                  M Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on 19 Oct 2021, 16:56 last edited by
                                  #16

                                  @Christian-Ehrlicher
                                  Hi
                                  Seems to call it from QPushButton::sizeHint() but I failed
                                  to find way to trigger it without altering text.
                                  I guess for full disclosure the source is needed and single step :9
                                  I use wobog for it.

                                  1 Reply Last reply
                                  0

                                  1/16

                                  19 Oct 2021, 13:34

                                  • Login

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