2014-02-20 77 views
0

我編寫了一個C++方法來查找所有串行端口,打開,寫入和關閉並使用Q_INVOKABLE從QML調用此方法。在QML中,首先我將一個LoadPage.qml推送到StackView,然後在onClicked:Button插槽中調用find()串行端口。QtQuick動畫凍結列表並打開串行端口

問題:如果有很多串行端口連接,動畫開始,然後立即凍結,當功能找到完成動畫重新開始時,它是一個凍結推動LoadPage.qml到StackView。 [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; 
} 
+0

我明白你爲什麼測試,如果每個端口都支持您所要求的參數;但我不明白爲什麼你發送一些數據到每個端口,並且在這樣做之後不做任何測試(你已經將端口存儲在你的內部列表中......)。你想通過測試行爲來掃描某種類型的設備嗎? – leemes

回答

4

您的代碼在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())); 
    m_futureWatcher.set(m_future); 
    ... 
    } 
    Q_SLOT void findPorts() { 
    if (m_future.isRunning()) return; 
    m_future = QtConcurrent::run(doFindPorts); 
    } 
};