![](/img/trans.png)
[英]QObject::startTimer: Timers cannot be started from another thread
[英]QSerialPort with no GUI, no thread: QObject::startTimer: Timers can only be used with threads started with QThread
我正在使用 QSerialPort 做一個沒有 GUI ( TEMPLATE = lib
) 的QSerialPort
。 我不創建線程,也不需要任何線程:我沒有 GUI,阻塞串行端口操作沒問題,這就是我想要的。
做的時候:
while (!serial_uart->isWritable());
while (!serial_uart->write(frame));
我得到:
QObject::startTimer:定時器只能用於以 QThread 啟動的線程
問題:如何在沒有 GUI 的庫中使用QSerialPort
而不會觸發此錯誤?
注意:我首先認為問題來自serial_uart->waitForReadyRead(timeout)
但即使沒有這個並且只有serial_uart->write()
我已經遇到了這個問題。
最小可重現 DLL 示例:
test.cpp
#include "test.h"
extern "C" {
__declspec(dllexport) Test* new_Test() { return new Test(); }
__declspec(dllexport) void DoTest(Test *t) { t->DoTest(); }
}
Test::Test() :QObject()
{
qDebug("Hello");
}
void Test::DoTest()
{
this->serialport = new QSerialPort();
this->serialport ->setPortName("COM12");
this->serialport->setBaudRate(QSerialPort::Baud19200);
this->serialport->open(QIODevice::ReadWrite);
while (!this->serialport->isWritable());
while (!this->serialport->write("hello"));
}
test.h
#include <QSerialPort>
class Test : public QObject
{
Q_OBJECT
public:
Test();
void DoTest();
QSerialPort *serialport;
};
test.pro
TEMPLATE = lib
TARGET = test
QT += serialport
INCLUDEPATH += .
HEADERS += test.h
SOURCES += test.cpp
當我從 Python 調用release/test.dll
時,我有這個:
from ctypes import *
dll = CDLL(r"release\test.dll")
dll.new_Test.restype = c_void_p
dll.new_Test.argtypes = []
dll.DoTest.restype = None
dll.DoTest.argtypes = [c_void_p]
t = dll.new_Test()
dll.DoTest(t)
你好
QObject::startTimer:定時器只能用於以 QThread 啟動的線程
Most of the QIODevice based classes (like Qt sockets or serial port) want to live in a Qt based thread and also their functions needs to be called from the same thread where the object was created.
出於這個原因,我通常通過以下方式解決這個問題:
為您將要使用的基於 QIODevice 的 class 創建包裝器 class(QObject 基於 Q_OBJECT 宏以實現信號/插槽功能)。 對於每個 function,您計划在包裝器 class 上使用創建插槽 function,然后調用 QIODevice 中的等效函數:
qint64 MySerialPort::write(const QByteArray &data) { // m_serialPort is created with new QSerialPort in constructor of MySerialPort. return m_serialPort->write(data); }
創建一個 QThread class,在其運行 function 中創建一個 MySerialPort 實例(帶有新的 MySerialPort),然后調用 exec()。 現在 MySerialPort 生活在一個事件循環中,並且能夠發送和接收信號/插槽。
void MySerialPortThread::run() { m_serialPort = new MySerialPort(); exec(); delete m_serialPort; // Automatic deletion after thread is stopped. }
線程還可以返回一個指向實例的指針,以便更容易地從外部訪問以連接信號和插槽。
MySerialPort* MySerialPortThread::serialPort()
{
return m_serialPort; // Instance of MySerialPort class
}
在您的主代碼中創建與 MySerialPort 的插槽匹配的信號並連接它們。
signals: qint64 writeSerial(const QByteArray& data); void MyMainClass::connectSignalsAndSlots() { MySerialPort* serialPort = m_serialThread->serialPort(); connect(this, &MyMainClass::writeSerial, serialPort, &MySerialPort::write, Qt::BlockingQueuedConnection); // Use either QueuedConnection or BlockingQueuedConnection to force the execution of the slot to the MySerialThread. }
發出信號以訪問 QSerialPort。
emit writeSerial(dataByteArray);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.