先看结果

一、搭建ROS框架

创建工作空间

mkdir -p calculate_qt_ws/src

创建功能包

cd calculate_qt_ws/src/
ros2 pkg create calculator_qt

二、编写头文件

c_cpp_properties.json

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/include/x86_64-linux-gnu/qt5/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c17",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

calculator.hpp

#ifndef CALCULATOR_HPP
#define CALCULATOR_HPP

#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QString>
#include <iostream>
#include <regex>
#include <cmath>
#include <stdlib.h>

class Calculator : public QWidget
{
    Q_OBJECT
private:
    std::string result_string;
    std::regex expression_pattern;
    std::regex clear_pattern;

    QLabel result_label;
    QPushButton
        button_0,
        button_1,
        button_2,
        button_3,
        button_4,
        button_5,
        button_6,
        button_7,
        button_8,
        button_9,
        add_button,
        sub_button,
        mul_button,
        div_button,
        equal_button,
        delete_button;
    QGridLayout glayout;
    QVBoxLayout vlayout;
    QHBoxLayout hlayout;

public:
    Calculator(QWidget *parent = nullptr);
    void put_text();
    void calculateExpression();
};

#endif // CALCULATOR_HPP

三、编写源文件

calculator.cpp

#include "calculator_qt/calculator.hpp"


Calculator::Calculator(QWidget *parent)
    : QWidget(parent),result_label("",this),
    button_0("0",this),button_1("1",this),button_2("2",this),button_3("3",this),
    button_4("4",this),button_5("5",this),button_6("6",this),button_7("7",this),
    button_8("8",this),button_9("9",this),add_button("+",this),sub_button("-",this),
    mul_button("*",this),div_button("/",this),equal_button("=",this),delete_button("cls",this)
{
    //结果字符串
    result_string = "";
    //正则匹配表达式
    expression_pattern = std::regex(R"(^([-]?\d+)([/*+-])([-]?\d+)$)");    //匹配表达式 加入括号分组
    clear_pattern = std::regex(R"(^([-]?\d+)([/*+-])?([-]?\d+)?$)");       //判断表达式 
    
    //窗口属性
    setWindowTitle("简易计算器");
    resize(400, 100);

    //交互框美化
    result_label.setMinimumWidth(200);
    result_label.setAlignment(Qt::AlignRight);
    result_label.setStyleSheet("border: 1px solid #ccc; padding: 5px; font-size: 16px;");

    //按钮链接
    connect(&button_0,&QPushButton::clicked,[&](){put_text(button_0);});
    connect(&button_1,&QPushButton::clicked,[&](){put_text(button_1);});
    connect(&button_2,&QPushButton::clicked,[&](){put_text(button_2);});
    connect(&button_3,&QPushButton::clicked,[&](){put_text(button_3);});
    connect(&button_4,&QPushButton::clicked,[&](){put_text(button_4);});
    connect(&button_5,&QPushButton::clicked,[&](){put_text(button_5);});
    connect(&button_6,&QPushButton::clicked,[&](){put_text(button_6);});
    connect(&button_7,&QPushButton::clicked,[&](){put_text(button_7);});
    connect(&button_8,&QPushButton::clicked,[&](){put_text(button_8);});
    connect(&button_9,&QPushButton::clicked,[&](){put_text(button_9);});
    connect(&add_button,&QPushButton::clicked,[&](){put_text(add_button);});
    connect(&sub_button,&QPushButton::clicked,[&](){put_text(sub_button);});
    connect(&mul_button,&QPushButton::clicked,[&](){put_text(mul_button);});
    connect(&div_button,&QPushButton::clicked,[&](){put_text(div_button);});
    connect(&equal_button,&QPushButton::clicked,[&](){calculateExpression();});
    connect(&delete_button,&QPushButton::clicked,[&](){result_label.setText("");});


    //布局配置 先配置九宫格按钮布局
    glayout.addWidget(&button_1, 0, 0);
    glayout.addWidget(&button_1, 0, 0);
    glayout.addWidget(&button_2, 0, 1);
    glayout.addWidget(&button_3, 0, 2);
    glayout.addWidget(&button_4, 1, 0);
    glayout.addWidget(&button_5, 1, 1);
    glayout.addWidget(&button_6, 1, 2);
    glayout.addWidget(&button_7, 2, 0);
    glayout.addWidget(&button_8, 2, 1);
    glayout.addWidget(&button_9, 2, 2);
    //按照小键盘布局,0跨多列,因为没有 . 所以跨三列
    glayout.addWidget(&button_0, 3, 0, 1, 3);

    //第四列填充符号按钮
    glayout.addWidget(&add_button, 0, 3);
    glayout.addWidget(&sub_button, 1, 3);
    glayout.addWidget(&mul_button, 2, 3);
    glayout.addWidget(&div_button, 3, 3);


    //配置水平布局,将结果框和‘=’按钮‘cls’按钮放置同一个布局中
    hlayout.addWidget(&result_label);
    hlayout.addWidget(&equal_button);
    hlayout.addWidget(&delete_button);

    //配置垂直布局,将水平布局和网格布局放置同一个垂直布局中
    vlayout.addLayout(&hlayout);    //先水平

    vlayout.addLayout(&glayout);    //后网格
    setLayout(&vlayout);            //让整个类(窗口)的布局使用垂直布局

    
}


