如何允许浮动 Qt5 停靠小部件的交互式调整大小

Posted

技术标签:

【中文标题】如何允许浮动 Qt5 停靠小部件的交互式调整大小【英文标题】:How to allow interactive resizing of floating Qt5 dock widget 【发布时间】:2018-12-05 23:47:12 【问题描述】:

我有以下 Qt5.11.0 代码来创建一个 qdockwidget。小部件的本质是允许用户在dockwidget 浮动时根据需要通过鼠标交互式地调整小部件的大小(下面的示例是人为设计的,但我相信可以说明问题)。

当我运行它并将dockwidget 浮动到它自己的***窗口中时,通过用户交互来调整dockwidget 的大小要么非常困难(Linux),要么不可能(OSX)。在 RHEL Linux 7.6 上,将鼠标悬停在浮动 Dockwidget 的右下角会产生一个“调整大小”光标,但是这种行为的热点最多只有一两个像素宽,这使得用户很难和令人沮丧调整浮动码头小部件的大小。在 OSX 10.13.6 上,我看不到任何通过鼠标交互来调整 dockwidget 大小的选项。

示例代码如下:

#include <QApplication>
#include <QMainWindow>
#include <QDockWidget>
#include <QTextEdit>
#include <QTextStream>
#include <QFile>
#include <QSizeGrip>

int
main( int argc, char *argv[] ) 
    QApplication app( argc, argv );

    QMainWindow* mw = new QMainWindow();
    mw->setCentralWidget( new QWidget() );

    QDockWidget* dockWidget = new QDockWidget( "Code viewer", mw );
    mw->addDockWidget( Qt::LeftDockWidgetArea, dockWidget );

    QTextEdit* textEdit = new QTextEdit( dockWidget );
    dockWidget->setWidget( textEdit );

    QFile file( "/etc/protocols" );
    QString filler;
    if( ! file.open( QIODevice::ReadOnly ) ) 
            exit( -1 );
     else 
            QTextStream in( &file );
            while( ! in.atEnd() ) 
                    filler += in.readLine();
            
            file.close();
    
    textEdit->setText( filler );

    mw->show();

    return app.exec();

我已经尝试过 QSizeGrip() 并在网上搜索过,但到目前为止无济于事。

如何在 Linux 上使用 Qt 控制鼠标驱动的浮动码头小部件调整大小的热区大小,以及如何在 OSX 上使用 Qt 首先启用此功能?

【问题讨论】:

【参考方案1】:

不幸的是,分离的 QDockWidget 的边框由窗口装饰器处理,因此您无法通过样式表或调整大小控制来更改它。 无论如何,您可以更改停靠小部件的窗口标志以强制窗口装饰器绘制常规边框。

在您的示例中,您可以这样做:

#include <QApplication>
#include <QMainWindow>
#include <QDockWidget>
#include <QTextEdit>
#include <QTextStream>
#include <QFile>
#include <QSizeGrip>

int main( int argc, char *argv[] ) 
    QApplication app( argc, argv );

    QMainWindow* mw = new QMainWindow();
    mw->setCentralWidget( new QWidget() );

    QDockWidget* dockWidget = new QDockWidget( "Code viewer", mw );
    mw->addDockWidget( Qt::LeftDockWidgetArea, dockWidget );

    // handle floating changes
    QObject::connect(dockWidget, &QDockWidget::topLevelChanged, [dockWidget] (bool floating)
    
        if (floating)
        
            dockWidget->setWindowFlags(Qt::Window);
            dockWidget->show();
        
    );

    QTextEdit* textEdit = new QTextEdit( dockWidget );
    dockWidget->setWidget( textEdit );

    QFile file( "/etc/protocols" );
    QString filler;
    if( ! file.open( QIODevice::ReadOnly ) ) 
            exit( -1 );
     else 
            QTextStream in( &file );
            while( ! in.atEnd() ) 
                    filler += in.readLine();
            
            file.close();
    
    textEdit->setText( filler );

    mw->show();

    return app.exec();

Here您可以找到所有可用窗口标志的描述,以自定义您的小部件的外观。

【讨论】:

\@Gabriella,这对我在 Linux 和 OSX 上都非常有用——非常感谢简洁、快速和有效的答案。 Qt::Window 标志已经为我设置为浮动 QDockWidgets(Debian sid 上的 PySide2 5.11.2,使用 KDE),但是清除 Qt::FramelessWindowHint 标志可以获得正常的窗口边框出现。也没有必要拨打QWidget::show()。 (续) 确实有一个小问题,因为 QDockWidget 在最初被取消停靠时会消失,直到窗口被放下,但我不确定这不是 Linux 的事情。清除Qt::BypassWindowManagerHint 并调用QWidget::show() 会在最初取消停靠时显示窗口,但随后在调整大小时窗口往往会消失。 (续) Qt Designer 似乎有带有适当边框的 QDockWidgets,并且没有额外的窗口标题来指示已清除的 Qt::FramelessWindowHint 标志,但我不确定他们是如何实现的。

以上是关于如何允许浮动 Qt5 停靠小部件的交互式调整大小的主要内容,如果未能解决你的问题,请参考以下文章

如何调整包含 QTableView 的小部件的大小?

Qt - 即使 QMainWindow 太小也允许停靠

QGraphicsBlurEffect 调整文本大小但不调整小部件本身

PyQt5,让用户调整小部件的大小

如何在VS2010中灵活地调整窗口视图

Delphi 2007 - ManualFloat 导致小部件控件浮动在所有其他窗口之上