rviz添加qt插件

一、增加rviz plugin插件

资料:http://admin.guyuehome.com/42336
https://blog.51cto.com/u_13625033/6126970

  • 这部分代码只是将上面两个链接中的代码整合在了一起,整合在一起后可以更好的理解其中的关系

1、创建软件包

catkin_create_pkg rviz_teleop_commander roscpp rviz std_msgs

在这里插入图片描述

2、创建​plugin_description.xml​​文件

  • 最后只是生成了一个动态库so文件,一个库里可以有多个插件,所以只有一个library
<library path="lib/librviz_teleop_commander"><class name="rviz_teleop_commander/TeleopPanel"type="rviz_teleop_commander::TeleopPanel"base_class_type="rviz::Panel"><description>A panel widget allowing simple diff-drive style robot base control.</description></class><class name="rviz_teleop_commander/cmd_control"type="rviz_teleop_commander::cmd_control"base_class_type="rviz::Panel"><description>A panel widget allowing simple diff-drive style robot base control.</description></class>
</library>

3、处理package.xml文件

  • 这部分不需要改太多,只在最后增加一个export即可
<?xml version="1.0"?>
<package format="2"><name>rviz_teleop_commander</name><version>0.0.0</version><description>The rviz_teleop_commander package</description><!-- One maintainer tag required, multiple allowed, one person per tag --><!-- Example:  --><!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --><maintainer email="wangyuanhao@todo.todo">wangyuanhao</maintainer><!-- One license tag required, multiple allowed, one license per tag --><!-- Commonly used license strings: --><!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --><license>TODO</license><!-- Url tags are optional, but multiple are allowed, one per tag --><!-- Optional attribute type can be: website, bugtracker, or repository --><!-- Example: --><!-- <url type="website">http://wiki.ros.org/rviz_teleop_commander</url> --><!-- Author tags are optional, multiple are allowed, one per tag --><!-- Authors do not have to be maintainers, but could be --><!-- Example: --><!-- <author email="jane.doe@example.com">Jane Doe</author> --><!-- The *depend tags are used to specify dependencies --><!-- Dependencies can be catkin packages or system dependencies --><!-- Examples: --><!-- Use depend as a shortcut for packages that are both build and exec dependencies --><!--   <depend>roscpp</depend> --><!--   Note that this is equivalent to the following: --><!--   <build_depend>roscpp</build_depend> --><!--   <exec_depend>roscpp</exec_depend> --><!-- Use build_depend for packages you need at compile time: --><!--   <build_depend>message_generation</build_depend> --><!-- Use build_export_depend for packages you need in order to build against this package: --><!--   <build_export_depend>message_generation</build_export_depend> --><!-- Use buildtool_depend for build tool packages: --><!--   <buildtool_depend>catkin</buildtool_depend> --><!-- Use exec_depend for packages you need at runtime: --><!--   <exec_depend>message_runtime</exec_depend> --><!-- Use test_depend for packages you need only for testing: --><!--   <test_depend>gtest</test_depend> --><!-- Use doc_depend for packages you need only for building documentation: --><!--   <doc_depend>doxygen</doc_depend> --><buildtool_depend>catkin</buildtool_depend><build_depend>roscpp</build_depend><build_depend>rviz</build_depend><build_depend>std_msgs</build_depend><build_export_depend>roscpp</build_export_depend><build_export_depend>rviz</build_export_depend><build_export_depend>std_msgs</build_export_depend><exec_depend>roscpp</exec_depend><exec_depend>rviz</exec_depend><exec_depend>std_msgs</exec_depend><!-- The export tag contains other, unspecified, tags --><export><!-- Other tools can request additional information be placed here --><rviz plugin="${prefix}/plugin_description.xml"/></export></package>

4、处理CMakeLists.txt文件

