您的位置:首页 > 编程语言 > Qt开发

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

2016-12-09 11:12 525 查看
转自:http://blog.csdn.net/ghostyu/article/details/7017112

应大家的要求,还是把完整的工程文件贴出来,大家省点事: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

[cpp]
view plain
copy

#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

[cpp]
view plain
copy

#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基础上又假如了点自己的东西

[cpp]
view plain
copy

#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

[cpp]
view plain
copy

#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

[cpp]
view plain
copy

#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

[cpp]
view plain
copy

#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++;  
    }  
  
    //用于按钮的单机  
  
  
    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

[cpp]
view plain
copy

#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学习笔记(四)中,记录一下,以备不时之需
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