前言
记录一下自己想做的一个小项目的过程,主要是看到了有一款桌面软件很有意思,名叫 Desktop Goose,他应该是使用Unity去做的,我也想有一个自己的要是能够将它的功能复现并且还能加上播放音乐,根据时间提示我该去干嘛了等功能就更好了。话不多说,说干就干,再写这篇文章的时候,已经能将大鹅的基本功能进行实现。
阶段一
阶段一先实现大鹅的基础功能,能够每经过一段事件进行移动,并且会有一定的速度,要能够在之后进行速度控制,并且在移动时不能拖动。
我使用Qt 的 QThread 类来创建新线程来控制鹅在桌面上的移动速度,这样方便之后让我的大鹅能够拥有自己的速度。并且能够在该线程中每隔一段事件移动一下大鹅的位置。
该线程的.h代码:
#ifndef GOOSETHREAD_H
#define GOOSETHREAD_H
#include <QRect>
#include <QThread>
#include <QTimer>
#include <cstdlib>
#include <ctime>
#include <QGuiApplication>
#include <QScreen>
#include <QApplication>
#include <qmath.h>
extern QPoint currentPosition;
class GooseThread : public QThread
{
Q_OBJECT
public:
explicit GooseThread(QObject *parent = nullptr);
void run() override;
void onTimer();
bool isMoving()const;
signals:
void moveGoose(int x, int y);
//void enableMouseTracking(bool enabled);
private:
int m_speed;
int m_moveInterval = 50;
int screenWidth;
int screenHeight;
bool m_isMoving; // 添加标志变量
int m_pauseInterval = 30000;
int counter = 0;
QRect screenRect;
QTimer *m_timer;
};
#endif // GOOSETHREAD_H
该线程的.c文件代码
#include "goosethread.h"
#include "QDebug"
QPoint currentPosition(0, 0); // 初始化大鹅位置为屏幕左上角
GooseThread::GooseThread(QObject *parent):QThread(parent), m_speed(500),m_isMoving(false)
{
//QPoint currentPosition(0, 0);
// m_timer = new QTimer(this);
// connect(m_timer, &QTimer::timeout, this, &GooseThread::onTimer);
// m_timer->start(10000); // 每隔一秒钟触发一次
}
void GooseThread::run()
{
// while (true) {
// QThread::msleep(m_speed);
// }
QRect screenRect = QGuiApplication::primaryScreen()->geometry();
int screenWidth = screenRect.width();
int screenHeight = screenRect.height();
while (true) {
//emit enableMouseTracking(false);
// 生成随机位置
int x = qrand() % screenWidth;
int y = qrand() % screenHeight;
QPoint newPosition(x, y);
// 计算大鹅移动的速度和方向
qreal dx = newPosition.x() - currentPosition.x();
qreal dy = newPosition.y() - currentPosition.y();
qreal distance = qSqrt(dx * dx + dy * dy);
qreal speed = m_speed / 5000.0; // 毫秒转换为秒
qreal duration = distance / speed;
qreal vx = dx / duration;
qreal vy = dy / duration;
m_isMoving = true; // 开始移动,禁止鼠标拖拽事件
// 更新大鹅的位置
for (qreal t = 0; t < duration; t += m_moveInterval) {
currentPosition.setX(currentPosition.x() + vx * m_moveInterval);
currentPosition.setY(currentPosition.y() + vy * m_moveInterval);
emit moveGoose(currentPosition.x(), currentPosition.y());
qDebug() << "1" <<currentPosition;
QThread::msleep(m_moveInterval);
}
m_isMoving = false; // 移动结束,允许鼠标拖拽事件
//emit enableMouseTracking(true);
currentPosition = newPosition;
msleep(m_pauseInterval);
}
}
bool GooseThread::isMoving() const
{
return m_isMoving;
}
//void GooseThread::onTimer()
//{
// QRect screenRect = QGuiApplication::primaryScreen()->geometry();
// int screenWidth = screenRect.width();
// int screenHeight = screenRect.height();
// // 设置随机数种子
// srand(time(NULL));
// // 生成随机坐标
// int newX = rand() % screenWidth;
// int newY = rand() % screenHeight;
// // 发送移动信号
// emit moveGoose(newX, newY);
//}
在这里我们定义了一个全局变量来保存大鹅的位置,将鼠标移动的坐标也保存在里面。
在主窗口中,我暂时添加了鼠标拖拉大鹅,判断是否大鹅在移动,移动的时候将拖拽事件禁止 。
widget.cpp代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
m_Menu = new QMenu(this);
m_Action = new QAction(this);
m_Action->setText("退出");
m_Menu->addAction(m_Action);
backgroundWidget *m_backgroundWidget = new backgroundWidget(this);
ui->backDoose->addWidget(m_backgroundWidget);
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_TranslucentBackground);
setMouseTracking(true);
m_gooseThread = new GooseThread(this);
connect(m_gooseThread, &GooseThread::moveGoose, this, &Widget::moveGoose);
connect(m_Action,&QAction::triggered,this,[=](){
qApp->exit(0);
});
//connect(m_gooseThread, &GooseThread::enableMouseTracking,this,&Widget::setMouseTrackingEnabled);
m_gooseThread->start();
}
Widget::~Widget()
{
delete ui;
}
void Widget::moveGoose(int dx, int dy)
{
this->move(dx,dy); // 移动大鹅图像
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
// if (event->buttons() & Qt::LeftButton) {
// int dx = event->pos().x() - currentPosition.x();
// int dy = event->pos().y() - currentPosition.y();
// move(x() + dx, y() + dy);
// currentPosition = event->pos();
// event->accept();
// }
if (m_gooseThread->isMoving()) { // 如果大鹅正在移动,则禁止拖拽事件
event->ignore();
return;
}
currentPosition = event->globalPos() - mOffese;
qDebug() << currentPosition;
this->move(currentPosition);
}
void Widget::mousePressEvent(QMouseEvent *event)
{
// QPoint currentPosition = mapFromGlobal(QCursor::pos());
// if (event->button() == Qt::LeftButton) {
// currentPosition = event->pos();
// event->accept();
// }
mOffese = event->globalPos() - this->pos();
}
void Widget::contextMenuEvent(QContextMenuEvent *event)
{
m_Menu->exec(QCursor::pos());
event->accept();
}
//void Widget::setMouseTrackingEnabled(bool enabled)
//{
// QWidget::setMouseTracking(enabled);
// if (enabled) {
// this->setCursor(Qt::OpenHandCursor);
// } else {
// this->setCursor(Qt::ArrowCursor);
// }
//}