Can't get QLabel, QComboBox, and QSpinBox to align in form layout
-
Looks like it is. Per https://stackoverflow.com/questions/41452512/how-to-remove-margins-of-qlayout-completely-mac-os-specific, setting the Qt::WA_LayoutUsesWidgetRect attribute on the ComboBox widget should solve this. Now I just need to figure out how to do that in Designer or in PySide2...
-
Well, it doesn't look like this can be done in Designer. I tried doing this in my Python script, but it doesn't seem to have any effect. Minimal working example below.
import sys import os from PySide2.QtWidgets import QApplication, QMainWindow from PySide2.QtCore import Qt from Ui_MainWindow import Ui_MainWindow class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.comboBox.setAttribute(Qt.WA_LayoutUsesWidgetRect) self.ui.comboBox_2.setAttribute(Qt.WA_LayoutUsesWidgetRect) if __name__ == "__main__": app = QApplication([]) widget = MainWindow() widget.show() sys.exit(app.exec_())
Ui_MainWindow.py:
(I didn't touch this file; I just generated it viapyside2-uic form.ui -o Ui_MainWindow.py
):from PySide2.QtCore import * from PySide2.QtGui import * from PySide2.QtWidgets import * class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(800, 600) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.widget = QWidget(self.centralwidget) self.widget.setObjectName(u"widget") self.widget.setGeometry(QRect(240, 100, 279, 52)) self.formLayout_2 = QFormLayout(self.widget) self.formLayout_2.setObjectName(u"formLayout_2") self.formLayout_2.setContentsMargins(0, 0, 0, 0) self.radioButton = QRadioButton(self.widget) self.radioButton.setObjectName(u"radioButton") self.formLayout_2.setWidget(0, QFormLayout.LabelRole, self.radioButton) self.widget_1 = QWidget(self.widget) self.widget_1.setObjectName(u"widget_1") self.formLayout = QFormLayout(self.widget_1) self.formLayout.setObjectName(u"formLayout") self.formLayout.setContentsMargins(-1, 0, -1, -1) self.doubleSpinBox = QDoubleSpinBox(self.widget_1) self.doubleSpinBox.setObjectName(u"doubleSpinBox") self.formLayout.setWidget(0, QFormLayout.LabelRole, self.doubleSpinBox) self.comboBox = QComboBox(self.widget_1) self.comboBox.setObjectName(u"comboBox") self.formLayout.setWidget(0, QFormLayout.FieldRole, self.comboBox) self.formLayout_2.setWidget(0, QFormLayout.FieldRole, self.widget_1) self.widget1 = QWidget(self.centralwidget) self.widget1.setObjectName(u"widget1") self.widget1.setGeometry(QRect(260, 240, 281, 52)) self.formLayout_3 = QFormLayout(self.widget1) self.formLayout_3.setObjectName(u"formLayout_3") self.formLayout_3.setContentsMargins(0, 0, 0, 0) self.radioButton_2 = QRadioButton(self.widget1) self.radioButton_2.setObjectName(u"radioButton_2") self.formLayout_3.setWidget(0, QFormLayout.LabelRole, self.radioButton_2) self.widget_2 = QWidget(self.widget1) self.widget_2.setObjectName(u"widget_2") self.horizontalLayout = QHBoxLayout(self.widget_2) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(-1, 0, -1, -1) self.doubleSpinBox_2 = QDoubleSpinBox(self.widget_2) self.doubleSpinBox_2.setObjectName(u"doubleSpinBox_2") self.horizontalLayout.addWidget(self.doubleSpinBox_2) self.comboBox_2 = QComboBox(self.widget_2) self.comboBox_2.setObjectName(u"comboBox_2") self.horizontalLayout.addWidget(self.comboBox_2) self.formLayout_3.setWidget(0, QFormLayout.FieldRole, self.widget_2) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") self.menubar.setGeometry(QRect(0, 0, 800, 22)) MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) # setupUi def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) self.radioButton.setText(QCoreApplication.translate("MainWindow", u"RadioButton", None)) self.radioButton_2.setText(QCoreApplication.translate("MainWindow", u"RadioButton", None)) # retranslateUi
Running
python main.py
on my Mac generates:
Running those exact same files on my Ubuntu Box makes it look fine, even if I remove the
setAttribute(Qt.WA_LayoutUsesWidgetRect)
lines.Any idea how I can get this to work on my Mac?
-
Use a grid layout.
-
There are 2 things you might mean by that:
If you mean to use a GridLayout for the Widget Container holding the ComboBox and SpinBox (as opposed to a FormLayout or HorizontalLayout), that gives the same result as using the HorizontalLayout, so that doesn't fix things.
If you mean to get rid of the Widget Container, and to use a GridLayout for all 3 objects (the Label, the ComboBox, and the SpinBox), this does result in them being aligned properly. However, my actual UI is a form, and this group of 3 items is one of several items I want to be part of a larger FormLayout. I could work around this by making the entire form using a GridLayout instead of a FormLayout, but then I would lose out on the advantages of a FormLayout that are specified here: https://doc.qt.io/qt-5/qformlayout.html#details. E.g., I wouldn't get the "Adherence to the different platform's look and feel guidelines."
If there's no other way out, I can do that, but I'd like to keep the FormLayout if possible.
-
If it's not properly aligned in QGridLayout I would consider it as a bug - please provide a minimal (c++) example and open a bug report at bugreports.qt.io/
-
Bug report generated (https://bugreports.qt.io/browse/QTBUG-89741).
The minimal C++ example would just be:
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ mainwindow.cpp HEADERS += \ mainwindow.h FORMS += \ mainwindow.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
mainwindow.h:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.cpp:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->comboBox->setAttribute(Qt::WA_LayoutUsesWidgetRect); ui->comboBox_2->setAttribute(Qt::WA_LayoutUsesWidgetRect); ui->comboBox_3->setAttribute(Qt::WA_LayoutUsesWidgetRect); } MainWindow::~MainWindow() { delete ui; }
mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <widget class="QWidget" name=""> <property name="geometry"> <rect> <x>170</x> <y>160</y> <width>261</width> <height>52</height> </rect> </property> <layout class="QFormLayout" name="formLayout_2"> <item row="0" column="0"> <widget class="QRadioButton" name="radioButton"> <property name="text"> <string>RadioButton</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QWidget" name="widget" native="true"> <layout class="QFormLayout" name="formLayout"> <property name="topMargin"> <number>0</number> </property> <item row="0" column="0"> <widget class="QSpinBox" name="spinBox"/> </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBox"/> </item> </layout> </widget> </item> </layout> </widget> <widget class="QWidget" name=""> <property name="geometry"> <rect> <x>160</x> <y>240</y> <width>263</width> <height>52</height> </rect> </property> <layout class="QFormLayout" name="formLayout_3"> <item row="0" column="0"> <widget class="QRadioButton" name="radioButton_2"> <property name="text"> <string>RadioButton</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QWidget" name="widget_2" native="true"> <layout class="QHBoxLayout" name="horizontalLayout"> <property name="topMargin"> <number>0</number> </property> <item> <widget class="QSpinBox" name="spinBox_2"/> </item> <item> <widget class="QComboBox" name="comboBox_2"/> </item> </layout> </widget> </item> </layout> </widget> <widget class="QWidget" name=""> <property name="geometry"> <rect> <x>160</x> <y>310</y> <width>263</width> <height>52</height> </rect> </property> <layout class="QFormLayout" name="formLayout_4"> <item row="0" column="0"> <widget class="QRadioButton" name="radioButton_3"> <property name="text"> <string>RadioButton</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QWidget" name="widget_3" native="true"> <layout class="QGridLayout" name="gridLayout"> <property name="topMargin"> <number>0</number> </property> <item row="0" column="0"> <widget class="QSpinBox" name="spinBox_3"/> </item> <item row="0" column="1"> <widget class="QComboBox" name="comboBox_3"/> </item> </layout> </widget> </item> </layout> </widget> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>22</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>
-
Thx, can you please attach the c++ testcase to the bug report?
-
You should create a zip file containing your source and append it to the bug report.