課題
- 程序界面由3個文本編輯框和1個文本標簽組成。
- 要求文本標簽實時顯示3個文本編輯框所輸入的數字之和。
- 文本編輯框輸入的不是合法數字時,將其值視為0。
- 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,做如下修改
- 使用 C++17,即改變 CONFIG 這一項,將 C++11 改為 C++17。
- 添加對 RxCpp 和 RxQt 所在路徑的引用,即添加 INCLUDEPATH 這一項
CONFIG += c++17
INCLUDEPATH += <下載位置>/RxCpp/Rx/v2/src \
<下載位置>/rxqt/include
配置 UI
打開 mainwindow.ui,在設計器中做如下修改
- 添加 Form Layout。這一步是為了方便添加並定位其他控件。
- 在 Form Layout 內添加三個 LineEdit 控件,分別命名為 edtNumber1,edtNumber2,edtNumber3 (設置 objectName 屬性)
然后將其水平對齊屬性均改為右對齊(將 alignment/Horizontal 屬性設置為 AlignRight )
然后再將其初值分別設為1,2,3(設置 text 屬性) - 在 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;
}