void Calculator::put_text(QPushButton & button)
{
    //通过正则判断当前输入是否为数字和指定的运算符号
    
    if(!std::regex_match(result_string, clear_pattern)) 
    {
        result_string = "";
    }
    
    result_string += button.text().toStdString();   //如果是,则将按钮标签加入交互框
    
    //将内容添加到交互框中
    result_label.setText(QString::fromStdString(result_string));
}

void Calculator::calculateExpression()
{ 
    
    std::smatch match;
    if (std::regex_search(result_string, match, expression_pattern))
    {

        int num1 = std::atoi(match[1].str().c_str());
        int num2 = std::atoi(match[3].str().c_str());
        std::string op = match[2].str();
        
        switch(op[0])
        {
            case '+':
                result_string = std::to_string(num1 + num2);
                break;
            case '-':
                result_string = std::to_string(num1 - num2);
                break;
            case '*':
                result_string = std::to_string(num1 * num2);
                break;
            case '/':
                if (num2 == 0)
                {
                    result_label.setText(QString::fromStdString("除数不为0!"));
                    return;
                }
                result_string = std::to_string(num1 / num2);
            break;

            default:
                result_string = "不支持运算符!";
                break;
        }

    }
    else
    {
        result_string = "表达式错误!";
    }
    result_label.setText(QString::fromStdString(result_string));
    return;

}





// main.cpp
int main(int argc, char *argv[])
{
    QApplication app(argc,argv);
    Calculator calculator;
    calculator.show();
    return app.exec();

}










四、编写CMakeLists

cmake_minimum_required(VERSION 3.8)
project(calculator_qt)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

########################################################################


#查找Qt5 库,注意大小写
find_package(Qt5 REQUIRED COMPONENTS Widgets)
#生产moc文件
qt5_wrap_cpp(MOC_SOURCES include/calculator_qt/calculator.hpp)

#包含头文件 calculator.hpp
include_directories(
  include
)

#生成执行文件
add_executable(
  calculator
  "src/calculator.cpp"
  ${MOC_SOURCES}
)

#链接Qt5库
target_link_libraries(
  calculator
  Qt5::Widgets
)
#安装
install(
  TARGETS calculator
  DESTINATION lib/${PROJECT_NAME}
)

########################################################################


if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

五、编译运行

在ws目录下执行

colcon build

结果:

iise@iise-virtual-machine:~/workspace/calculate_qt_ws$ colcon build
Starting >>> calculator_qt
Finished <<< calculator_qt [9.23s]                     

Summary: 1 package finished [9.58s]

然后执行即可

source install/setup.bash 
ros2 run calculator_qt calculator 

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