编写一个弹幕模拟器
说明
界面有一个lineEdit 用来输入弹幕,还有一个按键用来发送弹幕,还可以输入完之后直接按enter发送弹幕,弹幕发送之后会从左边往右边飘,飘到外面之后自动消失
设计思路
- 创建一个容器用来存储弹幕
- 输入弹幕的起始x值固定y值取一定范围的随机数
- 线程发送信号
- 收到信号之后容器中的label向右移动
- 移动之后出了界面之后删除label对象
- 关闭的时候回收内存以及线程的回收
代码
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QWidget>
#include <QThread>
class mythread : public QThread
{
Q_OBJECT
public:
mythread(QObject * parent = 0);
protected:
virtual void run();
signals:
void sendMsg();
};
#endif // MYTHREAD_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
#include <QCloseEvent>
#include <QPoint>
#include <random>
#include <QDebug>
#include "mythread.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushsend_clicked();
private:
Ui::Widget *ui;
QVector<QLabel*> v;//容器用来存放QLabel
QPoint movep;//移动的位移
mythread *t; //线程
public slots:
void recvMsg();
protected:
virtual void closeEvent(QCloseEvent* ev);
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
#include <time.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
srand(time(0));
w.show();
return a.exec();
}
mythread.cpp
#include "mythread.h"
mythread::mythread(QObject * parent):
QThread(parent)
{
}
void mythread::run()
{
while(1){
emit sendMsg();
this->msleep(20);
}
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//默认每次向右移动1个单位
movep.setX(1);
movep.setY(0);
t = new mythread;
t->start();
//连接线程接受信号执行recvMsg槽函数
QObject::connect(t,SIGNAL(sendMsg()),this,SLOT(recvMsg()));\
//点击enter时也可以发送弹幕
connect(ui->lineEdit,SIGNAL(returnPressed()),this,SLOT(on_pushsend_clicked()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushsend_clicked()
{
QString str = ui->lineEdit->text();
if(!str.isEmpty()){
//必须将this传进去,不然就会在新的窗口中显示
QLabel *l = new QLabel(this);
l->setText(str);
int y =20 +rand()%180;//随机值y在20-200之间
//设置label的坐标、长宽
l->setGeometry(0,y,200,20);
l->show();
v.push_back(l);//把label存到容器中
}
ui->lineEdit->clear();//清空输入框
}
void Widget::recvMsg()
{
QVector<QLabel*>::iterator it = v.begin();
for(;it!=v.end();){
//向右移动
QPoint p = (*it)->pos() + movep;
(*it)->move(p);
//移动到400的时候删除创建的label
if(p.x() == 400){
(*it)->clear();
v.erase(it);
}else{
it++;
}
}
}
void Widget::closeEvent(QCloseEvent *ev)
{
Q_UNUSED(ev);
//删除创建的label
while(v.size()!=0){
delete v.last();
v.pop_back();
}
t->terminate();
}
效果展示
没点按钮的都是按了回车