QtQuick 动画冻结在列表和打开的串口上
我编写了一个 C++ 方法来查找所有串行端口、打开、写入和关闭,并使用 Q_INVOKABLE 从 QML 调用此方法.在 QML,我首先将 LoadingPage.qml 推送到 StackView,然后在 onClicked: Button 插槽内调用 find() 串行端口.
I wrote a C++ method to find all serial ports, open, write and close and use to Q_INVOKABLE to call this method from a QML. At QML, first I push a LoadingPage.qml to StackView and then I call the find() Serial Ports, inside the onClicked: Button slot.
问题:如果连接了很多串口,将LoadingPage.qml推送到StackView时会冻结,动画开始然后立即冻结,当函数find完成动画重新开始时.[SerialPort.qml]如何更好地解决这个问题?
The problem: It is a freezing on push a LoadingPage.qml to StackView if there are many serial ports connected, the animation start and then immediately freezes, when the function find finish the animation start again. [SerialPort.qml] How is it the better way to solve that?
//SerialPort.qml
Button {
text: qsTr("start")
onClicked: {
stackView.push(Qt.resolvedUrl("LoadingPage.qml"))
module.find()
}
}
QVector<QString> Physical::find()
{
m_ports.clear();
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
bool hasError = false;
QSerialPort port;
port.setPort(info);
if (port.open(QIODevice::ReadWrite)) {
if (!hasError && !port.setBaudRate(serial::baudRate)) {
emit error(tr("Can't set baud to %1, error %2")
.arg(port.portName())
.arg(port.error()));
hasError |= true;
}
if (!hasError && !port.setDataBits(serial::dataBits)) {
emit error(tr("Can't set data bits to %1, error %2")
.arg(port.portName())
.arg(port.error()));
hasError |= true;
}
if (!hasError && !port.setParity(serial::parity)) {
emit error(tr("Can't set parity to %1, error %2")
.arg(port.portName())
.arg(port.error()));
hasError |= true;
}
if (!hasError && !port.setStopBits(serial::stopBits)) {
emit error(tr("Can't set stop bits to %1, error %2")
.arg(port.portName())
.arg(port.error()));
hasError |= true;
}
if (!hasError && !port.setFlowControl(serial::flowCtrl)) {
emit error(tr("Can't set flow control to %1, error %2")
.arg(port.portName())
.arg(port.error()));
hasError |= true;
}
if (!hasError) {
m_ports.append(port.portName());
}
QByteArray data;
data.resize(1);
data[0] = ID_READ;
port.write(data);
port.close();
}
}
return m_ports;
}
推荐答案
你的代码在 GUI 线程中运行,由于它阻塞了 GUI 线程,所以用户交互也停止了.
Your code runs in the GUI thread, and since it blocks the GUI thread, the user interaction is stopped as well.
您需要在单独的线程中执行扫描.Qt Concurrent 框架非常适合这一点,因为您正在执行一个可以在任何线程中完成的独立操作.您的 find()
方法可以转换为独立函数或静态方法(因为它确实如此).您还可以在 lambda 中捕获 this
.
You need to perform the scan in a separate thread. The Qt Concurrent framework is perfect for this, since you're performing a self-contained action that can be done in any thread. Your find()
method can be turned into a stand-alone function or a static method (since that's what it really is). You could also capture this
in a lambda.
然后您将按如下方式运行它:
You'd then run it as follows:
class Physical {
QFuture<QStringList> m_future;
QFutureWatcher<QStringList> m_futureWatcher;
// A string list is a simpler type to type :)
static QStringList doFindPorts() {
...
}
Q_SLOT void findPortsFinished() {
QStringList ports(m_future);
// use the list of ports
}
public:
Physical() {
connect(&m_futureWatcher, SIGNAL(finished()), SLOT(findPortsFinished()));
...
}
Q_SLOT void findPorts() {
if (m_future.isRunning()) return;
m_future = QtConcurrent::run(doFindPorts);
m_futureWatcher.setFuture(m_future);
}
};
相关文章