首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在QThread和QGui之间传递参数?

如何在QThread和QGui之间传递参数?
EN

Stack Overflow用户
提问于 2019-06-11 02:28:00
回答 1查看 147关注 0票数 0

我在后台套接字编程的QtGui应用程序上工作,我想从图形用户界面中的行编辑中获取IP地址和端口,并将其传递给QThread,线程是work,但我不能传递参数,我尝试使用构造函数,但它停止所有项目。

在开始QThread工作之前,我想从Gui中将参数传递给类中的构造函数或自定义函数。

此外,我需要使从套接字接收的数据绘图。所以为了解决这个问题,我尝试将对象指针传递给类,但是得到了很多bug

这里是线程代码和ui代码

代码语言:javascript
复制
//client code
#include "clientclass.h"
#include <QThread>
#include <QDebug>

clientClass::clientClass(char *serverIp, unsigned int serverPort, char *idname ="SCR")
{
    this->ip=serverIp;
    this->port=serverPort;
    this->id=idname;


    std::cout<<ip<<port<<id<<std::endl;

};

int clientClass::connection()
{

    SOCKET socketDescriptor;
    int numRead;

    char id[20]="SCR";

    unsigned int maxEpisodes;
    unsigned int maxSteps;
    char trackName[1000];
    BaseDriver::tstage stage;

    tDriver drive;
    strcpy(drive.trackName,trackName);
    drive.stage = stage;


    tSockAddrIn serv_addr;
    struct timeval timeVal;
    fd_set readSet;
    char buf[UDP_MSGLEN];

    // Create a socket (UDP on IPv4 protocol)
    socketDescriptor = socket(AF_INET, SOCK_DGRAM, 0);
    if (INVALID(socketDescriptor))
    {
        response = "Error: cannot create socket";
        return (1);
    }

    // Set some fields in the serverAddress structure.

    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons((this->port));
    serv_addr.sin_addr.s_addr = inet_addr(this->ip);
    //std::cout<<serv_addr.sin_port<<std::endl;
    std::cout<<serv_addr.sin_addr.s_addr<<std::endl;

    bool shutdownClient=false;
    unsigned long curEpisode=0;
    do
    {

        do
        {
            // Initialize the angles of rangefinders
            float angles[19];
            drive.init(angles);
            string initString = SimpleParser::stringify(string("init"),angles,19);
            response =QString ("Sending id to server: %1").arg(id);
            initString.insert(0,id);
            response =QString("Sending init string to the server");
            if (sendto(socketDescriptor, initString.c_str(), initString.length(), 0,
                       (struct sockaddr *) &serv_addr,
                       sizeof(serv_addr)) < 0)
            {

                response ="Error: cannot send data ";
                CLOSE(socketDescriptor);
                return (1);
            }

            // wait until answer comes back, for up to UDP_CLIENT_TIMEUOT micro sec
            FD_ZERO(&readSet);
            FD_SET(socketDescriptor, &readSet);
            timeVal.tv_sec = 0;
            timeVal.tv_usec = UDP_CLIENT_TIMEUOT;

            if (select(socketDescriptor+1, &readSet, NULL, NULL, &timeVal))
            {
                // Read data sent by the solorace server
                memset(buf, 0x0, UDP_MSGLEN);  // Zero out the buffer.
                numRead = recv(socketDescriptor, buf, UDP_MSGLEN, 0);
                if (numRead < 0)
                {
                    response ="Error: didn't get response from server";
                }
        else
        {
                    response = "Received";

                    if (strcmp(buf,"***identified***")==0)
                            break;
                }
          }

        }  while(1);

    unsigned long currentStep=0;

        while(1)
        {
            // wait until answer comes back, for up to UDP_CLIENT_TIMEUOT micro sec
            FD_ZERO(&readSet);
            FD_SET(socketDescriptor, &readSet);
            timeVal.tv_sec = 0;
            timeVal.tv_usec = UDP_CLIENT_TIMEUOT;



            cout<<"in connection"<<endl;



            if (select(socketDescriptor+1, &readSet, NULL, NULL, &timeVal))
            {
                // Read data sent by the solorace server
                memset(buf, 0x0, UDP_MSGLEN);  // Zero out the buffer.
                numRead = recv(socketDescriptor, buf, UDP_MSGLEN, 0);

                if (numRead < 0)
                {
                    response = "Error : didn't get response from server";
                    CLOSE(socketDescriptor);
                    return (1);
                }

                if (strcmp(buf,"***shutdown***")==0)
                {
                    drive.onShutdown();
                    shutdownClient = true;
                    response="Client Shutdown";
                    break;
                }

                if (strcmp(buf,"***restart***")==0)
                {
                    drive.onRestart();
                    response ="Client Restart";
                    break;
                }
                /**************************************************
                 * Compute The Action to send to the solorace sever
                 **************************************************/

        if ( (++currentStep) != maxSteps)
        {
                    string action = drive.drive(string(buf));
                    memset(buf, 0x0, UDP_MSGLEN);
                    sprintf(buf,"%s",action.c_str());

        }
        else
            sprintf (buf, "(meta 1)");

                if (sendto(socketDescriptor, buf, strlen(buf)+1, 0,
                           (struct sockaddr *) &serv_addr,
                           sizeof(serv_addr)) < 0)
                {
                    response = "Error : cannot send data ";
                    CLOSE(socketDescriptor);
                    return (1);
                }
            }
            else
            {
                response ="Server did not respond in 1 second ";
            }
        }
    } while(shutdownClient==false && ( (++curEpisode) != maxEpisodes) );

    if (shutdownClient==false)
    drive.onShutdown();
    CLOSE(socketDescriptor);
    return 0;
}

