QtQuick 动画冻结在列表和打开的串口上

Posted

技术标签:

【中文标题】QtQuick 动画冻结在列表和打开的串口上【英文标题】:QtQuick animation freezing on list and open serial ports 【发布时间】:2014-02-20 15:00:35 【问题描述】:

我编写了一个 C++ 方法来查找所有串行端口、打开、写入和关闭,并使用 Q_INVOKABLE 从 QML 调用此方法。在 QML,我首先将 LoadingPage.qml 推送到 StackView,然后在 onClicked: Button 插槽内调用 find() 串行端口。

问题:如果连接了多个串口,将LoadingPage.qml推送到StackView时会冻结,动画开始然后立即冻结,当函数find完成动画重新开始时。 [SerialPort.qml] 如何更好地解决这个问题?

//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;

【问题讨论】:

我明白你为什么要测试每个端口是否支持你请求的参数;但我不明白为什么你向每个端口发送一些数据并且这样做之后不测试任何东西(你已经将端口存储在你的内部列表中......)。您想通过测试行为来扫描某种类型的设备吗? 【参考方案1】:

您的代码在 GUI 线程中运行,由于它阻塞了 GUI 线程,因此用户交互也会停止。

您需要在单独的线程中执行扫描。 Qt Concurrent 框架非常适合这一点,因为您正在执行一个可以在任何线程中完成的独立操作。您的 find() 方法可以转换为独立函数或静态方法(因为它确实是这样)。您还可以在 lambda 中捕获 this

然后您将按如下方式运行它:

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);
  
;

【讨论】:

【参考方案2】:

设置future的正确接口是setFuture,在启动线程后调用

m_future = QtConcurrent::run(doFindPorts);
m_futureWatcher.setFuture(m_future);

【讨论】:

以上是关于QtQuick 动画冻结在列表和打开的串口上的主要内容,如果未能解决你的问题,请参考以下文章

启动图像和打开动画是不是会导致我的应用冻结?

动画在 FF 和 IE 上冻结,但不是 Chrome

Firefox svg 动画在特定 PC 上冻结

QT开发(五十一)——QtQuick基础

库需要 QApplication。如何在 Qt Quick 项目中使用 QApplication?

按下“停止”按钮时如何停止动画并冻结图像