c++ - 在 GUI 应用程序中使用线程
问题描述
我正在制作一个多人游戏。我需要接受客户的命令。这意味着我有 GUI 和 TcpServer。所以我需要同时工作。我使用了线程,但它不起作用。你能帮我找出问题吗?总结:首先玩家按下“在线”按钮。然后 Oyun() Gui 函数运行并且按钮与 connectPressed() 函数连接。在这个函数中,有一个线程可以在 Gui 工作时运行读取客户端命令。
首先,我使用 QTimer 以每 1 秒从客户端获取命令。但是我的 GUI 冻结了。然后我使用了 QThread,但根据我的研究,QThread 不适合 GUI 应用程序。所以我找到了 Qtconcurrent、QFutureWatcher 和 QFuture。但我的线程仍然无法正常工作。我应该在某个地方犯了错误。
#include <QApplication>
#include <anaclass.h>
#include <player2.h>
#include <tcpserver.h>
#include <QThread>
#include <QObject>
//#include <worker.h>
AnaClass *anaclass;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
anaclass = new AnaClass();
anaclass->show();
anaclass->Giris(); //button selection page
return a.exec();
}
#include "anaclass.h"
Puan *puanlama1;
Puan *puanlama2;
player2 *yilan2;
AnaClass::AnaClass() : QGraphicsView()
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setFixedSize(800,600);
scene = new QGraphicsScene;
scene->setSceneRect(0,0,800,600);
setScene(scene);
}
void AnaClass::Giris()
{
connectButton = new Button("Online");
double cxPos = this->width()/2 - connectButton->boundingRect().width()/2;
double cyPos= 425;
connectButton->setPos(cxPos, cyPos);
connect(connectButton, SIGNAL(clicked()), this, SLOT(connectPressed()));
scene->addItem(connectButton);
}
void AnaClass::Oyun()
{
scene->clear();
puanlama1 = new Puan();
puanlama1->setDefaultTextColor(Qt::blue);
puanlama1->setPos(5, 2);
scene->addItem(puanlama1);
yilan = new Yilan();
yilan->setRect(0,0,19,19);
scene->addItem(yilan);
yilan->setFlags(QGraphicsItem::ItemIsFocusable);
yilan->setFocus();
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::blue);
yilan->setBrush(brush);
if(stringButtonName == "Player2" || stringButtonName == "Online")
{
yilan->setPos(scene->width()/2 + 60, scene->height()/2);
}
else
{
yilan->setPos(scene->width()/2, scene->height()/2);
}
if(stringButtonName == "Player2" || stringButtonName == "Online")
{
yilan->playerNumber=1;
puanlama2 = new Puan();
puanlama2->setDefaultTextColor(Qt::green);
puanlama2->setPos(700, 2);
scene->addItem(puanlama2);
yilan2 = new player2();
yilan2->setRect(0,0,19,19);
scene->addItem(yilan2);
yilan2->setFlags(QGraphicsItem::ItemIsFocusable);
yilan2->setFocus();
QBrush brush2;
brush2.setStyle(Qt::SolidPattern);
brush2.setColor(Qt::green);
yilan2->setBrush(brush2);
yilan2->setPos(scene->width()/2 - 60,scene->height()/2);
}
emit emitTcp();
}
void AnaClass::connectPressed()
{
qDebug()<<"connect basildi";
server = new TCPServer();
server->Test();
stringButtonName = connectButton->buttonName;
qDebug()<<"Gelen Veri " + server->OkunanBilgi;
QFutureWatcher<void> watcher;
connect(&watcher, SIGNAL(finished()), server, SLOT(daimaOku()), Qt::QueuedConnection);
QFuture<void> deneme = QtConcurrent::run(this, &AnaClass::emitTcp);
watcher.setFuture(deneme);
Oyun();
}
}
#ifndef ANACLASS_H
#define ANACLASS_H
#include <QGraphicsScene>
#include <QGraphicsView>
#include <yilan.h>
#include <Meyve.h>
#include <QBrush>
#include <Puan.h>
#include <player2.h>
#include <QThread>
#include <label.h>
#include <QKeyEvent>
#include <button.h>
#include <QDebug>
#include <tcpserver.h>
#include <QTime>
#include <QTimer>
#include <QMutex>
//#include <worker.h>
#include <QFuture>
#include <QtConcurrent>
#include <QFutureWatcher>
class AnaClass : public QGraphicsView
{
Q_OBJECT
public:
AnaClass();
void Giris();
void Oyun();
void timerEvent(QTimerEvent *event);
void keyPressEvent(QKeyEvent *event2);
public:
Yilan *yilan;
//QThread *thread;
QGraphicsScene *scene;
Label *label1;
Button* player1Button;
Button* player2Button;
Button* connectButton;
TCPServer *server;
QTimer *timerOnline;
public:
int k=0;
int t=0;
QString stringButtonName;
signals:
void emitTcp();
public slots:
void connectPressed();
void player1Pressed();
void player2Pressed();
};
#endif // ANACLASS_H
#define TCPSERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
#include <QObject>
#include <QTimer>
class TCPServer : public QObject
{
Q_OBJECT
public:
TCPServer(QObject* parent = nullptr);
void Test();
signals:
//void emitTcp();
public slots:
void newConnection();
void daimaOku(); // always read as english
public:
QTcpServer *server;
QTcpSocket *socket;
QTimer *timerTcp;
QString OkunanBilgi;
};
#endif // TCPSERVER_H
#include "tcpserver.h"
TCPServer::TCPServer(QObject * parent) : QObject()
{
}
void TCPServer::Test()
{
server = new QTcpServer();
connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
if(!server->listen(QHostAddress::Any, 1234))
{
qDebug()<<"server baslamadi";
}
else
{
qDebug()<<"server basladi";
}
//timerTcp = new QTimer();
//connect(timerTcp, SIGNAL(timeout()), this, SLOT(daimaOku()));
//emit emitTcp();
}
void TCPServer::newConnection()
{
qDebug()<<"newconnection";
socket = server->nextPendingConnection();
socket->write("Merhaba Client");
socket->flush();
socket->waitForBytesWritten(5000);
timerTcp->start(50);
}
void TCPServer::daimaOku() //alwaysread() as english
{
qDebug()<<"always read function is working";
// if(socket->state() == QAbstractSocket::ConnectedState)
// {
// qDebug()<<"Daima oku fonsiyonu soket bagli";
// socket->waitForReadyRead();
// OkunanBilgi = socket->readAll();
// qDebug()<<"Tcp daima oku :" + OkunanBilgi;
// }
}
解决方案
谢谢您的意见。我通过删除 QFuture 并添加如下所示的 connect() 解决了这个问题。
timerOnline = new QTimer();
connect(timerOnline, SIGNAL(timeout()), server, SLOT(daimaOku()));
timerOnline->start(500);
但我还有另一个问题。当客户端连接服务器时,我的 Gui 应用程序冻结。您可以在下面找到修改后的代码。
void TCPServer::daimaOku()
{
qDebug()<<"Function is running";
if(socket->state() == QAbstractSocket::UnconnectedState)
{
qDebug()<<"Socket is not connected";
}
else
{
qDebug()<<"Socket connected";
socket->waitForReadyRead();
OkunanBilgi = socket->readAll();
qDebug()<<"Tcp always read :" + OkunanBilgi;
}
}
当客户端未连接时,输出为:
函数正在运行
套接字未连接
插座未连接...
我可以玩游戏,但是当客户端连接时,游戏冻结。我不明白为什么。
推荐阅读
- linux - 在 bash 中使用 /home/ 目录从所有用户创建菜单
- python - 光标返回
而不是返回对象本身 - go - golang 对 localhost 的处理
- javascript - 发送 cognito 身份验证作为承诺给出“无法读取未定义的属性'承诺'”
- wordpress - 将数据从 Woocommerce 结帐页面发送到另一个路径
- json - 如何从 SWIFT 中的 json 对象获取 json 数组?
- pdf - ghostscript:将 PDF 转换为灰色,为文本保留纯黑色
- amazon-web-services - 删除查询使我的表越来越大
- angular - 使用 router.navigate 从上一页导航时未调用 ngOnInit 和 Constructor
- php - 在 Salesforce Lightning API curl/php 中创建记录