>
代码语言:javascript
复制
// ui code 
<
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
#include <time.h>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    thread =new QThread();
    QString response;

    mine = new clientClass("127",3001,"SCR");

    mine->moveToThread(thread);


    connect(thread, SIGNAL(started()),mine, SLOT(connection()));

}

MainWindow::~MainWindow()
{
    delete ui;
    delete thread;
    delete mine;
}

void MainWindow::on_pushButton_clicked()
{
    thread->start();

    if(thread->isRunning()) std::cout<< "is running"<<endl;


}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-11 05:39:13

创建一个新的Worker子类化QObject类,并使用信号/插槽在您的worker和UI之间进行通信。

在我看来,每次要运行流程时创建一个新的worker比重用同一个worker要容易得多。因此,在创建新的worker之前,您必须删除该worker。您可以使用QObject::deleteLater插槽来实现此目的。

当您必须将结果发送到UI时,您需要在Worker类中触发一个信号,并且在您的MainWindow中需要一个插槽来处理结果。

您还需要一个标志来停止worker并中断无限循环。

一个工人的例子:

代码语言:javascript
复制
class MyWorker: public QObject
{
    Q_OBJECT
public:
    MyWorker(QString const& aAddress, unsigned int aPort, QObject* parent=nullptr): QObject(parent),
        address(aAddress), port(aPort)
    {}
    virtual ~MyWorker()
    {
        qDebug() << "Deleted" << address << port;
    }
public slots:
    void run()
    {
        running = true;
        int count = 0;
        while(running)
        {
            QCoreApplication::processEvents();
            for (int i = 0; i != 100000; ++i) { // Long time processing
            for (int i = 0; i != 100; ++i) {}
            }
            ++count;
            resultAvailable(QString("Loop count %1").arg(count));
        }
        finished(); // Inform that the worker has finished its task
    }

    void stop() // Call it to stop the thread
    {
        qDebug() << QThread::currentThreadId();
        running = false;
    }
signals:
    void resultAvailable(QString const&); // Will send message to the UI
    void finished();
private:
    QString address;
    unsigned int port;
    bool running;
};

调用worker并显示从它接收到的结果的UI。

代码语言:javascript
复制
class MyWindow: public QWidget
{
    Q_OBJECT
public:
    MyWindow(QWidget* parent=nullptr): QWidget(parent),
    address(new QLineEdit),
    port(new QLineEdit),
    ok(new QPushButton("Run")),
    label(new QLabel())
    {

        QVBoxLayout* layout = new QVBoxLayout(this);
        layout->addWidget(address);
        layout->addWidget(port);
        layout->addWidget(ok);
        layout->addWidget(label);
        connect(ok, &QPushButton::clicked, this, &MyWindow::process);
    }
public slots:
    void process()
    {
        // Create a new worker and its thread
        QThread* workerThread = new QThread(this);
        MyWorker* worker = new MyWorker(address->text(), port->text().toUInt());
        worker->moveToThread(workerThread); // Put the worker in a dedicated thread

        connect(ok, &QPushButton::clicked, worker, &MyWorker::stop); // If user clicks on the ok btn again, delete the previous worker
        connect(worker, &MyWorker::resultAvailable, this, &MyWindow::processResult); // Process the data sent by the worker in the UI
        connect(worker, &MyWorker::finished, workerThread, &QThread::quit); // Stop the thread when the worker has finished
        connect(workerThread, &QThread::finished, workerThread, &MyWorker::deleteLater); // Delete the thread when finished
        connect(workerThread, &QThread::finished, worker, &MyWorker::deleteLater); // Delete the thread when finished
        connect(workerThread, &QThread::started, worker, &MyWorker::run); // Starts the worker when the thread is launched
        workerThread->start(); // The worker will be called
    }

    void processResult(QString const& result)
    {
        label->setText("The result: " + result);
    }
private:
    QLineEdit* address;
    QLineEdit* port;
    QPushButton* ok;
    QLabel* label;
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56531707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档