【Qt学习】 碰撞检测 & 图元绘制

目录

一:自定义图元控件

二:定时器的使用

三:动画效果

四:核心源码

五:项目完整源码分享


一:自定义图元控件

视图类,命名,继承QObject信号槽机制 

图元类,命名,继承QObject信号槽机制 

二:定时器的使用

三:动画效果

图元动画显示结果如下

利用定时器

advance

控制图元进行移动

图元相互靠近 

图元互相远离 

图元 碰撞检测

四:核心源码

myview.h .cpp【视图类】

#ifndef MYVIEW_H
#define MYVIEW_H

#include <QObject>
#include<QGraphicsView>    //视图
#include<QGraphicsScene>   //场景
#include"myitem.h"
#include<QTimer>//定时器

class myView : public QGraphicsView//派生出自己的视图类
{
    Q_OBJECT
public:
    explicit myView();

    QGraphicsScene *myScene;//视图中放置场景
    myItem *item1;
    myItem *item2;

    QTimer *timer;

signals:

public slots:
    void timeSlot();
};

#endif // MYVIEW_H
#include "myview.h"
#include<QDebug>


myView::myView()
{
    this->resize(800,800);
    QGraphicsScene *myScene = new QGraphicsScene;
    this->setScene(myScene);  //视图中添加场景
    item1 = new myItem(":/image/050302.png",1,1);//图元1类型
    item2 = new myItem(":/image/050302.png",2,1);//图元2类型
    item1->setPos(100,this->height()/2);
    item2->setPos(500,this->height()/2);
    myScene->addItem(item1);  //场景中放置图元
    myScene->addItem(item2);  //场景中放置图元

    timer = new QTimer(this);
    //connect(timer,SIGNAL(timeout()),this,SLOT(timeSlot()));
    //让场景中的图元得到控制
    connect(timer,SIGNAL(timeout()),myScene,SLOT(advance()));
    timer->start(1000);

}

void myView::timeSlot()
{
    qDebug()<<"timeSlot";

}

myitem.h .cpp 【图元类】

#ifndef MYITEM_H
#define MYITEM_H

#include <QObject>
#include<QGraphicsItem>//图元

class myItem : public QObject,public QGraphicsItem
{
    Q_OBJECT
public:
    explicit myItem(QObject *parent = 0);
    myItem(QString filename,int iType,bool isStatus);

    //碰撞检测函数
    QRectF boundingRect() const;//虚函数函数字体是斜体字
    //图元绘制函数
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    QPixmap image;  //图元图片
    int iType;      //图元类型
    bool isStatus;  //图元状态

signals:

public slots:
    void advance(int phase);//纯虚函数 -- 需要实现
};

#endif // MYITEM_H
#include "myitem.h"
#include<QPainter>
#include<QDebug>
#include"indexwin.h"

myItem::myItem(QObject *parent) : QObject(parent)
{

}

myItem::myItem(QString filename, int iType, bool isStatus)
{
    image.load(filename);
    this->iType = iType;
    this->isStatus = isStatus;

}

//碰撞 特效 需要的类
//返回值:一个矩形
QRectF myItem::boundingRect() const
{
    return QRectF(0-image.width()/2,0-image.height()/2,image.width(),image.height());

}

void myItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawPixmap(0-image.width()/2,0-image.height()/2,image.width(),image.height(),image);

}

void myItem::advance(int phase)
{
    qDebug()<<"advance";
    if(this->iType ==1)
    {
        //碰撞会将图元加到链表
        //链表数量大于0就是发生碰撞了
        if(collidingItems().count()>0)
        {
            qDebug()<<"碰撞了";
           // 跳转界面
           // IndexWin *p = new IndexWin;
           // p->show();

        }
    //坐标相对于场景进行变化  方向 位置
    this->setPos(mapToScene(2,0));//-2向左移动
    }
    if(this->iType ==2)
    {
    //坐标相对于场景进行变化  方向 位置
    this->setPos(mapToScene(-2,0));//2向右移动
    }

}

五:项目完整源码分享

indexwin.h .cpp【布局管理的学习】

#ifndef INDEXWIN_H
#define INDEXWIN_H

#include <QWidget>
#include<QVBoxLayout>//垂直布局
#include<QHBoxLayout>//水平布局
#include<QPushButton>
#include<QLineEdit>
#include<QListWidget>//制作视频页面列表

class IndexWin : public QWidget
{
    Q_OBJECT
public:
    explicit IndexWin(QWidget *parent = 0);

