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

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

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

图2

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

图3

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


以下是源程序文件夹结构:

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

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学习笔记(四)中,记录一下,以备不时之需

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118484.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Google资深工程师深度讲解Go语言-函数式编程(六)

    Google资深工程师深度讲解Go语言-函数式编程(六)

    2022年2月16日
    43
  • canbus速率_erie canal

    canbus速率_erie canalDatabus和canal都能够提供实时从数据库获取变更,并提供给下游的实时消费流的功能。本文针对两个系统实现和应用上的不同点,做了一个简单的对比:对比项Databuscanal结论支持的

    2022年8月5日
    3
  • 轨迹规划——Bezier曲线与B样条曲线

    轨迹规划——Bezier曲线与B样条曲线一、Bezier曲线1、Bezier曲线的背景给定n+1个数据点,p0~pn,生成一条曲线,使得该曲线与这些点描述的形状相符。(如果要求曲线通过所有数据点,则属于插值问题;如果只要求曲线逼近这些数据点,则属于逼近问题。)2、Bezier曲线的定义p(t)=∑i=0naifi,n(t)p(t)=\sum_{i=0}^na_if_{i,n}(t)p(t)=i=0∑n​ai​fi,n…

    2022年6月20日
    38
  • idea实用插件大全_intellij idea插件

    idea实用插件大全_intellij idea插件?常用?MyBatisLogPlugin(控制台SQL转换成可执行SQL)?KeyPromoterX(快捷键提示)?CodeGlance(代码小地图)?FreeMybatisplugin(mapper和xml文件跳转)?GrepConsole(控制台日志过滤查看)?Lombok(简化类代码)?StringManipulation(字符串转换)?AlibabaJavaCodingGuidelines(阿里巴巴代码规约扫描)?JRebel(热部署)

    2022年8月31日
    2
  • latex中如何正确输入 双引号「建议收藏」

    latex中如何正确输入 双引号「建议收藏」latex中输入双引号时,如果都直接用键盘上的双引号键,打出的是一顺撇的。左面引号的正确输入法是:按两次“Tab上面,数字1左面那个键”。至于后边的引号,与老方法是一样的,即按两次单引号键(或一次SHIFT+单引号键—也就是一次双引号键啦怎么输入左单引号、左双引号、右单引号、有双引号?左单引号:`(键盘上1旁边的那个);左双引号:“;右单引号:'(键盘分号的右边那个);右双引号:”或”。在

    2022年4月19日
    929
  • 【STM32】STM32CubeMX教程二–基本使用(新建工程点亮LED灯)

    【STM32】STM32CubeMX教程二–基本使用(新建工程点亮LED灯)前言在配置好CubeMX之后,就是新建工程的开始了,那么首先我们需要一些准备,本片博客我们会很详细的介绍STM32CubeMx的基本使用和如何创建一个新的工程并且点亮LED灯面向初学者如果您想着快速实现工程的创建,可以直接跳过功能介绍,观看工程创建一栏并且,在新建工程时,我们分为了具体流程1~7如果您不想看每部分的讲解,直接按照流程操作即可,5分钟即可成功点亮LED灯安装…

    2022年6月14日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

评论列表(1条)

  • 匿名的头像
    匿名 2022年9月14日 下午7:44

    代码不能下载了

关注全栈程序员社区公众号