1. 程式人生 > >QT學習記錄1(訊號與槽)

QT學習記錄1(訊號與槽)

使用,學習QT的背景

剛入職新公司,工作是嵌入式軟體,工作內容包括使用QT進行一些軟體的開發等,以前沒有接觸過QT,特意建立第一篇部落格,用作QT的學習過程記錄
入職後,公司前輩要求使用QT寫一個軟體,接收硬體裝置傳回的資料並顯示,同時軟體可以對裝置的工作方式進行設定,使用TCP通訊協議。

C++和TCP通訊還算比較熟悉,所以前期程式碼沒有問題,Debug得到的資料已經達到預期,但是,在試圖把資訊顯示在UI介面中的label控制元件中的時候,問題出現了:
由於軟體在執行過程中需要不斷的向裝置發出資料,取回資料,需要持續佔用資源。所以用到了多執行緒進行處理,然而,在QT中,只有主執行緒可以對UI進行操作。所以,子執行緒不能操作UI介面。正因此才接觸到了QT的訊號與槽機制

對訊號和槽函式的理解:

訊號和槽函式就像一根插排,有插頭(訊號),有插座(槽函式),它們之間用電線連起來(connect函式),所以當插頭插上電之後,插座也會有對應的響應,比如指示燈亮起。。。

QT中的訊號和槽可以跨執行緒傳遞,也就是說,一旦訊號和槽繫結完成後,只要有訊號發出,那麼對應的槽函式就會被執行,無論兩者是不是在同一個執行緒中。

 

程式碼表示:

首先是訊號(相當於插頭)

mywrite.h檔案  新建的檔案,用作資料的處理

/*這個是mywrite.cpp檔案,用作資料處理*/


#ifndef MYWRITE_H
#define MYWRITE_H

#include <QObject>

class Mywrite : public QObject
{
    Q_OBJECT
public:
    explicit Mywrite(QObject *parent = 0);
    void run();    //假設這個是資料處理執行緒(不要在意繼承什麼的細節,多執行緒之後再發)
                   //它在執行過程中,需要顯示資料的時候,就發射下邊的訊號 ↓

signals:      //這個是訊號集,代表了訊號的集合,這一欄下邊的所有函式都是訊號
    
    //訊號只需要在標頭檔案中宣告即可,不需要實現
    void send_output_text(QString);  //這個是訊號(插頭),可以看到,為了滿足我們的需求
                                     //它是有引數的(當然,多引數或者無引數都可以)
                                     //這個訊號的引數是 QString 型別的

public slots:
};

#endif // MYWRITE_H

mywrite.cpp檔案,這個檔案用作資料處理

/*mywrite.cpp 檔案,這個檔案用作資料處理  */

#include "mywrite.h"

Mywrite::Mywrite(QObject *parent) : QObject(parent)
{
    
}

void Mywrite::run()    //假定的資料處理函式
{
    QString  data;
    /*
     *
            對資料進行傳送,接受,處理操作,假設最終獲取到了有用資料,並儲存在變數 data 中
    */

    //如果需要把data顯示在UI介面上,就可以呼叫設定好的訊號
    emit send_output_text(data);    //emit  發射的意思,執行這個操作之後,就會發出一個訊號
}

widget.h  標頭檔案,建立工程自帶的,    程式碼中加了很多註釋,就不多打字了

//  這個是widget.h 檔案
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:    //這個代表槽函式集合
    
    void set_outputt_text(QString);   //這個是建立的一個文字顯示槽函式
                                      //用來接受子執行緒傳過來的文字並顯示出來
                                      //我的UI介面中,用了一個label控制元件顯示資料
                                      //label控制元件名字叫做 label_output
                                      
private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

 widget.cpp  檔案,也是建立工程自帶的,這個檔案中包含了對槽函式的定義,訊號與槽函式的連線

/*widget.cpp    建立工程自帶的文字,這個CPP裡邊主要包含了UI介面的一些操作,比如點選按鈕
                輸入文字等*/


#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :       
    QWidget(parent),
    ui(new Ui::Widget)                  /*建構函式*/
{
    ui->setupUi(this);
    Mywrite myw;        //例項化一個Mywrite的物件出來
    
    //這個地方對訊號和槽函式進行繫結,繫結使用的函式是: connect
    //connect函式在QObject空間內,也可以省略前邊的QObject,直接寫connect
    //connect的4個引數是:
    //connect(訊號的發出者是誰, 發的哪個訊號, 訊號的接受者是誰, 接收到訊號做什麼操作);
    
    //有了上邊的基礎,     我們就知道了對應的4項是誰:
    //訊號的發出者:       資料處理函式發出的訊號,也就是Mywrite類例項化出的  myw
    //發出的訊號:        Mywrite類中的訊號:void send_output_text(QString)
    //訊號的接受者:      UI介面,  本函式是widget的建構函式,所以可以使用this指標,代表自己
    //接到訊號後的操作:   把接到的QString型別字串顯示到label上,對應槽函式: void set_output_text(QString)
    
    
    
    //下邊這行程式碼就完成了插頭(訊號)和插座(槽函式)的繫結
    QObject::connect(&myw, SIGNAL(send_output_text(QString)), this, SLOT(set_outputt_text(QString)));
    
}

Widget::~Widget()                      /*解構函式*/
{
    delete ui;
}

void Widget::set_output_text(QString qstr)     //這裡就是槽函式的函式實現
{
    ui->label_output->setText(qstr);     //對label進行文字設定,顯示內容為引數內容
}


注意:

這套程式碼是不能執行的,因為實際專案要用到多執行緒,然後啟動執行緒後才能進行資料處理,然後傳送訊號。這套程式碼是週末寫的,用作學習記錄,也希望能幫到剛接觸QT的朋友。