Why isn't a QComboBox positioned correctly in a layout?
-
A
QComboBox
seems to be shifted under the neighbouring widget in a layout. The combo box is shifted1px
down and2px
left.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 said in Why isn't a QComboBox positioned correctly in a layout?:
@JKSH Both the
QComboBox
and theQWidget
areQRect(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.
-
@Kerndog73 said in Why isn't a QComboBox positioned correctly in a layout?:
The
QWidget
isQRect(1,39 100x20)
and theQComboBox
isQRect(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_ComboBoxLayoutItem
case 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_LayoutUsesWidgetRect
attribute 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
QMacStyle
viaQProxyStyle
(which is the way I do), then reimplementsubElementRect(...)
function and make sure the function returns an invalid/default constructedQRect()
forSE_ComboBoxLayoutItem
case. 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-private
to 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