    QWidget *leftwin;
    QWidget *topwin;
    QWidget *indexwin;
    QWidget *rightwin;
    QListWidget *videowinlist;//制作视频页面列表
    QLineEdit *searchEdit;
    QPushButton *userBtn;
    QPushButton *vipBtn;



signals:

public slots:
    void goNewwinSlot();
};

#endif // INDEXWIN_H
#include "indexwin.h"
#include<QStringList>
#include<QDebug>
#include<QMessageBox>//弹窗
#include<QListWidget>//多个按钮显示,存放窗口的容器
#include<QDir>//路径
#include<QPixmap>//放置图片
#include<QListView>//设置图片模式

IndexWin::IndexWin(QWidget *parent) : QWidget(parent)
{
     this->resize(1500,800);

     leftwin = new QWidget();
     topwin = new QWidget();
     //indexwin = new QWidget();
     rightwin = new QWidget();
     videowinlist = new QListWidget();//视频列表

     //设置图片模式--上面图片下面名称
     videowinlist->setViewMode(QListView::IconMode);

     //获取视频图片路径
     QString videopath = QDir::currentPath()+"/image";
     qDebug()<<videopath;
     QDir dir(videopath);//查找目录

     QStringList moviename;
     moviename << "*.png";//查找.png图片

     QStringList files = dir.entryList(moviename,QDir::Files|QDir::Readable,QDir::Name);
     qDebug()<<files; //查找.png图片名

     for(int i=0;i<files.size();i++)
     {
         //显示.png图片及名称
         QListWidgetItem *newitem = new QListWidgetItem(
                     QIcon(QPixmap(videopath+"/"+files.at(i))),files.at(i));
         //设置图片尺寸
         newitem->setSizeHint(QSize(200,150));
         videowinlist->addItem(newitem);

     }

     //方法一:自定义所有控件
     //控件水平  顶部控件水平分布
     QHBoxLayout *hboxlayout = new QHBoxLayout(topwin);
     searchEdit = new QLineEdit();
     userBtn = new QPushButton();
     vipBtn = new QPushButton();
     hboxlayout->addStretch();
     hboxlayout->addWidget(searchEdit);
     hboxlayout->addWidget(userBtn);
     hboxlayout->addWidget(vipBtn);

     //方法二:动态创建所有控件
     //按钮控件垂直  左边窗口放置一个垂直布局
     QVBoxLayout *vboxlayout1 = new QVBoxLayout(leftwin);
     QStringList funBtnlist;
     funBtnlist<<"logo"<<"视频"<<"动漫"<<"电影";
     for(int i=0;i<funBtnlist.size();i++)
     {
         QPushButton *newBtn = new QPushButton(funBtnlist.at(i));
         //多个按钮绑定一个槽
         connect(newBtn,SIGNAL(clicked(bool)),this,SLOT(goNewwinSlot()));
         vboxlayout1->addWidget(newBtn);
     }
     //加空白 -- 将按钮上置
     vboxlayout1->addStretch();

     //两个窗口垂直
     //右半部分的布局放置顶部窗口和主窗口
     QVBoxLayout *rightboxlayout = new QVBoxLayout(rightwin);
     rightboxlayout->addWidget(topwin);
     //rightboxlayout->addWidget(indexwin);
     rightboxlayout->addWidget(videowinlist);

     //左边窗口和前面两个窗口垂直的部分 进行水平放置  最大的布局有this
     QHBoxLayout *mainlayout = new QHBoxLayout(this);
     mainlayout->addWidget(leftwin);//放置窗口
     //mainlayout->addLayout(rightboxlayout);//放置布局
     mainlayout->addWidget(rightwin);
}

void IndexWin::goNewwinSlot()
{
    //获取点击按钮的文本信息
    QPushButton *btn = (QPushButton *)sender();
    QString btnName = btn->text();
    qDebug()<<btn->text();
    //根据文本进行判断
    if(btnName == "logo")
    {
        //弹窗显示信息
        QMessageBox::information(NULL,"logo模块","这是logo模块测试");
    }
    if(btnName == "视频")
    {
        QMessageBox::information(NULL,"电视模块","这是电视模块测试");
    }
    if(btnName == "动漫")
    {
        QMessageBox::information(NULL,"动漫模块","这是动漫模块测试");
    }
    if(btnName == "电影")
    {
        QMessageBox::information(NULL,"电影模块","这是电影模块测试");
    }

}

usersdata.h .cpp【多用户登录的学习】

#ifndef USERSDATA_H
#define USERSDATA_H
#include<QString>//字符串

