QT 基于QScrollArea的界面嵌套移动

在实际的应用场景中,经常会出现软件界面战场图大于实际窗体大小,利用QScrollArea可以为widget窗体添加滚动条,可以实现小窗体利用滚动条显示大界面需求。实现如下:

  • QT创建一个qWidget界面

       

  • 在ui界面中利用QT自带的widget控件布局一个如下图所示的层叠关系,widget_2界面大小需大于widget大小

       

  • 界面布局好后,将widget_2提升为类,提升之前需为工程新添加一个设计界面类,添加完之后,将widget_2提升为类类名和前面新添加的设计界面类名一致

       

 

       

  • 源码实现如下
  patchwindow.h
 1 #ifndef PATCHWINDOW_H
 2 #define PATCHWINDOW_H
 3 
 4 #include <QDebug>
 5 #include <QPainter>
 6 #include <QWidget>
 7 #include <QMouseEvent>
 8 #include <QStyleOption>
 9 #include <QPaintEvent>
10 
11 enum CursorRegion{
12     NONE,
13     TOPLEFT,
14     TOPRIGHT,
15     BOTTOMRIGHT,
16     BOTTOMLEFT
17 };
18 
19 namespace Ui {
20 class Patchwindow;
21 }
22 
23 class Patchwindow : public QWidget
24 {
25     Q_OBJECT
26 
27 public:
28     explicit Patchwindow(QWidget *parent = 0);
29     ~Patchwindow();
30     CursorRegion getCursorRegion(QPoint);
31 
32 public:
33     int borderWidth;
34     int handleSize;
35 
36     bool mousePressed;
37     QPoint previousPos;
38 
39 private:
40     Ui::Patchwindow *ui;
41 
42 protected:
43     void mousePressEvent(QMouseEvent*);
44     void mouseReleaseEvent(QMouseEvent*);
45     void mouseMoveEvent(QMouseEvent*);
46 
47 signals:
48     void send_widget_rx_ry(int rx,int ry);
49 };
50 
51 #endif // PATCHWINDOW_H
View Code
 patchwindow.cpp
 1 #include "patchwindow.h"
 2 #include "ui_patchwindow.h"
 3 
 4 Patchwindow::Patchwindow(QWidget *parent) :
 5     QWidget(parent),
 6     ui(new Ui::Patchwindow)
 7 {
 8     ui->setupUi(this);
 9 
10     this->setMouseTracking(true);
11 
12     setFocusPolicy(Qt::StrongFocus);
13 
14     mousePressed = false;
15     borderWidth = 1;
16     handleSize = 8;
17 
18 }
19 
20 Patchwindow::~Patchwindow()
21 {
22     delete ui;
23 }
24 
25 
26 //设置鼠标形状
27 CursorRegion Patchwindow::getCursorRegion(QPoint pos)
28 {
29     if (pos.x() > 0 && pos.x() < (handleSize + borderWidth) &&
30         pos.y() > 0 && pos.y() < (handleSize + borderWidth)  ){
31         if (this->hasFocus())
32             this->setCursor(QCursor(Qt::SizeFDiagCursor));
33         return CursorRegion::TOPLEFT;
34     }
35 
36     if (pos.x() > (this->width() - handleSize - borderWidth) && pos.x() < this->width() &&
37         pos.y() > 0 && pos.y() < (handleSize + borderWidth)  ){
38         if (this->hasFocus())
39             this->setCursor(QCursor(Qt::SizeBDiagCursor));
40         return CursorRegion::TOPRIGHT;
41     }
42 
43     if (pos.x() > (this->width() - handleSize - borderWidth) && pos.x() < this->width() &&
44         pos.y() > (this->height() - handleSize - borderWidth) && pos.y() < this->height()  ){
45         if (this->hasFocus())
46             this->setCursor(QCursor(Qt::SizeFDiagCursor));
47         return CursorRegion::BOTTOMRIGHT;
48     }
49 
50 
51     if (pos.x() > 0 && pos.x() < (handleSize + borderWidth) &&
52         pos.y() > (this->height() - handleSize - borderWidth) && pos.y() < this->height()  ){
53         if (this->hasFocus())
54             this->setCursor(QCursor(Qt::SizeBDiagCursor));
55         return CursorRegion::BOTTOMLEFT;
56     }
57 
58     this->setCursor(Qt::ArrowCursor);
59     return CursorRegion::NONE;
60 }
61 
62 void Patchwindow::mousePressEvent(QMouseEvent *event)
63 {
64     mousePressed = true;
65     previousPos = this->mapToParent(event->pos());
66     //qDebug()<<"previousPos = "<<previousPos;
67 }
68 
69 void Patchwindow::mouseReleaseEvent(QMouseEvent*)
70 {
71     mousePressed = false;
72 }
73 
74 void Patchwindow::mouseMoveEvent(QMouseEvent *event)
75 {
76     if (mousePressed){
77         QPoint _curPos = this->mapToParent(event->pos());
78         QPoint _offPos = _curPos - previousPos;
79         previousPos = _curPos;
80         //qDebug()<<"_offPos = "<<_offPos;
81         //qDebug()<<"_curPos = "<<_curPos;
82         emit send_widget_rx_ry(_offPos.rx(),_offPos.ry());
83     }
84 }
View Code
 mainwindow.h
 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include <QHBoxLayout>
 6 #include <QDebug>
 7 #include <QScrollArea>
 8 
 9 