cmake_minimum_required(VERSION 3.0.2)
project(rviz_teleop_commander)## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTSroscpprvizstd_msgs
)###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES rviz_teleop_commander
#  CATKIN_DEPENDS roscpp rviz std_msgs
#  DEPENDS system_lib
)###########
## Build ##
############# Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include${catkin_INCLUDE_DIRS}
)####################################################################################
####################################################################################
## 找到相关的库
find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
set(QT_LIBRARIES Qt5::Widgets)## I prefer the Qt signals and slots to avoid defining "emit", "slots",
## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here.
add_definitions(-DQT_NO_KEYWORDS)## Here we specify which header files need to be run through "moc", Qt's meta-object compiler.
## 指定需要qt元编译的头文件
qt5_wrap_cpp(MOC_FILESsrc/teleop_pad.hsrc/cmd_control.h)## 定义SOURCE_FILES_1变量
message(MOC_FILES " ${MOC_FILES}")
set(SOURCE_FILES_1src/teleop_pad.cpp src/cmd_control.cpp ${MOC_FILES}
)## 生成库文件,定义库的名字与项目名字一样
add_library(${PROJECT_NAME} ${SOURCE_FILES_1})    
## 连接qt和ros的库到目标库
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${catkin_LIBRARIES})    ## Install rules 复制文件到指定位置
install(TARGETS ${PROJECT_NAME}ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)install(FILES plugin_description.xmlDESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})

5、编写代码

teleop_pad.h

#ifndef TELEOP_PAD_H
#define TELEOP_PAD_H//所需要包含的头文件
#ifndef Q_MOC_RUN
#include <ros/ros.h>
#include <ros/console.h>
#include <rviz/panel.h>   //plugin基类的头文件
#endifclass QLineEdit;namespace rviz_teleop_commander
{
// 所有的plugin都必须是rviz::Panel的子类
class TeleopPanel: public rviz::Panel
{
// 后边需要用到Qt的信号和槽,都是QObject的子类,所以需要声明Q_OBJECT宏
Q_OBJECT
public:// 构造函数,在类中会用到QWidget的实例来实现GUI界面,这里先初始化为0即可TeleopPanel( QWidget* parent = 0 );// 重载rviz::Panel积累中的函数,用于保存、加载配置文件中的数据,在我们这个plugin// 中,数据就是topic的名称virtual void load( const rviz::Config& config );virtual void save( rviz::Config config ) const;// 公共槽.
public Q_SLOTS:// 当用户输入topic的命名并按下回车后,回调用此槽来创建一个相应名称的topic publishervoid setTopic( const QString& topic );// 内部槽.
protected Q_SLOTS:void sendVel();                 // 发布当前的速度值void update_Linear_Velocity();  // 根据用户的输入更新线速度值void update_Angular_Velocity(); // 根据用户的输入更新角速度值void updateTopic();             // 根据用户的输入更新topic name// 内部变量.
protected:// topic name输入框QLineEdit* output_topic_editor_;QString output_topic_;// 线速度值输入框QLineEdit* output_topic_editor_1;QString output_topic_1;// 角速度值输入框QLineEdit* output_topic_editor_2;QString output_topic_2;// ROS的publisher,用来发布速度topicros::Publisher velocity_publisher_;// ROS节点句柄ros::NodeHandle nh_;// 当前保存的线速度和角速度值float linear_velocity_;float angular_velocity_;
};} // end namespace rviz_teleop_commander#endif // TELEOP_PANEL_H

teleop_pad.cpp

