QDockWidget具有一项功能,您可以双击标题栏,并且停靠栏将切换到浮动窗口并返回其停靠状态。问题是,如果您移动浮动窗口并调整其大小,然后切换回停靠栏,然后又重新回到浮动窗口,则会丢失位置和大小。
我一直在寻找用于调整和移动QDockWidget大小的解决方案,并且已经研究了QDockWidget的Qt源代码。我创建了一个QDockWidget的小子类,该子类似乎可以解决该问题。它会覆盖mouseDoubleClick,调整事件大小和移动事件,过滤掉Qt不必要的“随机”调整大小和位置,并将有关屏幕,位置和大小的信息存储在我存储在QSettings中的结构中,以确保会话之间的持久性。
// header
#include <QDockWidget>
#include "global.h"
class DockWidget : public QDockWidget
{
Q_OBJECT
public:
DockWidget(const QString &title, QWidget *parent = nullptr);
QSize sizeHint() const;
void rpt(QString s);
struct DWLoc {
int screen;
QPoint pos;
QSize size;
};
DWLoc dw;
bool ignore;
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
void moveEvent(QMoveEvent *event);
};
// cpp
#include "dockwidget.h"
DockWidget::DockWidget(const QString &title, QWidget *parent)
: QDockWidget(title, parent)
{
ignore = false;
}
bool DockWidget::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonDblClick) {
ignore = true;
setFloating(!isFloating());
if (isFloating()) {
// move and size to previous state
QRect screenres = QApplication::desktop()->screenGeometry(dw.screen);
move(QPoint(screenres.x() + dw.pos.x(), screenres.y() + dw.pos.y()));
ignore = false;
adjustSize();
}
ignore = false;
return true;
}
QDockWidget::event(event);
return true;
}
void DockWidget::resizeEvent(QResizeEvent *event)
{
if (ignore) {
return;
}
if (isFloating()) {
dw.screen = QApplication::desktop()->screenNumber(this);
QRect r = geometry();
QRect a = QApplication::desktop()->screen(dw.screen)->geometry();
dw.pos = QPoint(r.x() - a.x(), r.y() - a.y());
dw.size = event->size();
}
}
QSize DockWidget::sizeHint() const
{
return dw.size;
}
void DockWidget::moveEvent(QMoveEvent *event)
{
if (ignore || !isFloating()) return;
dw.screen = QApplication::desktop()->screenNumber(this);
QRect r = geometry();
QRect a = QApplication::desktop()->screen(dw.screen)->geometry();
dw.pos = QPoint(r.x() - a.x(), r.y() - a.y());
dw.size = QSize(r.width(), r.height());
}
虽然这似乎可行,但有没有更简单的方法来实现这一目标?如果QDockWidget位于现在关闭的屏幕上怎么办?