но как вызвать этот сигнал?
Объявите сигнал в интерфейсе класса QObject
. Вставьте макрос Q_OBJECT
в объявление класса. Прочитайте Singals и Slots в Qt .
Пример. Подкласс QThread
в вашем случае (QThread
наследует QObject
). Прочитайте Основы работы с потоками в Qt и Документы QThread .
Заголовок
#include <QThread>
class OtherThread : public QThread
{
Q_OBJECT
public:
OtherThread(QObject *parent);
~OtherThread();
signals:
void debug(QString);
// You have to override run(). Don't try to call it anywhere.
// There is start() method to start a thread
protected:
void run() override;
};
испускают сигнал из места, где вы нужно:
Исходный файл
#include "OtherThread.h"
OtherThread::OtherThread(QObject *parent)
: QThread(parent)
{ }
OtherThread::~OtherThread()
{
if(isRunning())
{
// Stop our loop
requestInterruption();
// Waits until return from run()
wait();
}
}
void OtherThread::run()
{
int it = 0;
while(!isInterruptionRequested())
{
// the line below will enqueue some call to the GUI thread
// no event loop in the sender thread is needed
emit debug(QString::number(it++));
msleep(500);
}
}
GUI заголовочный файл класса
#include <QtWidgets/QMainWindow>
class MainWin : public QMainWindow
{
Q_OBJECT
public:
MainWin(QWidget *parent = Q_NULLPTR);
};
GUI класс исходный файл
#include "MainWin.h"
#include "OtherThread.h"
#include <QTextEdit>
#include <QTimer>
MainWin::MainWin(QWidget *parent)
: QMainWindow(parent)
{
auto textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
auto otherThread = new OtherThread(this);
/*
No need to specify the connection type.
Qt::AutoConnection will be used by default.
In case of an automatic connection, Qt looks at the thread that invoked the signal
and compares it with the thread the receiver is living in to determine
which connection type it has to use.
*/
connect(otherThread, &OtherThread::debug,
textEdit, &QTextEdit::append);
// Attention: call start(), not run()!
otherThread->start();
// For example you want to stop the thread after 5 seconds
QTimer::singleShot(5000, [=]() { otherThread->requestInterruption(); });
}
Сделайте то же самое, используя высокоуровневый QtConcurrent API :
#include "MainWin.h"
#include <QtConcurrent/QtConcurrent>
#include <QThread> // for msleep
#include <atomic>
#include <QTextEdit>
#include <QTimer>
// Thread-safe flag to stop the thread. No mutex protection is needed
std::atomic<bool> gStop = false;
MainWin::MainWin(QWidget *parent)
: QMainWindow(parent)
{
auto textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
// Run the code in another thread using High-Level QtConcurrent API
QtConcurrent::run([=]()
{
int it = 0;
while(!gStop)
{
QString text = QString::number(it++);
// No need to explicitly specify Qt::QueuedConnection,
// Qt::AutoConnection will be used
QMetaObject::invokeMethod(textEdit, "append",
Q_ARG(QString, text));
QThread::msleep(500);
}
});
// Timer to stop the thread after 5 seconds
QTimer::singleShot(5000, [=]() { gStop = true; });
}
MainWin::~MainWin()
{
// Stop the loop if we exit the program earlier than after 5 seconds,
// to avoid undefined behaviour in that case
gStop = true;
}
Пожалуйста, также обратите внимание, что Qt предоставляет единое место для управления всеми сообщениями отладки, предупреждений, ошибок и других типов:
Методы отладки Qt для c ++
qInstallMessageHandler ()
Теперь вы можете установить обработчик событий один раз, и тогда все сообщения будут go в одном месте, где вы сможете выводить их там, где это необходимо, без использования пользовательских подключений.
Обратите внимание, что Qt предоставляет несколько глобальных макросов для записи предупреждения и отладочного текста:
qDebug()
используется для записи пользовательских отладочных выходных данных.
qInfo()
is u sed для информационных сообщений.
qWarning()
используется для сообщения о предупреждениях и исправляемых ошибках в вашем приложении.
qCritical()
используется для записи критических сообщений об ошибках и сообщения о системных ошибках.
qFatal()
используется для написание фатальных сообщений об ошибках незадолго до выхода.
.
Кроме того, я веду некоторые записи с QDebug
, а также вывод на std::cerr
. Могу ли я смешать эти выходы?
Кажется нет, я рекомендую переписать код, в котором вы используете std::cerr <<
, и заменить его на "qDebug() <<"
, qWarning() <<
, et c.
Еще один вопрос по использованию QMutex
. По сути, я просто читаю значения, установленные другим потоком, и запускаю / останавливаю поток. Нужно ли использовать QMutex
в таком простом случае?
Этот вопрос может быть не таким простым. Для простейших случаев volatile
может быть достаточно. Читать Синхронизация потоков .
(я имею в виду, я знаю, зачем использовать мьютекс; мой вопрос о том, что при использовании Qt, внутренних механизмов обработки GUI и обработки потоков может потребоваться)
Qt не влияет на такие основы программирования. Но обратите внимание, что все элементы GUI в Qt доступны только из потока GUI. Смотрите Основы потоков в Qt :
Как уже упоминалось, каждая программа имеет один поток при запуске. Этот поток называется "основным потоком" (также известным как "GUI поток" в приложениях Qt). Qt GUI должен работать в этом потоке. Все виджеты и несколько связанных классов, например QPixmap
, не работают во вторичных потоках. Вторичный поток обычно называют «рабочим потоком», потому что он используется для разгрузки обработки обработки из основной поток.
Таким образом, вы не можете получить доступ к элементам GUI напрямую из другого потока.
textEdit->append("some text"); // may be directly called from a GUI thread only
Использовать Singal-Slot механизм для доступа к GUI элементы из других потоков. Читайте также Синтаксис нового слота сигналов Qt5 .
Вы также можете вызывать методы, используя Qt::QueuedConnection
без первого подключения, используя QMetaObject :: invokeMethod :
QMetaObject::invokeMethod(textEdit, "append",
Qt::QueuedConnection,
Q_ARG(QString, "some text"));
Читайте также: Технологии многопоточности в Qt :
Qt предлагает множество классов и функций для работы с потоками. Ниже приведены четыре различных подхода, которые программисты Qt могут использовать для реализации многопоточных приложений ...
Edit. Расширенный полезный список статей.
Сигналы и слоты
Singals и слоты в Qt
Qt5 Синтаксис нового слота сигналов
QMetaObject :: invokeMethod
Как работают сигналы и слоты Qt
Отладка
Методы отладки Qt для c ++
Threading
Основы работы с потоками в Qt
Технологии многопоточности в Qt
Синхронизация потоков
Потоки и объекты
Отсутствующая статья о многопоточности Qt в C ++
Потоки События QObjects