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

 

posted on 2020-03-16 14:14  我来乔23  阅读(977)  评论(0编辑  收藏  举报

导航