ReactiveX 學習筆記(29)使用 RxCpp(RxQt)+ Qt 進行 GUI 編程


課題

  1. 程序界面由3個文本編輯框和1個文本標簽組成。
  2. 要求文本標簽實時顯示3個文本編輯框所輸入的數字之和。
  3. 文本編輯框輸入的不是合法數字時,將其值視為0。
  4. 3個文本編輯框的初值分別為1,2,3。

下載 RxCpp 和 RxQt

$ git clone --recursive https://github.com/ReactiveX/RxCpp.git
$ git clone --recursive https://github.com/tetsurom/rxqt.git

創建工程

啟動 Qt Creator, File / New File or Project...
在向導的第1頁選擇 Application 分類下的 Qt Widgets Application
在向導的第2頁輸入工程名稱 RxExample 以及工程所在位置
在向導的第3頁選擇 Desktop Qt
完成向導后點擊 Done 創建工程。

配置工程

打開工程文件 RxExample.pro,做如下修改

  1. 使用 C++17,即改變 CONFIG 這一項,將 C++11 改為 C++17。
  2. 添加對 RxCpp 和 RxQt 所在路徑的引用,即添加 INCLUDEPATH 這一項
CONFIG += c++17
INCLUDEPATH += <下載位置>/RxCpp/Rx/v2/src \
    <下載位置>/rxqt/include

配置 UI

打開 mainwindow.ui,在設計器中做如下修改

  1. 添加 Form Layout。這一步是為了方便添加並定位其他控件。
  2. 在 Form Layout 內添加三個 LineEdit 控件,分別命名為 edtNumber1,edtNumber2,edtNumber3 (設置 objectName 屬性)
    然后將其水平對齊屬性均改為右對齊(將 alignment/Horizontal 屬性設置為 AlignRight )
    然后再將其初值分別設為1,2,3(設置 text 屬性)
  3. 在 Form Layout 內添加一個 Label 控件, 將其命名為 lblResult(設置 objectName 屬性)
    然后將其水平對齊屬性改為右對齊(將 alignment/Horizontal 屬性設置為 AlignRight )

不使用 RxCpp(RxQt) 的解決方案

打開 mainwindow.ui,在設計器中給三個 LineEdit 控件分別添加 textChanged 事件
(右鍵點擊控件,然后選擇 Go to slot...,然后選擇 QLineEdit/textChanged(QString),最后按 OK )
這一步的結果是在 MainWindow 類中生成(由 IDE 添加)了以下三個方法

// mainwindow.h
void on_edtNumber1_textChanged(const QString &arg1);
void on_edtNumber2_textChanged(const QString &arg1);
void on_edtNumber3_textChanged(const QString &arg1);
// mainwindow.cpp
void MainWindow::on_edtNumber1_textChanged(const QString &arg1)
{
}
void MainWindow::on_edtNumber2_textChanged(const QString &arg1)
{
}
void MainWindow::on_edtNumber3_textChanged(const QString &arg1)
{
}

打開 mainwindow.h 和 mainwindow.cpp 在 MainWindow 類中添加 add 方法,執行加法操作

// mainwindow.h
void add();
// mainwindow.cpp
void MainWindow::add()
{
    int n = ui->edtNumber1->text().toInt() + ui->edtNumber2->text().toInt() + ui->edtNumber3->text().toInt();
    ui->lblResult->setNum(n);
}

最后在窗口的構造器以及三個 LineEdit 控件的事件中添加對 add 方法的調用

// mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    add();
}
void MainWindow::on_edtNumber1_textChanged(const QString &arg1)
{
    add();
}
void MainWindow::on_edtNumber2_textChanged(const QString &arg1)
{
    add();
}
void MainWindow::on_edtNumber3_textChanged(const QString &arg1)
{
    add();
}

使用 RxCpp(RxQt) 的解決方案

打開 mainwindow.cpp,添加對 RxQt 的引用並在窗口的構造器中添加事件處理程序,即將文件改為

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <rxqt.hpp> // 添加這一行

// mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 執行加法操作
    auto f = [](const QLineEdit* edt) {
        return rxqt::from_signal(edt, &QLineEdit::textChanged)
            .start_with(edt->text());
    };
    f(ui->edtNumber1).combine_latest([](const QString& s1, const QString& s2, const QString& s3){
        return s1.toInt() + s2.toInt() + s3.toInt();
    }, f(ui->edtNumber2), f(ui->edtNumber3))
    .subscribe([&](int n){ui->lblResult->setNum(n);});
}

MainWindow::~MainWindow()
{
    delete ui;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM