Qt多文檔實現屏幕空間(類似監控多畫面)效果


Qt多文檔程序中的每一個子窗口就是一個個的畫面,子窗口可以自由拖動,激活來使用。
現實中,類似於監控的多畫面同時排列顯示比較常見,也比較實用。
實現思路:
1、響應窗口的resizeEvent事件
2、根據分割數目,通過setGeometry動態設置子窗口相對位置
代碼如下:

  1 #ifndef MAINWINDOW_H
  2 #define MAINWINDOW_H
  3 
  4 #include <QMainWindow>
  5 
  6 class QMdiArea;
  7 class QMdiSubWindow;
  8 class MainWindow : public QMainWindow
  9 {
 10     Q_OBJECT
 11 
 12 public:
 13     MainWindow(QWidget *parent = nullptr);
 14     ~MainWindow();
 15 
 16 protected:
 17     virtual void resizeEvent(QResizeEvent *event);
 18 
 19 private:
 20     void splitWindow(QList<QMdiSubWindow *> list, QSize windowSize);
 21 
 22 private:
 23     QMdiArea    *m_area;
 24 };
 25 
 26 #endif // MAINWINDOW_H
 27 
 28 
 29 #include "MainWindow.h"
 30 #include <QMdiArea>
 31 #include <QMdiSubWindow>
 32 #include <QResizeEvent>
 33 #include "View.h"
 34 #include "Scene.h"
 35 
 36 MainWindow::MainWindow(QWidget *parent)
 37     : QMainWindow(parent)
 38     , m_area(new QMdiArea())
 39 {
 40     /// set mdi area
 41     setCentralWidget(m_area);
 42 
 43     /// test...
 44     for (int i = 0; i < 4; ++i) {
 45         View *view = new View(this);
 46         Scene *scene = new Scene();
 47         view->setScene(scene);
 48         QMdiSubWindow *subWindow = new QMdiSubWindow();
 49         subWindow->setWidget(view);
 50         subWindow->setWindowFlags(Qt::FramelessWindowHint);
 51         m_area->addSubWindow(subWindow);
 52     }
 53 }
 54 
 55 MainWindow::~MainWindow()
 56 {
 57 
 58 }
 59 
 60 void MainWindow::resizeEvent(QResizeEvent *event)
 61 {
 62     if (nullptr != m_area){
 63         QList<QMdiSubWindow *> list = m_area->subWindowList();
 64         QSize windowSize = event->size();
 65         splitWindow(list, windowSize);
 66     }
 67 
 68 }
 69 
 70 void MainWindow::splitWindow(QList<QMdiSubWindow *> list, QSize windowSize)
 71 {
 72     int subWindow = list.size();
 73     switch (subWindow) {
 74     case 1:
 75         list.at(0)->setGeometry(0, 0, windowSize.width(), windowSize.height());
 76         break;
 77     case 2:
 78         for (int i = 0; i < subWindow; ++i) {
 79             if (i == 0){
 80                 list.at(i)->setGeometry(0, 0, windowSize.width() / 2, windowSize.height());
 81             }
 82             else {
 83                 list.at(i)->setGeometry(windowSize.width() / 2, 0, windowSize.width() / 2, windowSize.height());
 84             }
 85         }
 86         break;
 87     case 3:
 88     case 4:
 89         for (int i = 0; i < subWindow; ++i) {
 90             switch (i){
 91             case 0:
 92                 list.at(i)->setGeometry(0, 0, windowSize.width() / 2, windowSize.height() / 2);
 93                 break;
 94             case 1:
 95                 list.at(i)->setGeometry(windowSize.width() / 2, 0, windowSize.width() / 2, windowSize.height() / 2);
 96                 break;
 97             case 2:
 98                 list.at(i)->setGeometry(0, windowSize.height() / 2,  windowSize.width() / 2, windowSize.height() / 2);
 99                 break;
100             case 3:
101                 list.at(i)->setGeometry( windowSize.width() / 2, windowSize.height() / 2, windowSize.width() / 2, windowSize.height() / 2);
102                 break;
103             }
104         }
105 
106     }
107 }
 1 #ifndef VIEW_H
 2 #define VIEW_H
 3 
 4 #include <QGraphicsView>
 5 
 6 class View : public QGraphicsView
 7 {
 8 public:
 9     View(QWidget *parent = nullptr);
10 };
11 
12 #endif // VIEW_H
13 
14 #include "View.h"
15 
16 
17 View::View(QWidget *parent)
18     : QGraphicsView(parent)
19 {
20 
21 }
#ifndef SCENE_H
#define SCENE_H

#include <QGraphicsScene>

class Scene : public QGraphicsScene
{
public:
    Scene();
};

#endif // SCENE_H

#include "Scene.h"
#include <QGraphicsRectItem>

Scene::Scene()
{
    QGraphicsRectItem *item = new QGraphicsRectItem();
    item->setPos(100, 100);
    item->setRect(0, 0, 200, 100);
    item->setFlags(QGraphicsItem::ItemIsMovable);
    addItem(item);
}

構建運行:

擴展:如果想分割一個單獨的QGraphicsScene,可以將窗口中心設置為(0,0),左上,右上,左下,右下分成四個區域。繪制每個圖元時,在paint繪制函數中使用painter->setClipRect設置所在剪切區域即可,相關代碼片段如下:

// 圖元類代碼片段
void QRectItem::paint(QPainter *painter,
                      const QStyleOptionGraphicsItem *option,
                      QWidget *widget)
{
    QPainterPath path;
    path.addRect(m_clipRect);
    painter->setClipPath(path);
}

void QRectItem::setClipRect(QRect rect)
{
    m_clipRect = rect;
}


// 場景類代碼片段
// split scene
QPen pen(Qt::black, 1, Qt::DashLine);
addLine(QLine(-10000, 0, 10000, 0), pen);
addLine(QLine(0, -10000, 0, 10000), pen);

QRectItem *item1 = new QRectItem();
item1->setPos(-200, -200);
item1->setRect(0, 0, 200, 100);
item1->setClipRect(QRect(-1000, -1000, 1000, 1000));
item1->setFlags(QGraphicsItem::ItemIsMovable);
addItem(item1);
View Code

 


免責聲明!

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



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