先看看运行效果,我用的群创7寸屏,主机是mini2440,分辨率是800*480,程序写比较粗糙,但对初学者还是有一点启发,大家一起进步。
qt中提供了QGphicsView,QGraphicsScene,QGraphicsItem,QGraphicsPixmapItem是QGraphicsItem的子类
分辨创建它们的实例:view,scene,item,然后通过各自的方法scene->addItem(item);view->setScene(scene);就可以达到类似下图的效果,想要进一步定制,则要继承QGraphicsItem或QGraphicsPixmapItem,然后重写paint()、boundingRect()等方法,此外如果还想要获取鼠标事件,重写mousePressEvent等事件就好了,注意,一旦重写了mousePressEvent方法,就以为了qt不会再自动处理item的任何press事件了,可以在你重写的mousePressEvent方法中最后添加QGraphicsItem::mousePressEvent(event);解决这个问题,就是说你获取到了鼠标事件,但是依然让qt处理这个鼠标事件。
程序中的item可以水平拖动,拖动的同时图标大小会渐变,中间最大,两边渐小。
图1
图2
图3
下面是源程序目录结构:
mainwindow.h与main.cpp是qt自动产生的代码,我没有产生窗口ui
myscene.h与某与scene.cpp是定义了类MyScene,继承自QGraphicsScene,我的目的是要获取其鼠标事件
nodeui.h与nodeui.cpp是定义了类NodeUI,继承自QGraphicsPixmapItem,目的相当多。
下面具体的源文件:myscene.h与myscene.cpp相对简单,就实现了一个功能
myscene.h
1 #ifndef MYSCENE_H
2 #define MYSCENE_H
3
4 #include <QGraphicsScene>
5
6 class MyScene : public QGraphicsScene
7 {
8 Q_OBJECT
9 public:
10 explicit MyScene(QObject *parent = 0);
11
12 private:
13 void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
14 void mousePressEvent(QGraphicsSceneMouseEvent *event);
15 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
16
17 signals:
18 void isMoving(QPointF &pos);
19
20 public slots:
21
22 private:
23 QPointF beforePos;
24 QPointF releasePos;
25 };
26
27 #endif // MYSCENE_H
myscene.cpp
1 #include "myscene.h"
2 #include <QGraphicsSceneMouseEvent>
3 #include <QPointF>
4 #include <QDebug>
5
6
7 MyScene::MyScene(QObject *parent) :
8 QGraphicsScene(parent)
9 {
10 }
11 void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
12 {
13 //QPointF pos = event->scenePos();
14 QPointF pos(event->scenePos().x()-beforePos.x(),event->scenePos().y()-beforePos.y());
15 emit isMoving(pos);
16 //qDebug()<<"x:"<<pos.x()<<"y:"<<pos.y();
17 }
18 void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
19 {
20 beforePos = event->scenePos();
21 }
22 void MyScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
23 {
24 releasePos = event->scenePos();
25 }
再看nodeui.h与nodeui.cpp,在原来的QGraphicsPixmapItem基础上又假如了点自己的东西
nodeui.h
1 #ifndef NODEUI_H
2 #define NODEUI_H
3
4 #include <QGraphicsPixmapItem>
5 #include <QGraphicsItem>
6 #include <QStyleOptionGraphicsItem>
7 #include <QPainter>
8 #include <QGraphicsSceneMouseEvent>
9 #include <QPointF>
10
11 class NodeUI : public QObject,public QGraphicsPixmapItem
12 {
13 Q_OBJECT
14 public:
15 NodeUI();
16 NodeUI(QString &file,QString &text,int imagesize=80);
17
18 //setup function
19 void setMyPixmap(QString &file,int size);
20 void setMyText(QString &text);
21 QString getMyText();
22 //virtual function
23 QRectF boundingRect() const;
24 QPainterPath shape() const;
25 signals:
26 void nodeIsMoving(QPointF &pos);
27 void nodeIsPressed();
28
29
30 protected:
31 void mousePressEvent(QGraphicsSceneMouseEvent *event);
32 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
33 private:
34 //QString myImage;
35 QString myText;
36
37 };
38
39 #endif // NODEUI_H
nodeui.cpp
1 #include "nodeui.h"
2 #include <QPixmap>
3 #include <iostream>
4 #include <QDebug>
5
6 NodeUI::NodeUI()
7 {
8 }
9 /*note: imagesize = 80 is in the nodeui.h*/
10 NodeUI::NodeUI(QString &file,QString &text,int imagesize)
11 {
12
13 setMyText(text);
14 setMyPixmap(file,imagesize);
15 }
16
17 void NodeUI::setMyText(QString &text)
18 {
19 myText = text;
20 }
21
22 void NodeUI::setMyPixmap(QString &file,int size)
23 {
24 //myImage = file;
25 QPixmap pixmap;
26 pixmap.load(file);
27 pixmap= pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
28 setPixmap(pixmap);
29 }
30 QRectF NodeUI::boundingRect() const
31 {
32 QRect rect = this->pixmap().rect();
33 //return QRectF(rect);
34 return QRectF(0,0,rect.width(),rect.width()+15);
35 }
36
37 void NodeUI::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
38 QWidget *widget)
39 {
40 QPixmap pixmap = this->pixmap();
41 QRect rect = pixmap.rect();
42
43 painter->drawPixmap(rect,pixmap);
44
45
46 //print name,calculate the text's heigh & width for center layout
47 QPen pen(Qt::black);
48 painter->setPen(pen);
49 painter->setRenderHint(QPainter::Antialiasing);
50 QFont font("Verdana",8, QFont::Normal);
51 painter->setFont(font);
52 painter->drawText(QRectF(0,rect.height(),rect.width(),15),Qt::AlignCenter,myText);
53
54 if (option->state & QStyle::State_Sunken)
55 {
56 QRectF rect1 = boundingRect();
57 //QPen pen(Qt::darkGreen);
58 painter->setPen(QPen(Qt::darkGreen));
59 }else
60 {
61
62 }
63 }
64 QPainterPath NodeUI::shape() const
65 {
66 QRectF rect = boundingRect();
67
68 QPainterPath path;
69 path.addRoundRect(rect, 5,5);
70 return path;
71 }
72
73 void NodeUI::mousePressEvent(QGraphicsSceneMouseEvent *event)
74 {
75 emit nodeIsPressed();
76 qDebug()<<"pressed";
77 QGraphicsItem::mousePressEvent(event);
78 }
79 void NodeUI::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
80 {
81 update(boundingRect());
82 QGraphicsItem::mouseReleaseEvent(event);
83 }
84 QString NodeUI::getMyText()
85 {
86 return myText;
87 }
最后是scene与item的文件mainwindow.cpp,继承了QMainWindow,作用就是画一个应用程序框架
mainwindow.h
1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include <QtGui/QMainWindow>
5 #include <QGraphicsView>
6 #include <QGraphicsScene>
7 #include <QPointF>
8 #include "nodeui.h"
9 #include "myscene.h"
10 #include <QMap>
11
12 class MainWindow : public QMainWindow
13 {
14 Q_OBJECT
15
16 public:
17 MainWindow(QWidget *parent = 0);
18 ~MainWindow();
19
20 NodeUI *selectedNodeUI();
21 bool isNodeUiClicked();
22 void nodeUiSizeAdjust();
23 //var
24
25 protected:
26
27
28 private:
29
30 void GetScreenInfo();
31 QGraphicsView *view;
32 //QGraphicsScene *scene;
33 MyScene *scene;
34 //instead of (NodeUI *nodeui;)&(QPointF nodeUiPos;)
35 //目前弃用,由于QMap的顺序无法人为设定,按照内部key自动升序
36 //QMap<NodeUI*,QPointF>nodeUiMaps;
37 //NodeUI *currentNodeUI;
38 //nodeui pressed or released
39 volatile bool mPressed;
40
41 QList<NodeUI*> nodeUiLists;
42 QList<QPointF> nodeUiPosLists;
43 QList<QPixmap> nodeUiPixmapLists;
44 /*
45 struct {
46 QList<NodeUI*> nodelists;
47 QList<QPointF> poslists;
48 }ss;
49 */
50 //弃用
51 NodeUI *nodeui;
52 QPointF nodeUiPos;
53
54 //sceen size info;
55 qint16 sceenSizeX;
56 qint16 sceenSizeY;
57 private slots:
58 void isMoving(QPointF &pos);
59 void isPressed();
60 void isReleased();
61 void selectionChanged();
62
63 signals:
64 void nodeUiClicked(NodeUI* node);
65 };
66
67 #endif // MAINWINDOW_H
mainwindow.cpp
1 #include "mainwindow.h"
2 #include <QDesktopWidget>
3 #include <QApplication>
4 #include <QPixmap>
5 #include <QGraphicsItem>
6 #include <QMouseEvent>
7 #include <QWidget>
8 #include <QGraphicsPixmapItem>
9 #include <QMessageBox>
10 #include <QDebug>
11
12
13 const qreal MY_NODEUI_POS_Y = 200;
14 const qreal MY_NODEUI_DIS = 110;
15 const qreal MY_NODEUI_STA = 90;
16 const int MYNODEUI_SIZE = 100;
17 const int MYNODEUI_SIZE_M = 20;
18 const int SCREEN_SIZE = 800;
19 MainWindow::MainWindow(QWidget *parent)
20 : QMainWindow(parent)
21 {
22 //初始化
23 mPressed = false;
24 //get windows size
25 GetScreenInfo();
26
27 view = new QGraphicsView;
28 scene = new MyScene();
29 scene->setSceneRect(0,0,800,480);
30
31 //new
32 QString file;
33 QString text;
34 QPointF pos;
35 NodeUI* node;
36
37 //HOME:1
38 file = QString(":/images/home.png");
39 text = QString("Home");
40 pos = QPointF(MY_NODEUI_STA,MY_NODEUI_POS_Y);
41
42 node = new NodeUI(file,text,MYNODEUI_SIZE);
43 node->setPos(pos);
44 nodeUiLists.append(node);
45 nodeUiPosLists.append(pos);
46 nodeUiPixmapLists.append(node->pixmap());
47 /*
48 here cannot delete node!!!!!!!!!!!!!!!
49 delete node;
50 */
51
52 //VIDIO:2
53 file = QString(":/images/securitycamera.png");
54 text = QString("Vidio");
55 pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*1,MY_NODEUI_POS_Y);
56
57 node = new NodeUI(file,text,MYNODEUI_SIZE);
58 node->setPos(pos);
59 nodeUiLists.append(node);
60 nodeUiPosLists.append(pos);
61 nodeUiPixmapLists.append(node->pixmap());
62
63 //APPLICATION:3
64 file = QString(":/images/application.png");
65 text = QString("Application");
66 pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*2,MY_NODEUI_POS_Y);
67
68 node = new NodeUI(file,text,MYNODEUI_SIZE);
69 node->setPos(pos);
70 nodeUiLists.append(node);
71 nodeUiPosLists.append(pos);
72 nodeUiPixmapLists.append(node->pixmap());
73
74 //NETWORK:4
75 file = QString(":/images/network-2.png");
76 text = QString("Network");
77 pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*3,MY_NODEUI_POS_Y);
78
79 node = new NodeUI(file,text,MYNODEUI_SIZE);
80 node->setPos(pos);
81 nodeUiLists.append(node);
82 nodeUiPosLists.append(pos);
83 nodeUiPixmapLists.append(node->pixmap());
84
85 //COMPUTER:5
86 file = QString(":/images/smartphone.png");
87 text = QString("Phone");
88 pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*4,MY_NODEUI_POS_Y);
89
90 node = new NodeUI(file,text,MYNODEUI_SIZE);
91 node->setPos(pos);
92 nodeUiLists.append(node);
93 nodeUiPosLists.append(pos);
94 nodeUiPixmapLists.append(node->pixmap());
95
96 //CUSTOMIZE:5
97 file = QString(":/images/customize.png");
98 text = QString("Setting");
99 pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*5,MY_NODEUI_POS_Y);
100
101 node = new NodeUI(file,text,MYNODEUI_SIZE);
102 node->setPos(pos);
103 nodeUiLists.append(node);
104 nodeUiPosLists.append(pos);
105 nodeUiPixmapLists.append(node->pixmap());
106
107 //重新计算UiSize
108 nodeUiSizeAdjust();
109
110 int i = 0;
111 foreach(NodeUI* node_temp,nodeUiLists)
112 {
113
114 node_temp->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
115
116 qDebug()<<"name:"<<node_temp->getMyText()<<nodeUiPosLists.at(i);
117
118 scene->addItem(node_temp);
119
120 i++;
121 }
122
123 //用于按钮的单机
124
125
126 view->setScene(scene);
127 //set drag mode
128 //view->setDragMode(QGraphicsView::RubberBandDrag);
129 view->setRenderHints(QPainter::Antialiasing);
130 //no menu
131 view->setContextMenuPolicy(Qt::NoContextMenu);
132
133 view->setBackgroundBrush(QImage(":/images/shuibo2.jpg"));
134 //view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
135 //view->setCacheMode(QGraphicsView::CacheBackground);
136 setCentralWidget(view);
137 setWindowTitle(tr("Main Window"));
138 }
139 //槽,当scene鼠标拖拽是执行
140 //控制UI图标的水平
141 void MainWindow::isMoving(QPointF &pos)
142 {
143 int i=0;
144 if(mPressed){
145 foreach(NodeUI* node,nodeUiLists)
146 {
147 node->setPos(nodeUiPosLists.at(i).x()+pos.x(),MY_NODEUI_POS_Y);
148 i++;
149 }
150 nodeUiSizeAdjust();
151 }
152 }
153 //槽,当nodeui鼠标按下时执行,调用selectedNodeUI函数,更新currentNodeUI变量
154 //除此之外,selectionChanged()也是一个槽,由scene调用
155 void MainWindow::isPressed()
156 {
157 selectionChanged();
158 mPressed = true;
159 }
160 //槽,当nodeui鼠标释放时执行
161 //应当设置标志位,让UI图片停止对鼠标拖动事件的响应
162 void MainWindow::isReleased()
163 {
164 mPressed = false;
165 if(isNodeUiClicked())
166 qDebug()<<"clicked";
167 qDebug()<<"release";
168 }
169
170 //槽,当scene的selectedItem变化时,发送同名信号到此槽
171 void MainWindow::selectionChanged()
172 {
173 int i=0,j=0;
174 QList<QGraphicsItem *> items = scene->selectedItems();
175 if (items.count() == 1) {
176 //当前所选择的UI图标的坐标
177 QPointF pos = items.first()->pos();
178 NodeUI* node_temp = dynamic_cast<NodeUI *>(items.first());
179 qDebug()<<"items.x:"<<pos.x()<<"items.y:"<<pos.y();
180
181 foreach(NodeUI* node,nodeUiLists)
182 {
183 if(node == node_temp)
184 break;
185 i++;
186 }
187 j=i;
188 i=0;
189 foreach(QPointF ppos,nodeUiPosLists)
190 {
191 nodeUiPosLists[i].setX((i-j)*MY_NODEUI_DIS+pos.x());
192 nodeUiPosLists[i].setY(MY_NODEUI_POS_Y);
193 i++;
194 }
195
196 } else {
197 return;
198 }
199 }
200 //判断是否Nodeui接收的是否是单击信号。
201 //判断依据是当前单击的nodeui对象的pos与存储在nodeUiPosListsd的位置比较,相等则为单击
202 bool MainWindow::isNodeUiClicked()
203 {
204 int i=-1;
205 QList<QGraphicsItem *> items = scene->selectedItems();
206 if (items.count() == 1) {
207 QPointF pos = items.first()->pos();
208 NodeUI* node_temp = dynamic_cast<NodeUI *>(items.first());
209 if(pos ==nodeUiPosLists.at(i)){
210 //emit nodeUiClicked(node_temp);
211 QMessageBox::information(this,"New Window","will open : "+node_temp->getMyText());
212 return true;
213 }
214 }
215 return false;
216 }
217 void MainWindow::nodeUiSizeAdjust()
218 {
219 quint16 i=0;
220 foreach(NodeUI* node,nodeUiLists)
221 {
222 //qDebug()<<"i= "<<i;
223 QPointF pos=node->pos();
224
225 pos.setX(node->pos().x()+MYNODEUI_SIZE/2);
226 //pos.setX(node->pos().x()+node->pixmap().width());
227 if(pos.x()>=0 && pos.x()<=SCREEN_SIZE/2)
228 {
229 //(MYNODEUI_SIZE-MYNODEUI_SIZE_M)/(SCREEN_SIZE/2)==(size-20)/pos.x()
230 quint16 size=pos.x()/5+20;
231 QPixmap pixmap = nodeUiPixmapLists.at(i);
232 //QPixmap pixmap = nodeUiLists.at(i)->pixmap();
233 pixmap = pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
234 nodeUiLists[i]->setPixmap(pixmap);
235 }
236
237 //if(pos.x()>SCREEN_SIZE/2 && pos.x()<=SCREEN_SIZE)
238 if(pos.x()>SCREEN_SIZE/2 && pos.x()<=SCREEN_SIZE+10)
239 {
240 //(MYNODEUI_SIZE-MYNODEUI_SIZE_M)/(SCREEN_SIZE/2)==(size-20)/pos.x()
241 quint16 size=(SCREEN_SIZE-pos.x())/5+20;
242 QPixmap pixmap = nodeUiPixmapLists.at(i);
243 //QPixmap pixmap = nodeUiLists.at(i)->pixmap();
244 pixmap = pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
245 nodeUiLists[i]->setPixmap(pixmap);
246 }
247 i++;
248 }
249 }
250 MainWindow::~MainWindow()
251 {
252 }
253 //获取设备分辨率的呢个信息
254 void MainWindow::GetScreenInfo()
255 {
256 QDesktopWidget* desktopWidget = QApplication::desktop();
257 //获取可用桌面大小
258 //QRect deskRect = desktopWidget->availableGeometry();
259 //获取设备屏幕大小
260 QRect screenRect = desktopWidget->screenGeometry();
261
262 sceenSizeX = screenRect.width();
263 sceenSizeY = screenRect.height();
264
265 //获取系统设置的屏幕个数(屏幕拷贝方式该值为1)
266 //g_nScreenCount = desktopWidget->screenCount();
267 }
最后是main.cpp
实例化MainWindow
1 #include <QtGui/QApplication>
2 #include "mainwindow.h"
3
4
5
6 int main(int argc, char *argv[])
7 {
8 QApplication a(argc, argv);
9 MainWindow w;
10
11 w.setWindowOpacity(1);
12 w.setWindowFlags(Qt::FramelessWindowHint);
13 w.setAttribute(Qt::WA_TranslucentBackground);
14 w.show();
15 //w.showFullScreen();
16
17 return a.exec();
18 }