class usersdata
{
public:
    usersdata();//默认构造
    usersdata(QString username,QString userpwd);//带参构造
    void setUsername(QString username);
    QString getUsername();
    void setUserpwd(QString userpwd);
    QString getUserpwd();

private:
    QString username;
    QString userpwd;
};

#endif // USERSDATA_H
#include "usersdata.h"

usersdata::usersdata()
{

}

usersdata::usersdata(QString username, QString userpwd)
{
    this->username = username;
    this->userpwd = userpwd;
}

void usersdata::setUsername(QString username)
{
    this->username = username;
}

QString usersdata::getUsername()
{
    return username;
}

void usersdata::setUserpwd(QString userpwd)
{
    this->userpwd = userpwd;
}

QString usersdata::getUserpwd()
{
    return userpwd;
}

widget.h .cpp 【绘制界面 以及 信号和槽的学习】

#ifndef WIDGET_H
#define WIDGET_H

#include<QPushButton>//按钮
#include<QLineEdit>//编辑框
#include<QLabel> //文本
#include<QMovie> //动态图

#include <QWidget>
#include<QList>
#include"usersdata.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
    QPushButton *loginBtn; //登录按钮
    QLineEdit *userEdit;   //用户编辑框
    QLineEdit *pwdEdit;    //密码编辑框
    QLabel *logoLab;       //logo文本,放置图片
    QLabel *userLab;       //用户文本
    QLabel *pwdLab;        //密码文本
    QLabel *loginLab;      //登录界面文本
    QLabel *gifLab;        //放置动态图文本
    QMovie *movie;         //动态图

    QList<usersdata *> userlist;//用户链表

//所有槽函数的定义使用
public slots:
    void goLoginSlot();
};

#endif // WIDGET_H
#include "widget.h"
#include<QDebug>     //输出头文件
#include"indexwin.h" //主界面窗口
#include<QDesktopWidget>//分辨率

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //数据类的准备
    usersdata *user1 = new usersdata("admin","123456");
    usersdata *user2 = new usersdata("manager","123456");
    userlist.append(user1);
    userlist.append(user2);

    //窗口大小设置
    this->resize(500,400);

    //setWindowFlags(Qt::FramelessWindowHint);//无边框
    //setAttribute(Qt::WA_TranslucentBackground);//背景透明

    QDesktopWidget w;

    int deskWidth = w.width();
    int deskHeight = w.height();

    qDebug()<<deskWidth<<deskHeight;

    //创建对象
    loginBtn = new QPushButton(this);
    userEdit = new QLineEdit(this);
    pwdEdit = new QLineEdit(this);
    logoLab = new QLabel(this);
    userLab = new QLabel(this);
    pwdLab = new QLabel(this);
    loginLab = new QLabel(this);
    gifLab = new QLabel(this);

    gifLab->resize(100,100);              //动态图文本大小
    movie = new QMovie("image/0505.gif"); //创建对象-动态图选择
    gifLab->setMovie(movie);              //放置动态图
    movie->start();                       //动态图显示

    // loginBtn->setText("登录");
    //登录按钮的起始位置,宽高设置
    loginBtn->setGeometry(200,200,100,50);
    //在登录按钮中放置图片
    loginBtn->setIcon(QIcon(QPixmap(":/image/050302.png")));
    //图片自适应按钮大小
    loginBtn->setIconSize(QSize(100,50));

    //userEdit->setGeometry(200,100,250,20);
    //pwdEdit->setGeometry(200,150,250,20);
    //用户编辑框起始位置
    userEdit->move(200,100);
    //用户编辑框提示内容信息
    userEdit->setPlaceholderText("请输入用户名");
    //用户编辑框设置输入长度
    userEdit->setMaxLength(11);
    //密码编辑框起始位置
    pwdEdit->move(200,150);
    //密码编辑框提示内容信息
    pwdEdit->setPlaceholderText("请输入密码");
    //密码编辑框设置输入长度
    pwdEdit->setMaxLength(8);
    //密码编辑框设置输入内容密文显示
    pwdEdit->setEchoMode(QLineEdit::Password);

    //logo文本大小
    //logoLab->resize(100,50);
    //放置logo图片到logoLab文本中
    //logoLab->setPixmap(QPixmap(":/image/050301.png").scaled(logoLab->size()));

    //用户名文本起始位置
    userLab->move(100,100);
    //用户名文本内容
    userLab->setText("用户名");
    //密码文本起始位置
    pwdLab->move(100,150);
    //密码文本内容
    pwdLab->setText("密码");
    //登录文本位置
    loginLab->move(250,40);
    //登录文本内容
    loginLab->setText("登录界面");

    //按钮点击让窗口关闭
    //connect(loginBtn,SIGNAL(clicked(bool)),this,SLOT(close()));
    //点击按钮跳转主界面
    connect(loginBtn,SIGNAL(clicked(bool)),this,SLOT(goLoginSlot()));
}

