QT将QWidget设置为Tool弹出框,业务上需要根据实际回填内容改变窗体高度,比如一条数据30px高,那么空的时候为0,n条的时候为n*30。然后发现空的时候高度被固定为了160;
代码如下:
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QDebug>
#include <QObject>
#include <QVBoxLayout>
#include <QWidget>
class MyWidget : public QWidget {
Q_OBJECT
public:
explicit MyWidget(QWidget* parent = nullptr);
~MyWidget() { qDebug() << this << "~MyWidget"; }
signals:
private:
};
#endif // MYWIDGET_H
#include "mywidget.h"
MyWidget::MyWidget(QWidget* parent) : QWidget{parent} {
QWidget::setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
QWidget::setAttribute(Qt::WA_ShowWithoutActivating);
QWidget::setWindowFlag(Qt::Tool);
QWidget::setWindowFlag(Qt::NoDropShadowWindowHint);
QWidget::resize(500, 300);
QWidget::move(500, 500);
QWidget::hide();
QWidget::setStyleSheet("background-color:skyblue;");
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include "mywidget.h"
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;
MyWidget* m_popup;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
m_popup = new MyWidget(this);
m_popup->resize(1000, 600);
connect(ui->pushButton, &QPushButton::clicked, this, [this]() {
m_popup->resize(m_popup->width(), 0);
m_popup->show();
});
connect(ui->pushButton_2, &QPushButton::clicked, this, [this]() {
m_popup->resize(m_popup->width(), 320);
m_popup->show();
});
}
MainWindow::~MainWindow() { delete ui; }
效果如下所示:
原因分析
QWidget设置为Tool,变成弹出框,然后就调用了hide,一直没show过,所以对应的windows窗口没有被创建出来,调用show()的时候,会创建windows窗口,具体调用流程如下:
QWidget::show()->QWidget::setVisible(bool visible)-> QWidgetPrivate::setVisible(bool visible)->QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)->QWidgetPrivate::create()->QWindow::create()->QWindowPrivate::create(bool recursive, WId nativeHandle)->QWindowsIntegration::createPlatformWindow(QWindow *window)->
QWindowsWindowData::create(const QWindow w,const QWindowsWindowData ¶meters,const QString &title)->WindowCreationData::create(const QWindow w, const WindowData &data, QString title)->QPlatformWindow::initialGeometry(const QWindow w, const QRect &initialGeometry, int defaultWidth, int defaultHeight,const QScreen resultingScreenReturn)->static QSize fixInitialSize(QSize size, const QWindow w, int deviceIndependentDefaultWidth,int deviceIndependentDefaultHeight)
最终设置窗体大小的代码就是fixInitialSize函数(在qplatformwindow.cpp),如下所示:
static QSize fixInitialSize(QSize size, const QWindow *w, int deviceIndependentDefaultWidth,
int deviceIndependentDefaultHeight)
{
if (size.width() == 0) {
const int minWidth = w->minimumWidth();
size.setWidth(minWidth > 0 ? minWidth : deviceIndependentDefaultWidth);
}
if (size.height() == 0) {
const int minHeight = w->minimumHeight();
size.setHeight(minHeight > 0 ? minHeight : deviceIndependentDefaultHeight);
}
return size;
}
用到的defaultwidth和defaultheight定义在qwindowswindow.cpp文件,如下所示:
enum {
defaultWindowWidth = 160,
defaultWindowHeight = 160
};
在创建窗口的时候如果宽高为0,则会使用minimumWidth/minumumHeight(>0)或160.
解决方案
- MyWidget构造里先调用show,让它创建出窗体
缺点:
后面调用的resize(1000,600),宽度无效
提前创建窗体会耗费性能
- 在点击事件里调用show创建窗体,然后hide,再调用resize
- 在点击事件里判断一下宽高,然后决定是否调用show
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。