【问题标题】:Qt Creator - write serial received data to UIQt Creator - 将串行接收的数据写入 UI
【发布时间】:2016-01-03 02:12:12
【问题描述】:

我正在与 qt creator 合作,我想为实现 UI 的类获取一个 QByteArray,比如说 A 类。B 类实现串行连接 (RS232) 并通过以下方式接收数据:

QSerialPort::connect(serialport,SIGNAL(readyRead()),this,SLOT(SerialPortManager::GiveReceivedDataToUI()));

所以在我的方法SerialPortManager::GiveReceivedDataToUI(){} 中,我将从我的串行连接中读取所有数据,如下所示:serialport->readAll(); 数据(存储在 QByteArray 中)仍在 B 类中。现在我想将此数据放入文本框A类。

我写了一些关于从不同类访问 UI 元素的线程。尝试了另一个连接,但我可以弄清楚如何将我的数据连接到 A(UI) 类中写入文本框的方法。我想用体面的 OO 来写它,而不仅仅是公开它。

有什么建议吗?

更新

class SerialPortManager : QMainWindow
{
     Q_OBJECT
private:    
    static SerialPortManager* instance;    
protected:
    SerialPortManager();
public:
    static SerialPortManager* GetInstance();
    void OpenSerialConnection();
    void CloseSerialConnection();
    void WriteSingleACLCommand(QString);
    void WriteMultipleACLCommands();

public slots:
    void GiveReceivedDataToUI();
signals:
    void Send(QByteArray& s);

};
#endif // SERIALPORTMANAGER_H

【问题讨论】:

  • “如何将我的数据连接到 A(UI) 类中编写文本框的方法。我想用体面的 OO 编写它”,那是体面的 oop。是否也要将数据存储在 UI 类中?
  • 您确定a 是正确的UI 类实例吗?在你的 sn-p a 似乎是一个临时实例。如果您在main 中创建Class AClass B 的实例,则可以在那里建立连接。对于好的设计,SerialPortManager 应该对你的UI 类一无所知。还要确保只建立一次连接。
  • 好吧,我有点困惑为什么SerialPortManager 是从QMainWindow 派生的,我假设你确实使用这个类作为你的主窗口。但问题是class SerialPortManager : QMainWindow。在这里,您从QMainWindow 私下派生,您应该公开派生:class SerialPortManager : public QMainWindow。顺便问一下,这个类为什么是单例类有什么原因吗?
  • 但是你真的在你的屏幕上显示这个类吗?您使用任何 GUI 功能吗?如果不是,那么您应该继承 QObject 而不是 QMainWindow
  • 最好的解决方案是在单独的线程类中启动,该线程类必须接收和发送数据到RS232,因为在这种情况下程序可能会被冻结。所以对这个使用机制signal and slot。在Class A 中,您将signal 发送到Class B,并带有一些到RS323 的命令。 Class B 在插槽中接收到信号并向串口发送一些命令,然后在readyRead() 中接收数据。当数据准备好时,Class BClass A 发出信号,并且数据将在Class A 中接收而不会冻结。

标签: c++ qt user-interface serial-port


【解决方案1】:

可能是这样。这也是与使用QThread 发送和接收数据SIGNAL 和SLOT 的类进行通信的唯一概念。这也是安全的,因为我们可以避免冻结。 (未经测试的代码。)

        class SerialPortManager : QSerialPort
        {
        Q_OBJECT

        public:
        SerialPortManager();

        private slots:
        SLOT_ReciveData()

        // here slot which will be received command from difrent class
        public slots:
        void CommandFromMainWindow(QByteArray command); 

        // here signal which will be emited if data was be received
        signals:
        void SendToMainWindow(QByteArray s); 

        };

        /******SOURCE********/
        SerialPortManager:: SerialPortManager()
        {
    // here also all setup Your serial port

        // in this connection we will be received data. This happen also in diffrent thread, because this is a part signal which was be send from main window
        QObject::connect(this , SIGNAL(readyRead()) , this , SLOT(SLOT_ReciveData()) , Qt::QueuedConnection);

}

// and slot to recived directly form Serial Port               
        void SerialPortManager::SLOT_ReciveData()
        {

                /************HERE WE GOT SOME DATA********/
        QByteArray buffer;

        while(this->bytesAvailable() > 0) // we read to time is data is available in buffer
        {
        buffer.append(this->readAll());

        }

        /******If any data is yet avaiable we send SIGNAL to mainwindow!!!!****/

        SendToMainWindow(buffer)

        }

MainWindowClass 是 Singelton

class MainWindow : public QMainWindow
{
private:

QThread *threadCOM;
SerialPortManager *comconfigure;         

// From this signal we something send to Serial Port for example some command
signals:
void SIGNAL_To_SerialManager_LetMeSomeData(QByteArray cmd);

// And here we something received form Serial Port
public slots:
void SLOT_Yeah_I_Get_Data(QByteArray &s);

};

MainWindow::MainWindow()
{

threadCOM = new QThread(this); // new thread for your class with serial port
comconfigure = new SerialPortManager();
comconfigure->moveToThread(threadCOM); // attachment particular thread to pinter Your class
threadCOM->start(QThread::HighestPriority); // and start, but wait for signal

// here connect signal form main windowd which send command to serial port
QObject::connect(this , SIGNAL(SIGNAL_To_SerialManager_GevMeSomeData(QByteArra);) , comconfigure , CommandFromMainWindow(QByteArray)))

// also connect signal to recived data to main window
QObject::connect(comconfigure , SIGNAL(SendToMainWindow(QByteArray)) , this, SLOT_Yeah_I_Get_Data(QByteArray)))

}

【讨论】:

  • 非常感谢,不胜感激。我会在接下来的几天里尝试一下,让你知道结果如何。
  • 你只需要记住不要留下内存泄漏。 comconfigure 在您的代码中永远不会被破坏。在退出应用程序之前正确停止线程也是一个好主意。
  • @thuga 还有另一个关于 readyRead() 信号的问题,只要有新数据可用,就会发出这个信号,因此新数据将直接发送到 MainWindow。有没有办法在发送者完全写完之前填满缓冲区(不使用waitForReadyRead)?,通过使用setReadBufferSize
  • setReadBufferSize 帮不了你。这只是设置缓冲区的最大大小。您需要知道您期望接收的数据的大小。获得这么多数据后,您可以将其发送至MainWindow
  • @Pim 你必须知道。 TCP 会将您的数据分成块,因此无法绕过它。找出此信息的常用方法是将要发送的数据的大小添加到您将要发送的数据的开头。我链接到的答案告诉你这一点。
猜你喜欢
  • 2011-04-28
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
  • 2020-05-26
  • 1970-01-01
相关资源
最近更新 更多