首页 > 解决方案 > 在 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;
//    }
}

标签: c++qt

解决方案


谢谢您的意见。我通过删除 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;
  }

}

当客户端未连接时,输出为:

函数正在运行

套接字未连接

插座未连接...

我可以玩游戏,但是当客户端连接时,游戏冻结。我不明白为什么。


推荐阅读