10 namespace Ui {
11 class MainWindow;
12 }
13 
14 class MainWindow : public QMainWindow
15 {
16     Q_OBJECT
17 
18 public:
19     explicit MainWindow(QWidget *parent = 0);
20     ~MainWindow();
21 
22     QScrollArea *m_pScroll;
23 
24 
25 private:
26     Ui::MainWindow *ui;
27 
28 private slots:
29     void remove_widget(int r_x,int r_y);
30 
31 
32 };
33 
34 #endif // MAINWINDOW_H
View Code
 mainwindow.cpp
 1 #include "mainwindow.h"
 2 #include "ui_mainwindow.h"
 3 #include <QPalette>
 4 
 5 #include <QScrollBar>
 6 
 7 MainWindow::MainWindow(QWidget *parent) :
 8     QMainWindow(parent),
 9     ui(new Ui::MainWindow)
10 {
11     ui->setupUi(this);
12     //this->resize(600,600);
13 
14     //给父窗体填充颜色
15     QPalette palette = ui->widget_2->palette();
16     palette.setBrush(QPalette::Window,QBrush(QColor(61,61,61)));
17     ui->widget_2->setAutoFillBackground(true);
18     ui->widget_2->setPalette(palette);
19 
20     ui->widget_2->setAttribute(Qt::WA_StyledBackground);
21     ui->widget_2->setStyleSheet("QWidget{background: black}");
22 
23     ui->widget_3->setAttribute(Qt::WA_TransparentForMouseEvents, true);//设置该层鼠标事件透明,可以设置为显示层
24 
25     m_pScroll = new QScrollArea(ui->widget);
26     m_pScroll->setWidget(ui->widget_2);//给widget_2设置滚动条
27     //ui->widget_2->setMinimumSize(1500,1000);//这里注意,要比主窗体的尺寸要大,不然太小的话会留下一片空白
28 
29     QHBoxLayout *pLayout = new QHBoxLayout;
30     pLayout->addWidget(m_pScroll);
31     pLayout->setMargin(0);
32     pLayout->setSpacing(0);
33     ui->widget->setLayout(pLayout);
34 
35     connect(ui->widget_2,&Patchwindow::send_widget_rx_ry,this,&MainWindow::remove_widget);
36 
37 }
38 
39 MainWindow::~MainWindow()
40 {
41     delete ui;
42 }
43 
44 void MainWindow::remove_widget(int r_x,int r_y)
45 {
46     r_y = m_pScroll->verticalScrollBar()->value()-r_y;
47     r_x = m_pScroll->horizontalScrollBar()->value()-r_x;
48 
49     if((0 < r_y) | (r_y == 0))
50     {
51         if(r_y > m_pScroll->verticalScrollBar()->maximum())
52         {
53             r_y = m_pScroll->verticalScrollBar()->maximum();
54         }
55     }
56     else
57     {
58         r_y = 0;
59     }
60 
61     if((0 < r_x) | (r_x == 0))
62     {
63         if(r_x > m_pScroll->horizontalScrollBar()->maximum())
64         {
65             r_x = m_pScroll->horizontalScrollBar()->maximum();
66         }
67     }
68     else
69     {
70         r_x = 0;
71     }
72 
73     m_pScroll->verticalScrollBar()->setValue(r_y);
74     m_pScroll->horizontalScrollBar()->setValue(r_x);
75 
76 }
View Code
  • 最终实现效果如下,可以通过滚轮滚动界面,也可以通过鼠标拖拽来实现界面拖拽效果:

    

    工程源码下载路径:

「ScrollArea」https://www.aliyundrive.com/s/QMf912nt86A 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。

 

posted @ 2022-06-10 14:04  熊来闯一闯  阅读(612)  评论(0编辑  收藏  举报