简体   繁体   English

在qt中将方形qWidget居中

[英]Centering a square qWidget in qt

I am trying to solve a graphics problem using the latest version of Qt. 我正在尝试使用最新版本的Qt解决图形问题。 The image below shows what I managed to get so far and I will use it to explain the expected result. 下图显示了到目前为止我能做的事情,我将用它来解释预期的结果。

我工作的结果

I'm using a main vertical layout and within the biggest widget of the layout there is a horizontal layout with only one child: the square widget. 我使用的是主要的垂直布局,并且在该布局的最大窗口小部件中,只有一个孩子的水平布局是:正方形窗口小部件。 The expected behavior would be of course to have the square widget centered horizontally and taking up the biggest space available. 预期的行为当然是使方形小部件水平居中并占用最大可用空间。 It is not required to use the same layout configuration, but the look of the interface should be the same. 不需要使用相同的布局配置,但是界面的外观应该相同。

The image above has been obtained by setting a QSizePolicy of minimumExpanding for both vertical and horizontal to the square widget and by forcing it to be square with the following code: 上面的图像是通过以下方式获得的:为方形小部件设置垂直和水平方向的QSizePolicy的minimumExpanding,并通过以下代码将其强制为方形:

void SquareWidget::resizeEvent(QResizeEvent *event) {
    //This is an override to the QWidget method

    QSize s = size();

    if (s.height()<s.width()) {
        resize(s.height(), s.height());
    } else {
        resize(s.width(), s.width());
    }
    return;
}

While trying to solve this problem I went through the documentation some of the answers on this website and I couldn't find a clear answer about how to do two tasks. 在尝试解决此问题时,我浏览了该网站上的一些文档,但找不到关于如何执行两项任务的明确答案。

First problem: how to make the widget square and keep its aspect ratio? 第一个问题:如何使小部件方形并保持其长宽比?

In this question 在这个问题上

it is said that the method heightForWidth () doesn't work in newer versions of qt, and after a test it doesn't work for me either. 有人说,heightForWidth()方法在较新版本的qt中不起作用,经过测试后,它对我也不起作用。 The above override of resizeEvent, on the other hand, causes recursion because there are calls to resize() (and as far as I understand the layout should handle the resizing). 另一方面,上面对resizeEvent的覆盖会导致递归,因为有对resize()的调用(据我所知,布局应处理调整大小)。

Second problem: how to center the square? 第二个问题:如何使正方形居中?

I tried using the layout alignment properties (center horizontally and vertically) but they cause the widget size to be immutable. 我尝试使用布局对齐属性(水平和垂直居中),但它们导致小部件尺寸不可变。

Maybe I am not understanding something about how Qt handles the widget placement. 也许我对Qt如何处理小部件放置不了解。 Any suggestion or clarification will be greatly appreciated. 任何建议或澄清将不胜感激。

You can do it with a QGridLayout . 您可以使用QGridLayout来实现

Please see the attached code. 请参阅随附的代码。

mainwindow.h 主窗口

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MyWidget final : public QWidget
{
    Q_OBJECT

protected:

    virtual void resizeEvent(QResizeEvent * event) override;
};

class MainWindow final : public QMainWindow
{
    Q_OBJECT

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

#endif // MAINWINDOW_H

mainwindow.cpp 主窗口

#include "mainwindow.h"

#include <QGridLayout>
#include <QLabel>
#include <QResizeEvent>
#include <QSpacerItem>

void MyWidget::resizeEvent(QResizeEvent * event)
{
    event->accept();

    const QSize current_size = size();
    const int min = std::min(current_size.width(), current_size.height());
    resize(min, min);
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    auto main_widget = new QWidget;
    auto header = new QLabel("Hello World");
    auto center_widget = new MyWidget;
    auto footer = new QLabel("Good bye World");
    auto spacer_left = new QSpacerItem(10, 10, QSizePolicy::Expanding);
    auto spacer_right = new QSpacerItem(10, 10, QSizePolicy::Expanding);
    auto grid_layout = new QGridLayout(main_widget);

    auto center_palette = center_widget->palette();
    center_palette.setColor(QPalette::Background, Qt::blue);
    center_widget->setAutoFillBackground(true);
    center_widget->setPalette(center_palette);

    grid_layout->addWidget(header, 0, 1);
    grid_layout->addItem(spacer_left, 1, 0);
    grid_layout->addWidget(center_widget, 1, 1);
    grid_layout->addItem(spacer_right, 1, 2);
    grid_layout->addWidget(footer, 2, 1);

    header->setAlignment(Qt::AlignCenter);
    footer->setAlignment(Qt::AlignCenter);

    setCentralWidget(main_widget);
}

Please see the result here 请在这里查看结果

Rather than trying to get the widget to keep itself square and centred it might be simpler to reparent it and put the required logic in the parent widget type. 与其尝试使小部件保持其自身的方形和居中,不如将其重新放置并在父小部件类型中放置所需的逻辑可能更简单。

So, something like... 所以,类似...

class keep_child_square_and_centred: public QWidget {
  using super = QWidget;
public:
  explicit keep_child_square_and_centred (QWidget *parent = nullptr)
    : super(parent)
    , m_widget(nullptr)
    {}
  virtual void set_widget (QWidget *widget)
    {
      if ((m_widget = widget))
        m_widget->setParent(this);
    }
  virtual QSize sizeHint () const override
    {
      return(m_widget ? m_widget->sizeHint() : super::sizeHint());
    }
protected:
  virtual void resizeEvent (QResizeEvent *event) override
    {
      super::resizeEvent(event);
      fixup();
    }
private:
  void fixup ()
    {
      if (m_widget) {
        QRect r(QPoint(), QSize(height(), height()));
        r.moveCenter(rect().center());
        m_widget->setGeometry(r);
      }
    }
  QWidget *m_widget;
};

Then use as... 然后用作...

keep_child_square_and_centred w;
SquareWidget sq;
w.set_widget(&sq);

You may still need to play around with a few settings if the parent is in a layout though. 如果父级处于布局中,则可能仍需要进行一些设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM