Qt 刷一个计算器

目录

添加一个全新的工程

啥是QUiLoader

运行这个工程


注意本博客使用的solution并不是最简单的方案,这是为了体验一下QUiTools和Qt6所支持的QuiLoader所写。这个计算器特别简单:

当你点击中间的"+"时可以切换运算符号,左右两侧都是简单的SpinBox,当你点击=或者变动数字或者变动运算符的时候会自动刷新结果。

添加一个全新的工程

很简单,我们使用的是基于CMake构建系统的一个小Demo,所以需要在构建的时候选择CMake构建系统。

啥是QUiLoader

QUiLoader Class | Qt UI Tools 6.7.1

我们知道,当我们使用QWidget编程的时候,基本的流程是先根据一定的需求设计Ui,当我们保存的时候,Qt将会解析我们的.ui文件(本质上是一个xml文件)得到控件树,然后生成对应的CPP模板代码进行解析(当我们默认的添加一组ui/h文件的时候),那么问题来了,我们可以自己控制解析吗?在之前没有QUiLoader的时候,我们可能需要从头开始,现在不需要了,用人家造好的轮子就行。

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    QUiLoader loader;
    QFile file(":/forms/myform.ui");
    file.open(QFile::ReadOnly);
    QWidget *myWidget = loader.load(&file, this);
    file.close();
​
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(myWidget);
    setLayout(layout);
}

这个来自官方的超级迷你Demo就是说明了这个类的使用方法。他就是读取一个UI文件返回解析的Widget。

我们先大概设计这个MainWindow出来:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
​
#include <QMainWindow>
​
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class QSpinBox;
class QPushButton;
class QLabel;
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    std::optional<QWidget*>         loadCalculatorAsDef();
    void                            anaylzeWidgets();       // 解析得到的QWidget
    void                            initOps();              // 初始化操作符映射池
    void                            handleOpsChange();      // 处理符号变化
    void                            handleResChange();      // 处理数字变化
    ~MainWindow();
​
private:
    Ui::MainWindow *ui;
    QWidget*        calculator;                         // 代劳指针,这个指针将会维护我们拿到的Widget
    QMap<QString, std::function<int(int, int)>> ops;      // 操作池
    QStringList     opsStr{"+", "-", "x", "/"};         // 支持的操作符
    QSpinBox*       spbx1;                              /// 下面开始都是代劳的操作指针
    QSpinBox*       spbx2;
    QPushButton*    op_btns;
    QPushButton*    res_btn;
    QLabel*         res_label;
    int             opIndex{0};                     // 当前正在运行的操作符号薄记
};
#endif // MAINWINDOW_H

下面我们开始考虑基本的加载逻辑:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initOps();
    if(!loadCalculatorAsDef().has_value())  // 我们能不能加载这个Widget?
        Error("Do nothing :(");         // 小Demo,装死就行
    else
        anaylzeWidgets();               // 分析这个Widget
}

anaylzeWidgets()这个我们自己编写的函数

TIPS:不熟悉下面的findChildren操作的同志们查找文档,他就是使用空间名称反向查找空间的

void MainWindow::anaylzeWidgets()
{
    spbx1 = calculator->findChild<QSpinBox*>("operatorSpinBox1");
    if(!spbx1){
        Error("Can not find left SpinBox");
        return;
    }
    spbx2 = calculator->findChild<QSpinBox*>("operatorSpinBox2");
    if(!spbx2){
        Error("Can not find right SpinBox");
        return;
    }
    op_btns = calculator->findChild<QPushButton*>("operatorSwitcher_btn");
    if(!op_btns){
        Error("Can not find operator btn");
        return;
    }
    res_btn = calculator->findChild<QPushButton*>("get_res_btn");
    if(!res_btn){
        Error("Can not find the res btn");
        return;
    }
    res_label = calculator->findChild<QLabel*>("result");
    if(!res_label){
        Error("Can not find the res label");
        return;
    }
    connect(op_btns, &QPushButton::clicked, this, &MainWindow::handleOpsChange);
    connect(res_btn, &QPushButton::clicked, this, &MainWindow::handleResChange);
    connect(spbx1, &QSpinBox::valueChanged, this, &MainWindow::handleResChange);
    connect(spbx2, &QSpinBox::valueChanged, this, &MainWindow::handleResChange);
}

