zoukankan      html  css  js  c++  java
  • Qt QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果

    先看看运行效果,我用的群创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 }
  • 相关阅读:
    记录 vue 中使用 SVG 渐变填充遇到过的坑
    关于map some filter every等遍历的一些临时记忆
    Blob文件处理
    电子签名 VUE加canvas实现 移动端和PC实现
    js导出excell表
    video
    移植QT5.6到嵌入式开发板(史上最详细的QT移植教程)
    Ubuntu16.04打开Qt显示/home/user/.config/QtProject/qtcreator/qtversion.xml : Permission denied
    哨兵2号影像数据获取以及处理流程
    Sentinel-2 哨兵二号数据下载及处理教程
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13085021.html
Copyright © 2011-2022 走看看