#include <stdio.h>#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>#include <geometry_msgs/Twist.h>
#include <QDebug>#include "teleop_pad.h"namespace rviz_teleop_commander
{// 构造函数,初始化变量
TeleopPanel::TeleopPanel( QWidget* parent ): rviz::Panel( parent ), linear_velocity_( 0 ), angular_velocity_( 0 )
{// 创建一个输入topic命名的窗口QVBoxLayout* topic_layout = new QVBoxLayout;topic_layout->addWidget( new QLabel( "Teleop Topic:" ));output_topic_editor_ = new QLineEdit;topic_layout->addWidget( output_topic_editor_ );// 创建一个输入线速度的窗口topic_layout->addWidget( new QLabel( "Linear Velocity:" ));output_topic_editor_1 = new QLineEdit;topic_layout->addWidget( output_topic_editor_1 );// 创建一个输入角速度的窗口topic_layout->addWidget( new QLabel( "Angular Velocity:" ));output_topic_editor_2 = new QLineEdit;topic_layout->addWidget( output_topic_editor_2 );QHBoxLayout* layout = new QHBoxLayout;layout->addLayout( topic_layout );setLayout( layout );// 创建一个定时器,用来定时发布消息QTimer* output_timer = new QTimer( this );// 设置信号与槽的连接// 输入topic命名,回车后,调用updateTopic()connect( output_topic_editor_, SIGNAL( editingFinished() ), this, SLOT( updateTopic() ));    // 输入线速度值,回车后,调用update_Linear_Velocity()    connect( output_topic_editor_1, SIGNAL( editingFinished() ), this, SLOT( update_Linear_Velocity() )); // 输入角速度值,回车后,调用update_Angular_Velocity()connect( output_topic_editor_2, SIGNAL( editingFinished() ), this, SLOT( update_Angular_Velocity() ));// 设置定时器的回调函数,按周期调用sendVel()connect( output_timer, SIGNAL( timeout() ), this, SLOT( sendVel() ));// 设置定时器的周期,100msoutput_timer->start( 100 );
}// 更新线速度值
void TeleopPanel::update_Linear_Velocity()
{// 获取输入框内的数据QString temp_string = output_topic_editor_1->text();// 将字符串转换成浮点数float lin = temp_string.toFloat();  // 保存当前的输入值linear_velocity_ = lin;
}// 更新角速度值
void TeleopPanel::update_Angular_Velocity()
{QString temp_string = output_topic_editor_2->text();float ang = temp_string.toFloat() ;  angular_velocity_ = ang;
}// 更新topic命名
void TeleopPanel::updateTopic()
{setTopic( output_topic_editor_->text() );
}// 设置topic命名
void TeleopPanel::setTopic( const QString& new_topic )
{// 检查topic是否发生改变.if( new_topic != output_topic_ ){output_topic_ = new_topic;// 如果命名为空,不发布任何信息if( output_topic_ == "" ){velocity_publisher_.shutdown();}// 否则,初始化publisherelse{velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>( output_topic_.toStdString(), 1 );}Q_EMIT configChanged();}
}// 发布消息
void TeleopPanel::sendVel()
{if( ros::ok() && velocity_publisher_ ){geometry_msgs::Twist msg;msg.linear.x = linear_velocity_;msg.linear.y = 0;msg.linear.z = 0;msg.angular.x = 0;msg.angular.y = 0;msg.angular.z = angular_velocity_;velocity_publisher_.publish( msg );}
}// 重载父类的功能
void TeleopPanel::save( rviz::Config config ) const
{rviz::Panel::save( config );config.mapSetValue( "Topic", output_topic_ );
}// 重载父类的功能,加载配置数据
void TeleopPanel::load( const rviz::Config& config )
{rviz::Panel::load( config );QString topic;if( config.mapGetString( "Topic", &topic )){output_topic_editor_->setText( topic );updateTopic();}
}} // end namespace rviz_teleop_commander// 声明此类是一个rviz的插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_teleop_commander::TeleopPanel,rviz::Panel )
// END_TUTORIAL

cmd_control.h

