我有一个带有停靠小部件和中央小部件的主窗口。中央小部件可以根据用户的选择进行更改,但停靠小部件保留。 当用户没有调整停靠小部件的大小时,一切都很好,并且更改中央小部件不会影响停靠小部件的大小(保持大小提示)。然而,当用户调整停靠小部件的大小时,它会异常放大并占据中央小部件空间。
这是问题的动画 gif:
这是重现问题的代码(使用 Qt5.15):
#include <QApplication>
#include <QLayout>
#include <QLabel>
#include <QMainWindow>
#include <QDockWidget>
#include <QToolBar>
#include <QTimer>
class Widget : public QWidget
{
public:
Widget(const QString& aName, QSize aSize, QWidget * parent = nullptr)
: QWidget(parent), size(aSize)
{
static int COUNT = 0;
static QStringList COLORS = { "LightBlue", "LightGreen", "LightSalmon" };
auto label = new QLabel(tr("%1 (%2x%3)").arg(aName).arg(size.width()).arg(size.height()), this);
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
label->setAlignment(Qt::AlignCenter);
label->setWordWrap(true);
label->setStyleSheet(QString("QLabel { background-color: %1 }").arg(COLORS.value(COUNT++ % COLORS.size())));
auto mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(label);
}
QSize sizeHint() const override
{
return size;
}
private:
QSize size;
};
class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
// Creating toolbar
addToolBar("Tool bar")->addAction("Switch central Widget", this, &MainWindow::switchCentralWidget);
// Creating main widget
switchCentralWidget();
// Creating dock widget
auto dockWidget = new QDockWidget("My dock widget");
dockWidget->setWidget(new Widget("DOCK WIDGET", {200, 400}, this));
addDockWidget(Qt::RightDockWidgetArea, dockWidget);
}
private slots:
void switchCentralWidget()
{
setCentralWidget(new Widget("CENTRAL WIDGET", {300, 400}, this));
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
我尝试(未成功)修改中央和停靠小部件的大小策略。 我发现防止扩展坞扩大的唯一方法是设置临时最大尺寸(见下文)。
void switchCentralWidget()
{
// Dirty hack
for (auto dock : findChildren<QDockWidget *>()) {
int width = dock->widget()->width();
int maxWidth = dock->widget()->maximumWidth();
dock->setMaximumWidth(width);
QTimer::singleShot(1000, dock, [=] { dock->setMaximumWidth(maxWidth); });
}
setCentralWidget(new Widget("CENTRAL WIDGET", {300, 400}, this));
}
但是它很脏,并且在修改停靠小部件的大小提示时会给我带来问题(一个用户操作是放置另一个中央小部件并修改停靠小部件字体大小)。
我想要的是停靠小部件保持与中央小部件切换之前相同的大小。
我无法阻止 QMainWindow 在调用时放大停靠小部件
setCentralWidget()
。解决方案是为中央小部件创建一个包装器:
class WidgetWrapper : public QWidget
{
public:
WidgetWrapper(QWidget *parent = nullptr)
: QWidget(parent),
layout(new QVBoxLayout(this)),
widget(nullptr)
{
layout->setContentsMargins(0, 0, 0, 0);
}
void setWidget(QWidget *aWidget) {
// Remove the current widget if it exists
if (widget) {
layout->removeWidget(widget);
widget->hide();
widget->deleteLater();
widget = nullptr;
}
// Add the new widget
if (aWidget) {
layout->addWidget(aWidget);
widget = aWidget;
}
}
private:
QVBoxLayout * layout;
QWidget * widget;
};
并像这样使用它:
class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent), centralWidget(new WidgetWrapper(this))
{
// Creating toolbar
addToolBar("Tool bar")->addAction("Switch central Widget", this, &MainWindow::switchCentralWidget);
// Init central widget
setCentralWidget(centralWidget);
switchCentralWidget();
// Creating dock widget
auto dockWidget = new QDockWidget("My dock widget");
dockWidget->setWidget(new Widget("DOCK WIDGET", {200, 400}, this));
addDockWidget(Qt::RightDockWidgetArea, dockWidget);
}
private slots:
void switchCentralWidget()
{
centralWidget->setWidget(new Widget("CENTRAL WIDGET", {300, 400}, this));
}
WidgetWrapper * centralWidget;
};