QPushButton creates empty space on Mac OS X result

2019-04-01 01:15发布

问题:

I recently moved to Mac OS X and noticed that the Dialogs in one of my applications look kind of strange... I have several Dialogs that are basically a simple form that has configurable paths:

Label: <QLineEdit> <QPushButton (opens file dialog)>
Label: ...

The Dialog is organized in a QGridLayout, it looks fine on Ubuntu:

On Mac OS X there is a big empty space below the QPushButtons row which makes the whole thing look strange:

I found this bug report which was apparently silently closed: https://bugreports.qt.io/browse/QTBUG-2699

UI code:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>431</width>
    <height>235</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string>PDF Export</string>
  </property>
  <property name="windowIcon">
   <iconset resource="resources.qrc">
    <normaloff>:/images/images/application-pdf.png</normaloff>:/images/images/application-pdf.png</iconset>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="1">
      <widget class="QLineEdit" name="texPath">
       <property name="readOnly">
        <bool>true</bool>
       </property>
      </widget>
     </item>
     <item row="1" column="0">
      <widget class="QLabel" name="label">
       <property name="text">
        <string>Auszubildender:</string>
       </property>
       <property name="buddy">
        <cstring>traineeName</cstring>
       </property>
      </widget>
     </item>
     <item row="1" column="1" colspan="2">
      <widget class="QLineEdit" name="traineeName"/>
     </item>
     <item row="2" column="0">
      <widget class="QLabel" name="label_2">
       <property name="text">
        <string>Ausbilder:</string>
       </property>
       <property name="buddy">
        <cstring>instructorName</cstring>
       </property>
      </widget>
     </item>
     <item row="2" column="1" colspan="2">
      <widget class="QLineEdit" name="instructorName"/>
     </item>
     <item row="3" column="0">
      <widget class="QLabel" name="label_5">
       <property name="text">
        <string>Name der Firma:</string>
       </property>
       <property name="buddy">
        <cstring>companyName</cstring>
       </property>
      </widget>
     </item>
     <item row="3" column="1" colspan="2">
      <widget class="QLineEdit" name="companyName"/>
     </item>
     <item row="4" column="0">
      <widget class="QLabel" name="label_3">
       <property name="text">
        <string>Datum der Unterschriften:</string>
       </property>
       <property name="buddy">
        <cstring>dateEdit</cstring>
       </property>
      </widget>
     </item>
     <item row="4" column="1" colspan="2">
      <widget class="QDateEdit" name="dateEdit">
       <property name="displayFormat">
        <string>dd.MM.yyyy</string>
       </property>
       <property name="calendarPopup">
        <bool>true</bool>
       </property>
      </widget>
     </item>
     <item row="0" column="2">
      <widget class="QPushButton" name="browseButton">
       <property name="text">
        <string/>
       </property>
       <property name="icon">
        <iconset resource="resources.qrc">
         <normaloff>:/images/images/document-open.png</normaloff>:/images/images/document-open.png</iconset>
       </property>
      </widget>
     </item>
     <item row="0" column="0">
      <widget class="QLabel" name="label_4">
       <property name="text">
        <string>Pfad zum TEX-Template:</string>
       </property>
       <property name="buddy">
        <cstring>texPath</cstring>
       </property>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <spacer name="horizontalSpacer">
       <property name="orientation">
        <enum>Qt::Horizontal</enum>
       </property>
       <property name="sizeHint" stdset="0">
        <size>
         <width>40</width>
         <height>20</height>
        </size>
       </property>
      </spacer>
     </item>
     <item>
      <widget class="QPushButton" name="cancelButton">
       <property name="text">
        <string>Abbrechen</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="generateButton">
       <property name="text">
        <string>PDF generieren...</string>
       </property>
       <property name="icon">
        <iconset resource="resources.qrc">
         <normaloff>:/images/images/arrow-right.png</normaloff>:/images/images/arrow-right.png</iconset>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <tabstops>
  <tabstop>texPath</tabstop>
  <tabstop>browseButton</tabstop>
  <tabstop>traineeName</tabstop>
  <tabstop>instructorName</tabstop>
  <tabstop>companyName</tabstop>
  <tabstop>dateEdit</tabstop>
  <tabstop>cancelButton</tabstop>
  <tabstop>generateButton</tabstop>
 </tabstops>
 <resources>
  <include location="resources.qrc"/>
 </resources>
 <connections>
  <connection>
   <sender>cancelButton</sender>
   <signal>clicked()</signal>
   <receiver>Dialog</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>246</x>
     <y>221</y>
    </hint>
    <hint type="destinationlabel">
     <x>133</x>
     <y>152</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

Is there any way to fix this?

回答1:

You should be using a QButtonBox for your buttons, not discrete buttons in a custom layout. You'll need to add the PDF generation button manually.

As a temporary workaround, you need to reduce the bottom margin size on OS X. Hopefully it'll get fixed eventually.

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton * btn = new QPushButton(tr("PDF Generieren..."));
    btn->setIcon(QIcon(":/images/images/arrow-right.png"));
    ui->buttonBox->addButton(btn, QDialogButtonBox::AcceptRole);
#if (QT_VERSION <= QT_VERSION_CHECK(5, 1, 1)) && defined(QT_OS_MAC)
    QMargins margins = layout()->contentsMargins();
    margins.setBottom(margins.bottom() - 6);
    layout()->setContentsMargins(margins);
#endif
}


回答2:

Since this is still a problem in Qt 5.6 here's a possible solution: create your own QProxyStyle and re-implement subElementRect for SE_PushButtonLayoutItem. For example, return default QCommonStyle::subElementRect().