#ifndef CMD_CONTROL_H
#define CMD_CONTROL_H#include <stdio.h>//所需要包含的头文件
#include <ros/ros.h>
#include <ros/console.h>
#include <rviz/panel.h>   //plugin基类的头文件#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QPushButton>
#include <geometry_msgs/Twist.h>
#include <QDebug>
#include <QCheckBox>
#include <QSlider>
namespace rviz_teleop_commander {
class cmd_control:public rviz::Panel
{Q_OBJECT
public:// 构造函数,在类中会用到QWidget的实例来实现GUI界面,这里先初始化为0即可cmd_control(QWidget* parent=0);// 重载rviz::Panel积累中的函数,用于保存、加载配置文件中的数据,在我们这个plugin中,数据就是topic的名称
//    virtual void load( const rviz::Config& config );virtual void save( rviz::Config config ) const;void move_base(char k,float speed_linear,float speed_trun);
public Q_SLOTS:void slot_cmd_control();void on_Slider_raw_valueChanged(int);// 内部变量.
protected:QPushButton* pushButton_i;QPushButton* pushButton_u;QPushButton* pushButton_o;QPushButton* pushButton_j;QPushButton* pushButton_l;QPushButton* pushButton_m;QPushButton* pushButton_back;QPushButton* pushButton_backr;QCheckBox* is_all_check;QSlider* yaw_slider;QSlider* linera_slider;// ROS的publisher,用来发布速度topicros::Publisher velocity_publisher_;QString output_topic_="cmd_vel";// The ROS node handle.ros::NodeHandle nh_;// 当前保存的线速度和角速度值float linear_velocity_;float angular_velocity_;};
}#endif // CMD_CONTROL_H

cmd_control.cpp

#include "cmd_control.h"
#include <stdio.h>#include <QPainter>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>#include <geometry_msgs/Twist.h>
#include <QDebug>namespace rviz_teleop_commander {
cmd_control::cmd_control(QWidget* parent):rviz::Panel (parent)
{//初始化uiQVBoxLayout *mainlayout=new QVBoxLayout;pushButton_i=new QPushButton;pushButton_i->setText("i");//快捷键pushButton_i->setShortcut(QKeySequence(QLatin1String("i")));pushButton_i->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");pushButton_u=new QPushButton;//快捷键pushButton_u->setShortcut(QKeySequence(QLatin1String("u")));pushButton_u->setText("u");pushButton_u->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");pushButton_o=new QPushButton;//快捷键pushButton_o->setShortcut(QKeySequence(QLatin1String("o")));pushButton_o->setText("o");pushButton_o->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");QHBoxLayout *first=new QHBoxLayout;first->addWidget(pushButton_u);first->addWidget(pushButton_i);first->addWidget(pushButton_o);mainlayout->addLayout(first);pushButton_j=new QPushButton;pushButton_j->setText("j");//快捷键pushButton_j->setShortcut(QKeySequence(QLatin1String("j")));pushButton_j->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");is_all_check=new QCheckBox;is_all_check->setText("使用全向轮模式");//快捷键is_all_check->setShortcut(QKeySequence(QLatin1String("k")));pushButton_l=new QPushButton;pushButton_l->setText("l");//快捷键pushButton_l->setShortcut(QKeySequence(QLatin1String("l")));pushButton_l->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");QHBoxLayout *second=new QHBoxLayout;second->addWidget(pushButton_j);second->addWidget(is_all_check);second->addWidget(pushButton_l);mainlayout->addLayout(second);pushButton_m=new QPushButton;//快捷键pushButton_m->setShortcut(QKeySequence(QLatin1String("m")));pushButton_m->setText("m");pushButton_m->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");pushButton_back=new QPushButton;//快捷键pushButton_back->setShortcut(QKeySequence(QLatin1String(",")));pushButton_back->setText(",");pushButton_back->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");pushButton_backr=new QPushButton;//快捷键pushButton_backr->setShortcut(QKeySequence(QLatin1String(".")));pushButton_backr->setText(".");
pushButton_backr->setStyleSheet("QPushButton#pushButton_i:pressed{background-color:rgb(239, 41, 41)}");
QHBoxLayout *third=new QHBoxLayout;
third->addWidget(pushButton_m);
third->addWidget(pushButton_back);
third->addWidget(pushButton_backr);
mainlayout->addLayout(third);QLabel *linera_label=new QLabel;
linera_label->setText("线速度(cm/s)");
linera_slider=new QSlider;
linera_slider->setOrientation(Qt::Horizontal);  // 水平方向
linera_slider->setRange(0,100);
linera_slider->setValue(50);
QHBoxLayout *five=new QHBoxLayout;
five->addWidget(linera_label);
five->addWidget(linera_slider);
mainlayout->addLayout(five);QLabel *yaw_label=new QLabel;
yaw_label->setText("角速度(cm/s)");
yaw_slider=new QSlider;
yaw_slider->setOrientation(Qt::Horizontal);  // 水平方向
yaw_slider->setRange(0,100);
yaw_slider->setValue(100);
QHBoxLayout *six=new QHBoxLayout;
six->addWidget(yaw_label);
six->addWidget(yaw_slider);
mainlayout->addLayout(six);setLayout(mainlayout);//绑定信号//绑定速度控制按钮connect(pushButton_i,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_u,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_o,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_j,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_l,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_m,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_back,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));connect(pushButton_backr,SIGNAL(clicked()),this,SLOT(slot_cmd_control()));//创建发布者velocity_publisher_ = nh_.advertise<geometry_msgs::Twist>( output_topic_.toStdString(), 1 );}void cmd_control::slot_cmd_control()
{QPushButton* btn=qobject_cast<QPushButton*>(sender());char key=btn->text().toStdString()[0];//速度float liner=linera_slider->value()*0.01;float turn=yaw_slider->value()*0.01;bool is_all=is_all_check->isChecked();switch (key) {case 'u':move_base(is_all?'U':'u',liner,turn);break;case 'i':move_base(is_all?'I':'i',liner,turn);break;case 'o':move_base(is_all?'O':'o',liner,turn);break;case 'j':move_base(is_all?'J':'j',liner,turn);break;case 'l':move_base(is_all?'L':'l',liner,turn);break;case 'm':move_base(is_all?'M':'m',liner,turn);break;case ',':move_base(is_all?'<':',',liner,turn);break;case '.':move_base(is_all?'>':'.',liner,turn);break;}}
void cmd_control::move_base(char k,float speed_linear,float speed_trun)
{std::map<char, std::vector<float>> moveBindings{{'i', {1, 0, 0, 0}},{'o', {1, 0, 0, -1}},{'j', {0, 0, 0, 1}},{'l', {0, 0, 0, -1}},{'u', {1, 0, 0, 1}},{',', {-1, 0, 0, 0}},{'.', {-1, 0, 0, 1}},{'m', {-1, 0, 0, -1}},{'O', {1, -1, 0, 0}},{'I', {1, 0, 0, 0}},{'J', {0, 1, 0, 0}},{'L', {0, -1, 0, 0}},{'U', {1, 1, 0, 0}},{'<', {-1, 0, 0, 0}},{'>', {-1, -1, 0, 0}},{'M', {-1, 1, 0, 0}},{'t', {0, 0, 1, 0}},{'b', {0, 0, -1, 0}},{'k', {0, 0, 0, 0}},{'K', {0, 0, 0, 0}}};char key=k;//计算是往哪个方向float x = moveBindings[key][0];float y = moveBindings[key][1];float z = moveBindings[key][2];float th = moveBindings[key][3];//计算线速度和角速度float speed = speed_linear;float turn = speed_trun;// Update the Twist messagegeometry_msgs::Twist twist;twist.linear.x = x * speed;twist.linear.y = y * speed;twist.linear.z = z * speed;twist.angular.x = 0;twist.angular.y = 0;twist.angular.z = th * turn;// Publish it and resolve any remaining callbacksvelocity_publisher_.publish(twist);ros::spinOnce();
}// 重载父类的功能
void cmd_control::save( rviz::Config config ) const
{rviz::Panel::save( config );config.mapSetValue( "Topic", output_topic_ );
}}// 声明此类是一个rviz的插件
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(rviz_teleop_commander::cmd_control,rviz::Panel )
// END_TUTORIAL

6、编译并使用

  • 编译通过后,打开rviz即可调用插件
    在这里插入图片描述

二、通过Qt可视化工具构建rviz插件

1、qt creator开发

  • rviz插件的源代码的主要库是qt库,qt库的常见开发方式是使用qt creator,代码框架主要是主函数+定义ui界面的cpp文件和h文件。
  • 主函数基本就是启动代码,不用修改。
#include "mainwindow.h"#include <QApplication>
#include <QLocale>
#include <QTranslator>int main(int argc, char *argv[])
{QApplication a(argc, argv);QTranslator translator;const QStringList uiLanguages = QLocale::system().uiLanguages();for (const QString &locale : uiLanguages) {const QString baseName = "qt_to_rviz_" + QLocale(locale).name();if (translator.load(":/i18n/" + baseName)) {a.installTranslator(&translator);break;}}MainWindow w;w.show();return a.exec();
}
  • 头文件中声明需要用到的组件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
private:QLabel *lab;  //这里声明了一个标签组建,记得要引入对应组建的头文件
};
#endif // MAINWINDOW_H
  • cpp文件主要在构造函数中定义和启动组建
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{this->lab = new QLabel("Hello, world!", this);ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}

在这里插入图片描述

