一杯清酒邀明月
天下本无事,庸人扰之而烦耳。

先看看运行效果,我用的群创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 }

 

posted on 2020-06-10 14:41  一杯清酒邀明月  阅读(885)  评论(0编辑  收藏  举报