• qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果


    应大家的要求,还是把完整的project文件贴出来,大家省点事:http://www.kuaipan.cn/file/id_48923272389086450.htm

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

    #ifndef MYSCENE_H
    #define MYSCENE_H
    
    #include <QGraphicsScene>
    
    class MyScene : public QGraphicsScene
    {
    Q_OBJECT
    public:
        explicit MyScene(QObject *parent = 0);
    
    private:
        void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
        void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    
    signals:
        void isMoving(QPointF &pos);
    
    public slots:
    
    private:
        QPointF  beforePos;
        QPointF  releasePos;
    };
    
    #endif // MYSCENE_H
    

    myscene.cpp

    #include "myscene.h"
    #include <QGraphicsSceneMouseEvent>
    #include <QPointF>
    #include <QDebug>
    
    
    MyScene::MyScene(QObject *parent) :
        QGraphicsScene(parent)
    {
    }
    void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        //QPointF pos = event->scenePos();
        QPointF pos(event->scenePos().x()-beforePos.x(),event->scenePos().y()-beforePos.y());
        emit isMoving(pos);
        //qDebug()<<"x:"<<pos.x()<<"y:"<<pos.y();
    }
    void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        beforePos = event->scenePos();
    }
    void MyScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
        releasePos = event->scenePos();
    }
    

    再看nodeui.h与nodeui.cpp,在原来的QGraphicsPixmapItem基础上又假如了点自己的东西

    #ifndef NODEUI_H
    #define NODEUI_H
    
    #include <QGraphicsPixmapItem>
    #include <QGraphicsItem>
    #include <QStyleOptionGraphicsItem>
    #include <QPainter>
    #include <QGraphicsSceneMouseEvent>
    #include <QPointF>
    
    class NodeUI : public QObject,public QGraphicsPixmapItem
    {
        Q_OBJECT
    public:
        NodeUI();
        NodeUI(QString &file,QString &text,int imagesize=80);
    
        //setup function
        void setMyPixmap(QString &file,int size);
        void setMyText(QString &text);
        QString getMyText();
        //virtual function
        QRectF boundingRect() const;
        QPainterPath shape() const;
    signals:
        void nodeIsMoving(QPointF &pos);
        void nodeIsPressed();
    
    
    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
        void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    private:
        //QString myImage;
        QString myText;
    
    };
    
    #endif // NODEUI_H

    nideui.cpp

    #include "nodeui.h"
    #include <QPixmap>
    #include <iostream>
    #include <QDebug>
    
    NodeUI::NodeUI()
    {
    }
    /*note: imagesize = 80 is in the nodeui.h*/
    NodeUI::NodeUI(QString &file,QString &text,int imagesize)
    {
    
        setMyText(text);
        setMyPixmap(file,imagesize);
    }
    
    void NodeUI::setMyText(QString &text)
    {
        myText = text;
    }
    
    void NodeUI::setMyPixmap(QString &file,int size)
    {
        //myImage = file;
        QPixmap pixmap;
        pixmap.load(file);
        pixmap= pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        setPixmap(pixmap);
    }
    QRectF NodeUI::boundingRect() const
    {
        QRect rect = this->pixmap().rect();
        //return QRectF(rect);
        return QRectF(0,0,rect.width(),rect.width()+15);
    }
    
    void NodeUI::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget)
    {
        QPixmap pixmap = this->pixmap();
        QRect rect = pixmap.rect();
    
        painter->drawPixmap(rect,pixmap);
    
    
        //print name,calculate the text's heigh & width for center layout
        QPen pen(Qt::black);
        painter->setPen(pen);
        painter->setRenderHint(QPainter::Antialiasing);
        QFont font("Verdana",8, QFont::Normal);
        painter->setFont(font);
        painter->drawText(QRectF(0,rect.height(),rect.width(),15),Qt::AlignCenter,myText);
    
        if (option->state & QStyle::State_Sunken)
        {
            QRectF rect1 = boundingRect();
            //QPen pen(Qt::darkGreen);
            painter->setPen(QPen(Qt::darkGreen));
        }else
        {
    
        }
    }
    QPainterPath NodeUI::shape() const
    {
        QRectF rect = boundingRect();
    
        QPainterPath path;
        path.addRoundRect(rect, 5,5);
        return path;
    }
    
    void NodeUI::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        emit nodeIsPressed();
        qDebug()<<"pressed";
        QGraphicsItem::mousePressEvent(event);
    }
    void NodeUI::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
        update(boundingRect());
        QGraphicsItem::mouseReleaseEvent(event);
    }
    QString NodeUI::getMyText()
    {
        return myText;
    }
    

    最后是scene与item的文件mainwindow.cpp,继承了QMainWindow,作用就是画一个应用程序框架

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QtGui/QMainWindow>
    #include <QGraphicsView>
    #include <QGraphicsScene>
    #include <QPointF>
    #include "nodeui.h"
    #include "myscene.h"
    #include <QMap>
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        NodeUI *selectedNodeUI();
        bool isNodeUiClicked();
        void nodeUiSizeAdjust();
        //var
    
    protected:
    
    
    private:
    
        void GetScreenInfo();
        QGraphicsView *view;
        //QGraphicsScene *scene;
        MyScene *scene;
        //instead of (NodeUI *nodeui;)&(QPointF nodeUiPos;)
        //眼下弃用,因为QMap的顺序无法人为设定,依照内部key自己主动升序
        //QMap<NodeUI*,QPointF>nodeUiMaps;
        //NodeUI *currentNodeUI;
        //nodeui pressed or released
        volatile bool mPressed;
    
        QList<NodeUI*> nodeUiLists;
        QList<QPointF> nodeUiPosLists;
        QList<QPixmap> nodeUiPixmapLists;
    /*
        struct {
            QList<NodeUI*> nodelists;
            QList<QPointF> poslists;
        }ss;
        */
        //弃用
        NodeUI *nodeui;
        QPointF nodeUiPos;
    
        //sceen size info;
        qint16 sceenSizeX;
        qint16 sceenSizeY;
    private slots:
        void isMoving(QPointF &pos);
        void isPressed();
        void isReleased();
        void selectionChanged();
    
    signals:
        void nodeUiClicked(NodeUI* node);
    };
    
    #endif // MAINWINDOW_H
    
    mainwindow.cpp

    #include "mainwindow.h"
    #include <QDesktopWidget>
    #include <QApplication>
    #include <QPixmap>
    #include <QGraphicsItem>
    #include <QMouseEvent>
    #include <QWidget>
    #include <QGraphicsPixmapItem>
    #include <QMessageBox>
    #include <QDebug>
    
    
    const qreal MY_NODEUI_POS_Y = 200;
    const qreal MY_NODEUI_DIS = 110;
    const qreal MY_NODEUI_STA = 90;
    const int   MYNODEUI_SIZE = 100;
    const int   MYNODEUI_SIZE_M = 20;
    const int   SCREEN_SIZE = 800;
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        //初始化
        mPressed = false;
        //get windows size
        GetScreenInfo();
    
        view = new QGraphicsView;
        scene = new MyScene();
        scene->setSceneRect(0,0,800,480);
    
        //new
        QString file;
        QString text;
        QPointF pos;
        NodeUI* node;
    
        //HOME:1
        file = QString(":/images/home.png");
        text = QString("Home");
        pos = QPointF(MY_NODEUI_STA,MY_NODEUI_POS_Y);
    
        node = new NodeUI(file,text,MYNODEUI_SIZE);
        node->setPos(pos);
        nodeUiLists.append(node);
        nodeUiPosLists.append(pos);
        nodeUiPixmapLists.append(node->pixmap());
        /*
        here cannot delete node!!!!!!!!!!!!!!!
        delete node;
        */
    
        //VIDIO:2
        file = QString(":/images/securitycamera.png");
        text = QString("Vidio");
        pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*1,MY_NODEUI_POS_Y);
    
        node = new NodeUI(file,text,MYNODEUI_SIZE);
        node->setPos(pos);
        nodeUiLists.append(node);
        nodeUiPosLists.append(pos);
        nodeUiPixmapLists.append(node->pixmap());
    
        //APPLICATION:3
        file = QString(":/images/application.png");
        text = QString("Application");
        pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*2,MY_NODEUI_POS_Y);
    
        node = new NodeUI(file,text,MYNODEUI_SIZE);
        node->setPos(pos);
        nodeUiLists.append(node);
        nodeUiPosLists.append(pos);
        nodeUiPixmapLists.append(node->pixmap());
    
        //NETWORK:4
        file = QString(":/images/network-2.png");
        text = QString("Network");
        pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*3,MY_NODEUI_POS_Y);
    
        node = new NodeUI(file,text,MYNODEUI_SIZE);
        node->setPos(pos);
        nodeUiLists.append(node);
        nodeUiPosLists.append(pos);
        nodeUiPixmapLists.append(node->pixmap());
    
        //COMPUTER:5
        file = QString(":/images/smartphone.png");
        text = QString("Phone");
        pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*4,MY_NODEUI_POS_Y);
    
        node = new NodeUI(file,text,MYNODEUI_SIZE);
        node->setPos(pos);
        nodeUiLists.append(node);
        nodeUiPosLists.append(pos);
        nodeUiPixmapLists.append(node->pixmap());
    
        //CUSTOMIZE:5
        file = QString(":/images/customize.png");
        text = QString("Setting");
        pos = QPointF(MY_NODEUI_STA+MY_NODEUI_DIS*5,MY_NODEUI_POS_Y);
    
        node = new NodeUI(file,text,MYNODEUI_SIZE);
        node->setPos(pos);
        nodeUiLists.append(node);
        nodeUiPosLists.append(pos);
        nodeUiPixmapLists.append(node->pixmap());
    
        //又一次计算UiSize
        nodeUiSizeAdjust();
    
        int i = 0;
        foreach(NodeUI* node_temp,nodeUiLists)
        {
    
            node_temp->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
    
            qDebug()<<"name:"<<node_temp->getMyText()<<nodeUiPosLists.at(i);
    
            scene->addItem(node_temp);
    
            i++;
        }
    
        //用于button的单机
    
    
        view->setScene(scene);
        //set drag mode
        //view->setDragMode(QGraphicsView::RubberBandDrag);
        view->setRenderHints(QPainter::Antialiasing);
        //no menu
        view->setContextMenuPolicy(Qt::NoContextMenu);
    
        view->setBackgroundBrush(QImage(":/images/shuibo2.jpg"));
        //view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
        //view->setCacheMode(QGraphicsView::CacheBackground);
        setCentralWidget(view);
        setWindowTitle(tr("Main Window"));
    }
    //槽,当scene鼠标拖拽是运行
    //控制UI图标的水平
    void MainWindow::isMoving(QPointF &pos)
    {
        int i=0;
        if(mPressed){
            foreach(NodeUI* node,nodeUiLists)
            {
                node->setPos(nodeUiPosLists.at(i).x()+pos.x(),MY_NODEUI_POS_Y);
                i++;
            }
            nodeUiSizeAdjust();
        }
    }
    //槽,当nodeui鼠标按下时运行,调用selectedNodeUI函数,更新currentNodeUI变量
    //除此之外,selectionChanged()也是一个槽,由scene调用
    void MainWindow::isPressed()
    {
        selectionChanged();
        mPressed = true;
    }
    //槽,当nodeui鼠标释放时运行
    //应当设置标志位,让UI图片停止对鼠标拖动事件的响应
    void MainWindow::isReleased()
    {
        mPressed = false;
        if(isNodeUiClicked())
            qDebug()<<"clicked";
        qDebug()<<"release";
    }
    
    //槽,当scene的selectedItem变化时,发送同名信号到此槽
    void MainWindow::selectionChanged()
    {
        int i=0,j=0;
        QList<QGraphicsItem *> items = scene->selectedItems();
        if (items.count() == 1) {
            //当前所选择的UI图标的坐标
            QPointF pos = items.first()->pos();
            NodeUI* node_temp = dynamic_cast<NodeUI *>(items.first());
            qDebug()<<"items.x:"<<pos.x()<<"items.y:"<<pos.y();
    
            foreach(NodeUI* node,nodeUiLists)
            {
                if(node == node_temp)
                    break;
                i++;
            }
            j=i;
            i=0;
            foreach(QPointF ppos,nodeUiPosLists)
            {
                nodeUiPosLists[i].setX((i-j)*MY_NODEUI_DIS+pos.x());
                nodeUiPosLists[i].setY(MY_NODEUI_POS_Y);
                i++;
            }
    
        } else {
            return;
        }
    }
    //推断是否Nodeui接收的是否是单击信号。
    //推断根据是当前单击的nodeui对象的pos与存储在nodeUiPosListsd的位置比較,相等则为单击
    bool MainWindow::isNodeUiClicked()
    {
        int i=-1;
        QList<QGraphicsItem *> items = scene->selectedItems();
        if (items.count() == 1) {
            QPointF pos = items.first()->pos();
            NodeUI* node_temp = dynamic_cast<NodeUI *>(items.first());
            if(pos ==nodeUiPosLists.at(i)){
                //emit nodeUiClicked(node_temp);
                QMessageBox::information(this,"New Window","will open : "+node_temp->getMyText());
                return true;
            }
        }
        return false;
    }
    void MainWindow::nodeUiSizeAdjust()
    {
        quint16 i=0;
        foreach(NodeUI* node,nodeUiLists)
        {
            //qDebug()<<"i= "<<i;
            QPointF pos=node->pos();
    
            pos.setX(node->pos().x()+MYNODEUI_SIZE/2);
            //pos.setX(node->pos().x()+node->pixmap().width());
            if(pos.x()>=0 && pos.x()<=SCREEN_SIZE/2)
            {
                //(MYNODEUI_SIZE-MYNODEUI_SIZE_M)/(SCREEN_SIZE/2)==(size-20)/pos.x()
                quint16 size=pos.x()/5+20;
                QPixmap pixmap = nodeUiPixmapLists.at(i);
                //QPixmap pixmap = nodeUiLists.at(i)->pixmap();
                pixmap = pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
                nodeUiLists[i]->setPixmap(pixmap);
            }
    
            //if(pos.x()>SCREEN_SIZE/2 && pos.x()<=SCREEN_SIZE)
            if(pos.x()>SCREEN_SIZE/2 && pos.x()<=SCREEN_SIZE+10)
            {
                //(MYNODEUI_SIZE-MYNODEUI_SIZE_M)/(SCREEN_SIZE/2)==(size-20)/pos.x()
                quint16 size=(SCREEN_SIZE-pos.x())/5+20;
                QPixmap pixmap = nodeUiPixmapLists.at(i);
                //QPixmap pixmap = nodeUiLists.at(i)->pixmap();
                pixmap = pixmap.scaled(size,size,Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
                nodeUiLists[i]->setPixmap(pixmap);
            }
            i++;
        }
    }
    MainWindow::~MainWindow()
    {
    }
    //获取设备分辨率的呢个信息
    void MainWindow::GetScreenInfo()
    {
        QDesktopWidget* desktopWidget = QApplication::desktop();
        //获取可用桌面大小
        //QRect deskRect = desktopWidget->availableGeometry();
        //获取设备屏幕大小
        QRect screenRect = desktopWidget->screenGeometry();
    
        sceenSizeX = screenRect.width();
        sceenSizeY = screenRect.height();
    
        //获取系统设置的屏幕个数(屏幕拷贝方式该值为1)
        //g_nScreenCount = desktopWidget->screenCount();
    }
    
    
    最后是main.cpp

    实例化MainWindow

    #include <QtGui/QApplication>
    #include "mainwindow.h"
    
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
    
        w.setWindowOpacity(1);
        w.setWindowFlags(Qt::FramelessWindowHint);
        w.setAttribute(Qt::WA_TranslucentBackground);
        w.show();
        //w.showFullScreen();
    
        return a.exec();
    }
    

    大概都写了注解了,事实上看看一个名称也该大概了解其作用,写这程序时遇到的问题都记录在了前一篇qt学习笔记(四)中,记录一下,以备不时之需

  • 相关阅读:
    margin和pading的百分比值
    Vue中的computed和watch
    JS的自身属性和继承属性
    JS对象的可枚举属性和不可枚举属性
    Dart语言学习
    Practice_Test
    Lesson2 basic python_20200920
    Python 基础语法L1
    小男孩和狗的故事
    智者的故事
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4503534.html
Copyright © 2020-2023  润新知