Widget::~Widget()
{

}


void Widget::goLoginSlot()
{
    qDebug()<<"点击登录";

    //获取 编辑框内容
    QString username = userEdit->text();
    //qDebug()<<username;
    QString userpwd = pwdEdit->text();

    //字符串形式toLatin1转成数组形式
    for(int i=0;i<userlist.size();i++)
    {
        //if(strcmp(username.toLatin1(),userlist.at(i)->getUsername().toLatin1()) == 0
        // &&strcmp(userpwd.toLatin1(),userlist.at(i)->getUserpwd().toLatin1()) == 0)
        if(username.compare(username,userlist.at(i)->getUsername())==0
                &&userpwd.compare(userpwd,userlist.at(i)->getUserpwd())==0)
        {
            qDebug()<<"登录成功";
            IndexWin *p = new IndexWin;
            p->show();
            this->hide();
        }
    }
}

main.cpp

#include "widget.h"
#include <QApplication>
#include"indexwin.h"
#include<QGraphicsScene>   //场景
#include<QGraphicsRectItem>//图元
#include<QGraphicsView>    //视图
#include<QTransform>
#include"myview.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    myView w;
    w.show();



    return a.exec();
}
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的示例,演示如何在Qt中使用鼠标绘制直线图: ```cpp #include <QtGui> #include <Widgets> class Line : public QGraphicsLineItem { public: Line(const QLineF& line) : QGraphicsLineItem(line) {} QRectF boundingRect() const override { return pen().widthF() + 20.0 + QGraphicsLineItem::boundingRect(); } QPainterPath shape() const override { QPainterPath path = QGraphicsLineItem::shape(); path.addRect(boundingRect()); return path; } void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override { if (option->state & QStyle::State_Selected) { painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine)); painter->drawRect(boundingRect()); } QGraphicsLineItem::paint(painter, option, widget); } }; class GraphicsView : public QGraphicsView { public: GraphicsView(QWidget* parent = nullptr) : QGraphicsView(parent), m_isDrawing(false), m_line(nullptr) { setRenderHint(QPainter::Antialiasing); setDragMode(QGraphicsView::RubberBandDrag); setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing); setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); setSelectionMode(QGraphicsView::SingleSelection); } protected: void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { m_startPos = mapToScene(event->pos()); m_isDrawing = true; } QGraphicsView::mousePressEvent(event); } void mouseMoveEvent(QMouseEvent* event) override { if (m_isDrawing) { if (!m_line) { m_line = new Line(QLineF(m_startPos, mapToScene(event->pos()))); scene()->addItem(m_line); } else { m_line->setLine(QLineF(m_startPos, mapToScene(event->pos()))); } } QGraphicsView::mouseMoveEvent(event); } void mouseReleaseEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton && m_isDrawing) { m_isDrawing = false; m_line = nullptr; } QGraphicsView::mouseReleaseEvent(event); } private: bool m_isDrawing; QPointF m_startPos; Line* m_line; }; int main(int argc, char* argv[]) { QApplication app(argc, argv); QGraphicsScene scene; GraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setScene(&scene); view.setDragMode(QGraphicsView::RubberBandDrag); QGraphicsLineItem* line = new QGraphicsLineItem(QLineF(0.0, 0.0, 100.0, 100.0)); line->setPen(QPen(Qt::red, 2)); scene.addItem(line); QGraphicsEllipseItem* ellipse = new QGraphicsEllipseItem(QRectF(0.0, 0.0, 100.0, 100.0)); ellipse->setPen(QPen(Qt::blue, 2)); ellipse->setBrush(QBrush(Qt::green)); scene.addItem(ellipse); view.setSceneRect(-150, -150, 300, 300); view.setFixedSize(300, 300); view.show(); return app.exec(); } ``` 该示例演示了如何使用QGraphicsView和QGraphicsScene来绘制直线。在鼠标按下时,记录起始位置,并在鼠标移动时绘制直线。在鼠标释放时,停止绘制。该示例还演示了如何添加其他类型的图元,如椭圆和直线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chenruhan_QAQ_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值