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?
Forum Updated to NodeBB v4.3 + New Features

How to update entire window on change in QProxyStyle?

Scheduled Pinned Locked Moved Unsolved General and Desktop
qproxystyleqpushbuttonqwidgetpainting issues
16 Posts 3 Posters 1.9k Views 3 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.
  • 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 Online
                                Christian EhrlicherC Online
                                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

                                  10/16

                                  19 Oct 2021, 15:34

                                  • Login

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