c++ - Qt 布局 - 在调整大小时保持小部件纵横比

标签 c++ qt layout aspect-ratio

<分区>

我想在 QGroupBox 上保持 16/9 的纵横比(下图左侧的那个)。为了进行测试,我制作了一个简单的程序,其中包含 4 个垂直布局的分组框,全部采用水平布局:

ma​​in.cpp

#include "MainWindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "MainWindow.h"
#include "ui_MainWindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qDebug() << "horizontalLayout->hasHeightForWidth: " << ui->horizontalLayout->hasHeightForWidth();
}

MainWindow::~MainWindow()
{
    delete ui;
}

主窗口.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>1000</width>
    <height>703</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="GroupBoxHFW" name="groupBox_1">
      <property name="title">
       <string>GroupBox</string>
      </property>
     </widget>
    </item>
    <item>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <widget class="QGroupBox" name="groupBox_2">
        <property name="minimumSize">
         <size>
          <width>485</width>
          <height>204</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>485</width>
          <height>204</height>
         </size>
        </property>
        <property name="title">
         <string>GroupBox</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBox_3">
        <property name="minimumSize">
         <size>
          <width>485</width>
          <height>204</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>485</width>
          <height>204</height>
         </size>
        </property>
        <property name="title">
         <string>GroupBox</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBox_4">
        <property name="minimumSize">
         <size>
          <width>485</width>
          <height>204</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>485</width>
          <height>204</height>
         </size>
        </property>
        <property name="title">
         <string>GroupBox</string>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="verticalSpacer">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>40</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1000</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="toolBar">
   <property name="windowTitle">
    <string>toolBar</string>
   </property>
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <customwidgets>
  <customwidget>
   <class>GroupBoxHFW</class>
   <extends>QGroupBox</extends>
   <header>GroupBoxHFW.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

GroupBoxHFW.h

#ifndef GROUPBOXHFW_H
#define GROUPBOXHFW_H

#include <QGroupBox>

class GroupBoxHFW : public QGroupBox
{
public:
    GroupBoxHFW(QWidget * parent = 0);
    GroupBoxHFW(const QString & title, QWidget * parent = 0);

    int heightForWidth(int w) const;
    bool hasHeightForWidth() const;
};

#endif // GROUPBOXHFW_H

GroupBoxHFW.cpp

#include "GroupBoxHFW.h"

#include <QDebug>

GroupBoxHFW::GroupBoxHFW(QWidget * parent) : QGroupBox(parent)
{
    QSizePolicy policy(this->sizePolicy());
    policy.setHeightForWidth(true);

    this->setSizePolicy(policy);
}

GroupBoxHFW::GroupBoxHFW(const QString & title, QWidget * parent) : QGroupBox(title, parent)
{
    QSizePolicy policy(this->sizePolicy());
    policy.setHeightForWidth(true);

    this->setSizePolicy(policy);
}


int GroupBoxHFW::heightForWidth(int w) const
{
    qDebug() << "GroupBoxHFW::heightForWidth called";
    return 9.f / 16.f * w;
}

bool GroupBoxHFW::hasHeightForWidth() const
{
    qDebug() << "GroupBoxHFW::hasHeightForWidth called";
    return true;
}

如您所见,我重新实现了虚函数 int heightForWidth(int w) constbool hasHeightForWidth() const,希望我的 QGroupBox 会自动调整大小为 16/9 纵横比。不幸的是,它不起作用。 GroupBoxHFW::heightForWidth() 仅在程序启动时调用一次,甚至不调整小部件的大小。

这是程序的输出:

GroupBoxHFW::hasHeightForWidth called
horizontalLayout->hasHeightForWidth:  true
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::heightForWidth called
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::hasHeightForWidth called

更奇怪的是,当我调整窗口大小时,QGroupBox 调整大小时,上面的函数(hasHeightForWidth()heightForWidth() 都没有被调用。

怎么了?

最佳答案

如果此组框位于垂直布局内,您的方法可能会奏效。

顾名思义,当高度取决于宽度时,hasHeightForWidth 定义明确(这是为文本换行而设计的),而不是另一种方式(您的情况)。

你能做什么?试试这个(我已经为 QGraphicsWidget 实现了类似的东西,它工作得很好):

QSize GroupBoxHFW::sizeHint() const {
    QSize s = size();
    lastHeight = s.height();
    s.setWidth((s.height()*16)/9);
    s.setHeight(QGroupBox::sizeHint().height());
    return s;
}

void GroupBoxHFW::resizeEvent(QResizeEvent * event) {
    QGroupBox::resizeEvent(event);

    if (lastHeight!=height()) {
        updateGeometry(); // it is possible that this call should be scheduled to next iteration of event loop
    }
}

小题外话:
如果我这样做,我会尝试通过 QLayout 的子类而不是某些 QWidget 的子类来实现此功能。这样它就可以多次用于不同的小部件。

关于c++ - Qt 布局 - 在调整大小时保持小部件纵横比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24264320/

相关文章:

c++ - 如何从文件系统填充 XML 树?

c++ - 检索未命名结构的类型以在成员函数中使用它

css - Bootstrap 4 网格元素不在同一水平线上

c++ - Qt 可以使用 cin 吗?

c++ - 我的程序有一个保存配置文件的GUI,如何双击该配置文件直接用配置数据加载GUI?

java - 在java swing中调整窗口大小时如何使按钮粘在一个地方?

android - 从互联网下载 Android 布局

c++ - OpenGL 法线贴图问题 - 法线可能朝向错误的方向?

c++ - QMetaObject 上的 lua_newuserdata 位置新增

c++ - 必须在传递给 C 运行时函数的 QWidget 和无效参数之前构造 QApplication