我有一个多服务器应用程序,到目前为止运行良好。我有4个cpp文件。 Main.cpp 构建程序。 MainWindow.cpp 构造 ui 并启动(通过单击按钮)MyServer.cpp。 MyServer.cpp 创建一个线程并启动 MyThread.cpp。 我的目标是在文本浏览器上显示几个主要步骤(例如“服务器已启动”、“新连接”等)。
我通过
emit updateUI("server started");
将 MyServer.cpp 的输出传递到 mainwindow.cpp,其中输出被捕获:
//Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myserver.h"
#include "mythread.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::AppendToBrowser(const QString text)
{
ui->textBrowser->append(text);
}
void MainWindow::on_startButton_clicked()
{
MyServer* mServer = new MyServer;
connect(mServer, SIGNAL(updateUI(const QString)), this, SLOT(AppendToBrowser(const QString)));
mServer->StartServer();
ui->textBrowser->setPlainText("Server Started");
}
这工作得很好,因为连接命令就在 mainwindow.cpp 本身中。 问题在 mythread.cpp 中开始“更深”一步。
我在
中创建了另一个信号//MyThread.h
signals:
void updateUI_serv(const QString text);
并将其在 MyServer.cpp 中与 MainWindow.cpp 连接起来。
//MyServer.cpp
#include "myserver.h"
#include "mainwindow.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::StartServer()
{
if(!this->listen(QHostAddress::Any,1234))
{
qDebug("Server Error");
}
else
{
qDebug("Server started");
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug("new connection");
MyThread *thread = new MyThread(socketDescriptor,this);
MainWindow *mMain = new MainWindow;
connect(thread, SIGNAL(updateUI_serv(const QString)),mMain ,SLOT(AppendToBrowser(const QString)));
//flags thread for selfdeletion
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
//calls run
thread->start();
emit updateUI("thread started!");
}
// MyThread.cpp
#include "mythread.h"
#include "mainwindow.h"
#include "myserver.h"
MyThread::MyThread(int ID, QObject *parent) :
QThread(parent)
{
this->socketDescriptor = ID;
emit updateUI_serv("start");
}
void MyThread::run()
{
//thread stars here
qDebug("Starting thread");
socket = new QTcpSocket();
emit updateUI_serv("hallo");
//set socketdescriptor number
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);
qDebug("client connected");
exec();
}
void MyThread::readyRead()
{
QByteArray Data = socket->readAll();
QString Datain = QString::fromLatin1(Data);
qDebug("Date in:");
emit updateUI_serv("data in:");
socket->write(Data);
}
void MyThread::disconnected()
{
qDebug("Disconnected");
socket->deleteLater();
exit(0);
}
连接命令位于信号(来自 mythread.cpp 的 updateUI_serv)和槽(来自 mainwindow.cpp 的 AppendToBrowser)文件“之间”。 此时,当我尝试将数据(作为客户端通过 telnet)写入服务器应用程序时,程序就会崩溃。
我也尝试将连接命令设置到主窗口和 mythread 中,但是两次我都遇到了不同的问题(例如调试问题,或者文本没有显示在文本浏览器中)。 到目前为止谢谢。
最终 myServer-Object 不在主线程中运行,因此从另一个线程访问 ui 元素会使您的应用程序崩溃。
您可以通过将以下代码添加到 AppendToBrowser 插槽来确保仅显示来自 mainThread 的消息:
if( QApplication::instance()->thread() == QThread::currentThread() )
ui->textBrowser->setPlainText("whateverTextThereShallBe");
else
return;
//You should not run into this else...
这个 if 部分检查当前调用更新的对象是否是主线程。 else 部分检查错误。如果您在 else 部分中运行,则您正在尝试从不是主线程(UI 线程)的线程中更改 ui 元素。将服务器中的 SIGNAL 连接到另一个 SIGNAL(SIGNAL->SIGNAL 连接),并在 MainWindow.cpp 中添加到 SIGNAL(SERVER) -> SLOT(MainWindow) 的连接。最后尝试与 5 号进行连接呼叫。排队连接的参数(Qt::QueuedConnection IIRC)。
啊,我自己得到的。 我通过创建一个新函数(
void forwarding(const Qstring);
)解决了这个问题,在该函数中我用普通的emit updateUI(text);
发出了它..东西终于起作用了!