Qt 基於Qt的詞典開發系列--無邊框視窗的縮放與拖動
阿新 • • 發佈:2020-08-14
在現在,絕大多數軟體都向著簡潔,時尚發展。就拿有道的單詞本和我做的單詞本來說,絕大多數使用者肯定喜歡我所做的單詞本(就單單介面,關於顏色搭配和佈局問題,大家就不要在意了)。
有道的單詞本:
我所做的單詞本:
很明顯,兩者的主要區別就是周圍的邊框問題。你可以對比QQ以前的版本和這幾年的版本,就會發現都傾向於下面這種視窗模式。下面我們就說說如何用Qt實現無邊框視窗的縮放與拖動。 對於無邊框視窗的拖動其實很簡單,其基本思想是,在滑鼠移動前後記錄滑鼠的座標,然後將視窗移動這兩個座標之差的距離即可,具體實現可以看程式碼,就非常清楚了。下面主要講講如何實現滑鼠改變視窗的大小,首先,我們將一個視窗分為以下9個區域,其中只有滑鼠在22區域時無法改變其形狀,不能改變視窗大小。當滑鼠在其它區域時,滑鼠改變形狀並可以改變視窗大小。視窗區域分類如下圖:
具體實現如下程式碼(widget.ui未做任何改變): 1、widget.h檔案
1 #ifndef WIDGET_H
2 #define WIDGET_H
3
4 #include <QWidget>
5 #define MARGIN 20//四個角的長度
6 namespace Ui {
7 class Widget;
8 }
9
10 class Widget : public QWidget
11 {
12 Q_OBJECT
13
14 public:
15 explicit Widget(QWidget *parent = 0 );
16 ~Widget();
17 int countFlag(QPoint p, int row);
18 void setCursorType(int flag);
19 int countRow(QPoint p);
20
21 protected:
22 void mousePressEvent(QMouseEvent *event);
23 void mouseReleaseEvent(QMouseEvent *event);
24 void mouseDoubleClickEvent(QMouseEvent *event );
25 void mouseMoveEvent(QMouseEvent *event);
26 private:
27 Ui::Widget *ui;
28 bool isLeftPressed;
29 int curPos;
30 QPoint pLast;
31 };
32
33 #endif // WIDGET_H
2、widget.cpp檔案
1 #include "widget.h"
2 #include "ui_widget.h"
3 #include<QMouseEvent>
4 #include<QDebug>
5
6 Widget::Widget(QWidget *parent) :
7 QWidget(parent),
8 ui(new Ui::Widget)
9 {
10 ui->setupUi(this);
11 this->setMouseTracking(true);
12 //設定在不按滑鼠的情況下也觸發滑鼠移動事件,注意QMainWindow的情況:centralWidget()->setMouseTracking(true);
13 isLeftPressed=false;
14 curPos=0;//標記滑鼠左擊時的位置
15 this->setMinimumSize(400,300);//設定最小尺寸
16 QCursor cursor;
17 cursor.setShape(Qt::ArrowCursor);//設定滑鼠為箭頭形狀
18 // ui->pushButton->setCursor(cursor);//當放在按鈕上時,為箭頭
19 // cursor.setShape(Qt::OpenHandCursor);
20 QWidget::setCursor(cursor);//當放在主視窗上時,為手形
21 qDebug()<<"h="<<this->height();
22 setWindowFlags(Qt::FramelessWindowHint);//設定主視窗無邊框
23 qDebug()<<this->minimumHeight();
24 }
25
26 Widget::~Widget()
27 {
28 delete ui;
29 }
30 void Widget::mousePressEvent(QMouseEvent *event)//滑鼠按下事件
31 {
32 if(event->button()==Qt::LeftButton)
33 {
34 this->isLeftPressed=true;
35 QPoint temp=event->globalPos();
36 pLast=temp;
37 curPos=countFlag(event->pos(),countRow(event->pos()));
38 event->ignore();
39 }
40 }
41
42 void Widget::mouseReleaseEvent(QMouseEvent *event)//滑鼠釋放事件
43 {
44 if(isLeftPressed)
45 isLeftPressed=false;
46 QApplication::restoreOverrideCursor();//恢復滑鼠指標性狀
47 event->ignore();
48 }
49
50 void Widget::mouseDoubleClickEvent(QMouseEvent *event)//滑鼠雙擊 全屏
51 {
52 if(event->button()==Qt::LeftButton)
53 {
54 if(windowState()!=Qt::WindowFullScreen)
55 setWindowState(Qt::WindowFullScreen);
56 else setWindowState(Qt::WindowNoState);//恢復正常模式
57 }
58 event->ignore();
59 }
60
61 void Widget::mouseMoveEvent(QMouseEvent *event)//滑鼠移動事件
62 {
63
64 int poss=countFlag(event->pos(),countRow(event->pos()));
65 setCursorType(poss);
66 if(isLeftPressed)//是否左擊
67 {
68 QPoint ptemp=event->globalPos();
69 ptemp=ptemp-pLast;
70 if(curPos==22)//移動視窗
71 {
72 ptemp=ptemp+pos();
73 move(ptemp);
74 }
75 else
76 {
77 QRect wid=geometry();
78
79 switch(curPos)//改變視窗的大小
80 {
81
82 case 11:wid.setTopLeft(wid.topLeft()+ptemp);break;//左上角
83 case 13:wid.setTopRight(wid.topRight()+ptemp);break;//右上角
84 case 31:wid.setBottomLeft(wid.bottomLeft()+ptemp);break;//左下角
85 case 33:wid.setBottomRight(wid.bottomRight()+ptemp);break;//右下角
86 case 12:wid.setTop(wid.top()+ptemp.y());break;//中上角
87 case 21:wid.setLeft(wid.left()+ptemp.x());break;//中左角
88 case 23:wid.setRight(wid.right()+ptemp.x());break;//中右角
89 case 32:wid.setBottom(wid.bottom()+ptemp.y());break;//中下角
90 }
91 setGeometry(wid);
92 }
93
94
95 pLast=event->globalPos();//更新位置
96 }
97 event->ignore();
98 }
99
100
101
102 int Widget::countFlag(QPoint p,int row)//計算滑鼠在哪一列和哪一行
103 {
104 if(p.y()<MARGIN)
105 return 10+row;
106 else if(p.y()>this->height()-MARGIN)
107 return 30+row;
108 else
109 return 20+row;
110 }
111
112 void Widget::setCursorType(int flag)//根據滑鼠所在位置改變滑鼠指標形狀
113 {
114 Qt::CursorShape cursor;
115 switch(flag)
116 {
117 case 11:
118 case 33:
119 cursor=Qt::SizeFDiagCursor;break;
120 case 13:
121 case 31:
122 cursor=Qt::SizeBDiagCursor;break;
123 case 21:
124 case 23:
125 cursor=Qt::SizeHorCursor;break;
126 case 12:
127 case 32:
128 cursor=Qt::SizeVerCursor;break;
129 case 22:
130 cursor=Qt::OpenHandCursor;break;
131 default:
132 // QApplication::restoreOverrideCursor();//恢復滑鼠指標性狀
133 break;
134
135 }
136 setCursor(cursor);
137 }
138
139 int Widget::countRow(QPoint p)//計算在哪一列
140 {
141 return (p.x()<MARGIN)?1:(p.x()>(this->width()-MARGIN)?3:2);
142 }
3、main.cpp檔案
1 #include<QtWidgets>
2 #include "widget.h"
3 int main(int argc, char *argv[])
4 {
5 QApplication a(argc, argv);
6 Widget w;
7 w.show();
8
9 return a.exec();
10 }
程式執行截圖如下:
當你將滑鼠放在視窗的邊緣時,滑鼠會變化形狀,表示可以拖動視窗。由於沒有關閉視窗,只能在強制關閉視窗。如果想做到和不同視窗實現最小化和關閉視窗的畫,我們可以在視窗左上角放置兩個ToolButton,並設定autorise屬性,加上圖片即可。下面給出使用上面的無邊框視窗所做的詞典軟體的主介面: