使用ROS2 + Qt编写一个简易计算器
先看结果。
·
先看结果

一、搭建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
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)