好,那么我们怎么拿到Widget呢?简单的仿写一个

std::optional<QWidget*> MainWindow::loadCalculatorAsDef()
{
    QUiLoader calcloader;
    QFile file(UI_PATH);    // 这个UIPath就是我们的ui文件所在位置
    file.open(QIODevice::ReadOnly);
    if(!file.isOpen()){     // 文件打不打得开?
        Error("Can not find demo ui");
        return {};
    }
​
    QWidget* widget = calcloader.load(&file, this); // 能不能有效的从这个UI文件中加载一个Widget?
    if(!widget){
        Error("Can not analyze the ui file");
        return {};
    }
    this->calculator = widget;
    qDebug() << calcloader.availableWidgets(); // 查看支持的Widget
    return {widget};
}

剩下的就是写拿到的控件逻辑了:

void MainWindow::initOps()
{
    ops.insert(opsStr[0], [=](int x, int y)->int{return x + y;});
    ops.insert(opsStr[1], [=](int x, int y)->int{return x - y;});
    ops.insert(opsStr[2], [=](int x, int y)->int{return x * y;});
    ops.insert(opsStr[3], [=](int x, int y)->int{return x/y;});
}
​
void MainWindow::handleOpsChange()
{
    this->opIndex++;
    opIndex %= ops.size();
    op_btns->setText(opsStr[opIndex]);
    handleResChange();
}
​
void MainWindow::handleResChange()
{
    auto func = ops.value(opsStr[opIndex]);
    auto val1 = spbx1->value();
    auto val2 = spbx2->value();
    if(opIndex == 3 && val2 == 0){
        res_label->setText("NUL");
        return;
    }
    auto res = func(val1, val2);
    res_label->setText(QString::number(res));
}

运行这个工程

我们要留意到每一个类使用的时候,要不要添加依赖:需要的!

Header:#include <QUiLoader>
CMake:find_package(Qt6 REQUIRED COMPONENTS UiTools) target_link_libraries(mytarget PRIVATE Qt6::UiTools)
qmake:QT += uitools
Inherits:QObject
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui UiTools Widgets)
target_link_libraries(
QUiLoader PRIVATE 
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::UiTools 
Qt${QT_VERSION_MAJOR}::Core 
Qt${QT_VERSION_MAJOR}::Gui) # 加一些依赖

当我们修改好CMakeLists的时候,我们构建这个工程。

完事!

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的!以下是用QT一个简单的计算器的基本步骤: 1. 打开QT Creator,新建一个QT Widgets Application项目。 2. 在mainwindow.ui界面上拖放QPushButton、QLabel和QLineEdit控件,用于输入、输出和计算。 3. 给QPushButton添加点击事件,实现计算功能。点击事件中获取QLineEdit中的输入,进行计算,然后将结果输出到QLabel中。 4. 编译并运行程序,测试计算器功能。 示例代码: mainwindow.h文件: ```c++ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_calculateButton_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H ``` mainwindow.cpp文件: ```c++ #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_calculateButton_clicked() { // 获取输入 QString input = ui->inputLineEdit->text(); // 计算 QString result = QString::number(eval(input.toStdString().c_str())); // 输出结果 ui->resultLabel->setText(result); } ``` eval函数是一个用于计算表达式的函数,可以使用Qt的QScriptEngine类来实现。该函数的实现可以参考以下示例代码: ```c++ #include <QScriptEngine> double eval(const char* expr) { QScriptEngine engine; QScriptValue result = engine.evaluate(expr); return result.toNumber(); } ``` 这样,一个简单的计算器就完成了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值