Why isn't a QComboBox positioned correctly in a layout?
-
A
QComboBoxseems to be shifted under the neighbouring widget in a layout. The combo box is shifted1pxdown and2pxleft.Here's the code to reproduce the problem:
#include <QtGui/qpainter.h> #include <QtWidgets/qcombobox.h> #include <QtWidgets/qboxlayout.h> #include <QtWidgets/qmainwindow.h> #include <QtWidgets/qapplication.h> template <typename Base> class Rectangle : public Base { public: explicit Rectangle(QColor color) : color{color} { Base::setFixedSize(100, 20); } private: QColor color; void paintEvent(QPaintEvent *) override { QPainter{this}.fillRect(Base::rect(), color); } }; int main(int argc, char **argv) { QApplication app{argc, argv}; QMainWindow window; QWidget central; window.setCentralWidget(¢ral); QHBoxLayout layout{¢ral}; layout.setSpacing(0); layout.setContentsMargins(0, 0, 0, 0); layout.addWidget(new Rectangle<QWidget>{Qt::red}); layout.addWidget(new Rectangle<QComboBox>{Qt::blue}); window.show(); return app.exec(); }This is what I see when the blue widget is a
QComboBox:
This is what I see when the blue widget is a plain old
QWidget:
I expect both of those screenshots to be the same (but they aren't).
I'm using macOS 10.14.5 and Qt 5.12.3.
-
@Kerndog73 What do you get if you call this in Base::paintEvent()?
qDebug() << rect(); -
@Kerndog73 What do you get if you call this in Base::paintEvent()?
qDebug() << rect(); -
@Kerndog73 said in Why isn't a QComboBox positioned correctly in a layout?:
@JKSH Both the
QComboBoxand theQWidgetareQRect(0,0 100x20)Ok, their sizes are as expected.
What about
qDebug() << geometry();? -
@Kerndog73 said in Why isn't a QComboBox positioned correctly in a layout?:
@JKSH Both the
QComboBoxand theQWidgetareQRect(0,0 100x20)Ok, their sizes are as expected.
What about
qDebug() << geometry();? -
I updated to macOS 10.14.6 and the issue persists. I also found a thread about a similar issue. I might be able to use a similar solution (make the widget a little bigger and offset the painting). I'm thinking about creating a bug report but my previous bug reports have gotten no response after months so I don't think I'll bother.
-
@JKSH The
QWidgetisQRect(1,39 100x20)and theQComboBoxisQRect(99,40 100x20). I think the combo box geometry should beQRect(101,39 100x20).@Kerndog73 said in Why isn't a QComboBox positioned correctly in a layout?:
The
QWidgetisQRect(1,39 100x20)and theQComboBoxisQRect(99,40 100x20). I think the combo box geometry should beQRect(101,39 100x20)....
I'm thinking about creating a bug report but my previous bug reports have gotten no response after months so I don't think I'll bother.
You might have better luck asking in the Interest mailing list (you must subscribe first). Qt engineers are active on that list, and might be able to explain why the offset occurs.
I might be able to use a similar solution (make the widget a little bigger and offset the painting).
That sounds like a pracctical workaround
-
@Kerndog73 said in Why isn't a QComboBox positioned correctly in a layout?:
The
QWidgetisQRect(1,39 100x20)and theQComboBoxisQRect(99,40 100x20). I think the combo box geometry should beQRect(101,39 100x20)....
I'm thinking about creating a bug report but my previous bug reports have gotten no response after months so I don't think I'll bother.
You might have better luck asking in the Interest mailing list (you must subscribe first). Qt engineers are active on that list, and might be able to explain why the offset occurs.
I might be able to use a similar solution (make the widget a little bigger and offset the painting).
That sounds like a pracctical workaround
-
I think the problem is because of this piece of code from qtbase/src/plugins/styles/mac/qmacstyle_mac.mm file. Somehow they call
setLayoutItemMargins(...)function under theSE_ComboBoxLayoutItemcase statement and it breaks QComboBox's alignment in a layout. I had this problem today and I fixed it after I removed the case statement in my own custom subclass ofQMacStyle.In order to fix the problem, you have 3 options:
- Set
Qt::WA_LayoutUsesWidgetRectattribute true on the comboBox:
comboBox->setAttribute(Qt::WA_LayoutUsesWidgetRect);- Set your application style to something else, like fusion style:
QApplication::setStyle("fusion");-
Implement your own custom style class based on
QMacStyleviaQProxyStyle(which is the way I do), then reimplementsubElementRect(...)function and make sure the function returns an invalid/default constructedQRect()forSE_ComboBoxLayoutItemcase. Finally set your application style to your own custom style class. -
BONUS (pretty nasty option): As a bonus option, you can follow the "hacky" way below:
4.1. AddQT += widgets-privateto your .pro file
4.2. Insert the comboBox to the layout
4.3. CallsetLayoutItemMargins(...)function of thecomboBox#include <private/qwidget_p.h> class Hacker : public QWidget { public: Q_DECLARE_PRIVATE(QWidget) }; reinterpret_cast<Hacker*>(comboBox)->d_func()->setLayoutItemMargins(0, 0, 0, 0); // Might be an undefined behavior based on C++ standards
- Set