  • 这是普通qt程序的开发和使用方法,这里只有qt实现的界面可视化代码,没有增加业务功能代码。只要把这部分代码和业务代码耦合在一起就可以实现效果了

2、qt designer

  • 还有一种方法是使用qt designer,这种工具通过可视化界面设计ui界面并设置相关配置,最后通过uic工具生成h文件,h文件中会有qt功能的主要代码,在其基础之上修改即可。
  • 在qt designer中设计ui界面,保存为ui文件
    在这里插入图片描述* 使用uic生成头文件,相关类可以从这个头文件中挑选和复用代码,不过还是有挺多要修改的
uic mainwindow.ui -o qwe.h
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.15.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/#ifndef QWE_H
#define QWE_H#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>QT_BEGIN_NAMESPACEclass Ui_MainWindow
{
public:QWidget *centralwidget;QPushButton *pushButton;QLabel *label;QLineEdit *lineEdit;void setupUi(QMainWindow *MainWindow){//主界面if (MainWindow->objectName().isEmpty())MainWindow->setObjectName(QString::fromUtf8("MainWindow"));MainWindow->resize(800, 600);//核心部件,管理者?centralwidget = new QWidget(MainWindow);centralwidget->setObjectName(QString::fromUtf8("centralwidget"));//按键部件pushButton = new QPushButton(centralwidget);pushButton->setObjectName(QString::fromUtf8("pushButton"));pushButton->setGeometry(QRect(120, 250, 89, 25));//标签部件label = new QLabel(centralwidget);label->setObjectName(QString::fromUtf8("label"));label->setGeometry(QRect(370, 220, 201, 21));//横线编辑框lineEdit = new QLineEdit(centralwidget);lineEdit->setObjectName(QString::fromUtf8("lineEdit"));lineEdit->setGeometry(QRect(250, 360, 113, 25));//设置核心部件MainWindow->setCentralWidget(centralwidget);//渲染retranslateUi(MainWindow);//连接槽位QMetaObject::connectSlotsByName(MainWindow);} // setupUivoid retranslateUi(QMainWindow *MainWindow){MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));pushButton->setText(QCoreApplication::translate("MainWindow", "PushButton", nullptr));label->setText(QCoreApplication::translate("MainWindow", "hellow world", nullptr));} // retranslateUi};namespace Ui {class MainWindow: public Ui_MainWindow {};
} // namespace UiQT_END_NAMESPACE#endif // QWE_H

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/133842.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IntelliJ IDEA 如何修改默认Maven仓库地址

在使用idea过程中&#xff0c;每次新建项目或者打开项目时&#xff0c;maven仓库地址都会变为默认地址。如何修改默认地址&#xff0c;让其保持不变&#xff0c;如下这种方式可以简单快捷的设置。 1.打开idea&#xff0c;取消项目自动加载 2.点击 Customize,然后再点击 All se…

DeepLearning - 余弦退火热重启学习率 CosineAnnealingWarmRestartsLR

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134249925 CosineAnnealingWarmRestartsLR&#xff0c;即 余弦退火热重启学习率&#xff0c;周期性修改学习率的下降和上升&#xff0c;间隔幅度逐…

K7系列FPGA进行FLASH读写1——CCLK控制(STARTUPE2原语)

最近的工作涉及对 FPGA 进行远程更新&#xff0c;也就是通过远程通信接口将 .bin 文件送到 FPGA&#xff0c;然后写入 FLASH&#xff0c;这样当 FPGA 重新上电后就可以执行更新后的程序了。因此第一步工作就是进行 FLASH 的读写控制。 然而如果尝试配置 FLASH 管脚时&#xff0…

Android Datastore 动态创建与源码解析

涉及到的知识点 1、协程原理---->很好的博客介绍&#xff0c;一个小故事讲明白进程、线程、Kotlin 协程到底啥关系&#xff1f; 2、Channel知识点---->Android—kotlin-Channel超详细讲解 3、Coroutines : CompletableDeferred and structured concurrency 封装的DataS…

数学建模比赛中常用的建模提示词(数模prompt)

以下为数学建模比赛中常用的建模提示词&#xff0c;希望对你有所帮助&#xff01; 帮我总结一下数学建模有哪些预测类算法&#xff1f; 灰色预测模型级比检验是什么意思? 描述一下BP神经网络算法的建模步骤 对于分类变量与分类变量相关性分析用什么算法 前10年的数据分别是1&a…

代码随想录 Day38 完全背包问题 LeetCode T70 爬楼梯 T322 零钱兑换 T279 完全平方数

前言 在今天的题目开始之前,让我们来回顾一下之前的知识,动规五部曲 1.确定dp数组含义 2.确定dp数组的递推公式 3.初始化dp数组 4.确定遍历顺序 5.打印dp数组来排错 tips: 1.当求取物品有限的时候用0-1背包,求取物品无限的时候用完全背包 结果是排列还是组合也有说法,当结果是组…

渗透实战靶机2wp

0x00 简介 1、测试环境 目标IP&#xff1a;10.xxxx 测试IP&#xff1a;192.168.139.128 测试环境&#xff1a;win10、kali等 测试时间&#xff1a;2021.7.22-2021.7.22 测试人员&#xff1a;ruanruan 2、测试过程 本次实战主要通过对收集到的端口、目录等信息进行持续整…

润和软件HopeStage与奇安信网神终端安全管理系统、可信浏览器完成产品兼容性互认证

近日&#xff0c;江苏润和软件股份有限公司&#xff08;以下简称“润和软件”&#xff09;HopeStage 操作系统与奇安信网神信息技术&#xff08;北京&#xff09;股份有限公司&#xff08;以下简称“奇安信”&#xff09;终端安全管理系统、可信浏览器完成产品兼容性测试。 测试…

阿里云二级域名绑定与宝塔Nginx反向代理配置

在阿里或者腾讯...各大域名商买好域名&#xff0c;备案解析好&#xff0c;目标URL&#xff0c;是真正的地址&#xff0c;比如一些端口&#xff0c;后者会自动填写。 注意ssl配置好&#xff0c;这里不要带反代端口

vue中异步更新$nextTick

1.需求 编辑标题, 编辑框自动聚焦 点击编辑&#xff0c;显示编辑框让编辑框&#xff0c;立刻获取焦点 2.代码实现 <template><div class"app"><div v-if"isShowEdit"><input type"text" v-model"editValue"…

王道p18 第12题假设 A中的 n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素:否则输出-1

视频讲解在&#xff1a;&#x1f447; p18 第12题 c语言实现王道数据结构课后习题_哔哩哔哩_bilibili 从前向后扫描数组元素&#xff0c;标记出一个可能成为主元素的元素 Num。然后重新计数&#xff0c;确认 Num 是否是主元素。 我们可分为以下两步: 1.选取候选的主元素。依…

YOLO目标检测——汽车头部尾部检测数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;用于训练自动驾驶系统中的车辆感知模块&#xff0c;以实现对周围车辆头部和尾部的准确检测和识别数据集说明&#xff1a;汽车头部尾部检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软…

【JMeter】后置处理器的分类以及场景介绍

1.常用后置处理器的分类 Json提取器 针对响应体的返回结果是json格式的会自动生成新的变量名为【提取器中变量名_MatchNr】,取到的个数由jsonpath expression取到的个数决定 可以当作普通变量调用,调用语法:${提取器中变量名_MatchNr}正则表达式提取器 返回结果是任何数据格…

一款好用的PDF转翻页电子书网站

​你是否曾经遇到过PDF文件无法翻页或者阅读不便的问题&#xff1f;今天给大家推荐一款好用的PDF转翻页电子书网站&#xff0c;让你轻松阅读PDF文件&#xff0c;不再烦恼翻页问题&#xff01; 一、网站介绍 这款FLBOOK在线制作电子杂志网站支持多种电子文件格式转换&#xff0…

JWT简介 JWT结构 JWT示例 前端添加JWT令牌功能 后端程序

目录 1. JWT简述 1.1 什么是JWT 1.2 为什么使用JWT 1.3 JWT结构 1.4 验证过程 2. JWT示例 2.1 后台程序 2.2 前台加入jwt令牌功能 1. JWT简述 1.1 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准&#xff08;(RFC 7…

〔001〕虚幻 UE5 安装教程

✨ 目录 🎈 下载启动程序🎈 注册个人账户🎈 选择引擎版本🎈 选择安装选项🎈 虚幻商城的使用🎈 每月免费插件🎈 安装插件🎈 下载启动程序 下载地址:https://www.unrealengine.com/zh-CN/download点击上面地址,下载 UE5 启动程序并安装🎈 注册个人账户 打开商…

Linux多虚拟主机和配置限制访问与日志

目录 一、多虚拟主机 1.配置单网卡多个ip 2.给每个主机站点设置主页 3.测试访问 二、限制访问 1.限制所有 2.放行192.168.0.0/24网段访问 三、日志与状态页 1.定义访客日志 2.状态页配置 一、多虚拟主机 1.配置单网卡多个ip ip address add 192.168.0.231/24 dev e…

案例研究|腾讯音乐娱乐集团与JumpServer共探安全运维审计解决方案

近年来&#xff0c;得益于人民消费水平的提升以及版权意识的加强&#xff0c;用户付费意愿和在线用户数量持续增长&#xff0c;中国在线音乐市场呈现出稳定增长的发展态势。随着腾讯音乐于2018年12月上市&#xff0c;进一步推动了中国在线音乐市场的发展。 腾讯音乐娱乐集团&a…

rust入门基础案例:猜数字游戏

案例出处是《Rust权威指南》&#xff0c;书中有更加详细的解释。从这个例子中&#xff0c;我们可以了解到 rust 的两个操作&#xff1a; 如何从控制台读取用户输入rust 如何生成随机数 代码格式化 编译器可在保存时对代码做格式化处理&#xff0c;底层调用 rustfmt 来实现&a…

Kubernetes Dashboard 用户名密码方式登录

Author&#xff1a;rab 前言 为了 K8s 集群安全&#xff0c;默认情况下 Dashboard 以 Token 的形式登录的&#xff0c;那如果我们想以用户名/密码的方式登录该怎么操作呢&#xff1f;其实只需要我们创建用户并进行 ClusterRoleBinding 绑定即可&#xff0c;接下来是具体的操作…