Qt實戰10.支持最小化和最大化的QDockWidget


1 需求描述

由於項目需要,xx軟件的一些模塊均是以dockwidget的方式進行開發的,這樣便於實現靈活布局;但是在某些情況下需要全屏展示dockwidget中的內容,遺憾的是QDockWidget除了關閉按鈕,最小化、最大化按鈕都沒提供。

簡單整理下需求:在不影響QDockWidget正常功能情況下,當dockwidget懸浮時,自動出現最小化、最大化按鈕使窗口能夠最小化、最大化顯示。

2 設計思路

首先第一點,QDockWidget繼承QWidget,隱隱感覺還是好辦,應該問題不大,穩定情緒不要慌。

2.1 怎么動態獲取dockwidget的懸浮狀態?

當然是捕獲事件,經測試當dockwidget懸浮狀態改變時會觸發QEvent::ZOrderChange事件或topLevelChanged信號,我們只要捕獲到這個事件或信號就可以了。

2.2 怎么增加dockwidget的最小、最大化按鈕?

剛剛說了,QDockWidget繼承QWidget,通過setWindowFlags設置窗口的標記應該能滿足需求的。

3 代碼實現

理清思路后,下面開始實現,先通過事件處理,繼承QDockWidget重寫event函數,如下:

#ifndef CUSTOMDOCKWIDGET_H
#define CUSTOMDOCKWIDGET_H

#include <QDockWidget>

class CustomDockWidget : public QDockWidget
{
    Q_OBJECT
public:
    explicit CustomDockWidget(QWidget *parent = nullptr);

    // QObject interface
public:
    bool event(QEvent *event) override;
};

#endif // CUSTOMDOCKWIDGET_H
#include "CustomDockWidget.h"
#include <QEvent>

CustomDockWidget::CustomDockWidget(QWidget *parent) : QDockWidget(parent)
{
}

bool CustomDockWidget::event(QEvent *event)
{
    if (QEvent::ZOrderChange == event->type()) {
        if (isFloating()) {
            QWidget w;
            setMaximumSize(w.maximumSize());
            setWindowFlags(Qt::Dialog
                           | Qt::WindowCloseButtonHint
                           | Qt::WindowMaximizeButtonHint
                           | Qt::WindowMinimizeButtonHint);
            show();
        }
    }

    return QDockWidget::event(event);
}

代碼邏輯很簡單,就不需要解釋什么了吧,捕獲QEvent::ZOrderChange事件,根據dockwidget懸浮狀態做對應處理。
setMaximumSize這里如果不設置,最大化按鈕會是灰色的,因為dockwidget懸浮后maximumSize會改變,maximumSize如果不夠大的話窗口就不能最大化。
最后那個show()是有必要的,不然雙擊標題欄后dockwidget會隱藏。


當然,這里也可以通過信號處理,直接連接topLevelChanged信號:

connect(this, &QDockWidget::topLevelChanged, [=]() {
      if (isFloating()) {
          QWidget w;
          setMaximumSize(w.maximumSize());
          setWindowFlags(Qt::Dialog
                         | Qt::WindowCloseButtonHint
                         | Qt::WindowMaximizeButtonHint
                         | Qt::WindowMinimizeButtonHint);
          show();
      };
});

最終的效果都一樣,但是重寫事件的方式可以實現更復雜的功能,靈活度更高,可以應對更復雜的需求。

4 總結

通過上述過程便完成了dockwidget的最大化、最小話的功能實現,並且對QDockWidget原有的功能也沒有副作用,效果不錯;但是就這樣了嗎?如果用戶想雙擊標題欄實現全屏效果怎么辦呢?捕獲NonClientAreaMouseButtonDblClick事件就可以啦,面對不同的需求要能夠舉一反三,這是程序員必備的技能。

5 下載

測試代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM