Я пытаюсь реализовать это: при запуске приложения мне нужно создать несколько потоков, которые будут использовать одно и то же окно QDialog для получения сообщений от пользователя. Когда поток запущен, он запрашивает у пользователя ввод, а при нажатии кнопки «ОК» он выводит сообщение на консоль. Я не могу понять, почему, но я получаю диалоговое окно только один раз, и после этого он печатает мое одно сообщение для завершения консоли и приложений.Thread, выполняемый только один раз
Вот как я описываю диалоговое окно:
#include <QtWidgets>
class MyDialog : public QDialog
{
Q_OBJECT
public:
QWaitCondition* condition;
explicit MyDialog(QWidget *parent = 0);
signals:
void got_message(QString);
public slots:
void show_message_input();
void show_message();
private:
QLabel* message_label;
QVBoxLayout* vbox;
QHBoxLayout* hbox;
QLineEdit* message_input;
QDialogButtonBox* dialog_buttons;
};
MyDialog::MyDialog(QWidget *parent) : QDialog(parent)
{
setModal(true);
message_label = new QLabel("Message");
message_input = new QLineEdit();
dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
hbox = new QHBoxLayout();
hbox->addWidget(message_label);
hbox->addWidget(message_input);
vbox = new QVBoxLayout();
vbox->addLayout(hbox);
vbox->addWidget(dialog_buttons);
setLayout(vbox);
connect(dialog_buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), this, SLOT(reject()));
condition = new QWaitCondition();
}
void MyDialog::show_message_input()
{
int result = this->exec();
if (result == QDialog::Accepted)
{
emit got_message(message_input->text());
condition->wakeAll();
}
}
Вот MyThread класс:
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(int id, MyDialog* window, QObject *parent = 0);
signals:
void show_input();
public slots:
void print_message(QString);
private:
static QMutex mutex;
static QMutex mutex2;
MyDialog* window;
int id;
void run();
void get_captcha_value();
};
QMutex MyThread::mutex;
QMutex MyThread::mutex2;
MyThread::MyThread(int id, MyDialog* window, QObject *parent) :
QThread(parent)
{
this->id = id;
this->window = window;
connect(this, SIGNAL(show_input()), this->window, SLOT(show_message_input()));
}
void MyThread::get_captcha_value()
{
QMutexLocker lock(&mutex);
connect(this->window, SIGNAL(got_message(QString)), SLOT(print_message(QString)));
emit show_input();
mutex2.lock();
window->condition->wait(&mutex2);
mutex2.unlock();
}
void MyThread::run()
{
mutex.lock();
qDebug() << "Starting thread " << id;
mutex.unlock();
get_captcha_value();
mutex.lock();
qDebug() << "Finishing thread " << id;
mutex.unlock();
}
void MyThread::print_message(QString message)
{
qDebug() << message;
QObject::disconnect(this, SLOT(print_message(QString)));
}
И main
функция:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDialog* window = new MyDialog();
QList<MyThread*> threads;
for(int i = 0; i < 5; i++)
{
MyThread* thread = new MyThread(i, window);
threads << thread;
thread->start();
}
return a.exec();
}
Подклассификация 'QThread' не является хорошей идеей, если вы собираетесь использовать слоты. В документе [docs] (https://qt-project.org/doc/qt-5.0/qtcore/qthread.html#details): * Важно помнить, что объект QThread обычно живет в потоке, где он был а не в потоке, которым он управляет. Эта часто встречающаяся деталь означает, что слоты QThread будут выполняться в контексте его домашнего потока, а не в контексте потока, который он управляет. По этой причине внедрение новых слотов в подклассе QThread является подверженным ошибкам и обескураженным. * – thuga