[英]Qt and C++ - my own class and signals/slots
我已经通过编写简单的GUI开始使用C ++学习Qt。 在开始学习信号和插槽的机制后,我决定编写程序,使我们能够控制工业机器人手臂。 这样的想法很简单:我们有6个按钮,并根据按下的按钮而不同,然后出现一个文本,描述我们做了什么。 例如:“手臂移到左侧”。
我要进行构建,但是首先我要向您提出一些问题。
这是我的代码:
#ifndef ARM_H
#define ARM_H
#include <QVector>
#include <QString>
#include <QLabel>
class Arm{
public:
Arm();
static void displayMoves(QLabel *ptrQLabel); //function for display QString listMoves
QVector<bool(*)(void)> vctrMovesFun; //contains pointers for function which defines moves of industrial robot
private:
static QString listMoves; //contain every move which industrial robot has done
static bool moveArmForward();
static bool moveArmBackward();
static bool moveArmLeft();
static bool moveArmRight();
static bool spinArmLeft();
static bool spinArmRight(); //all this functions define moves of robot's arm
};
#endif // ARM_H
#include "arm.h"
QString Arm::listMoves = ""; //empty string
//***************************************************************
Arm::Arm(){
vctrMovesFun = {&moveArmForward, &moveArmBackward, &moveArmLeft,
&moveArmRight, &spinArmLeft, &spinArmRight}; //set reference to functions
}
//***************************************************************
bool Arm::moveArmForward(){
listMoves+= "Arm moved forward\n";
return true;}
//***************************************************************
bool Arm::moveArmBackward(){
listMoves+= "Arm moved backward\n";
return true;}
//***************************************************************
bool Arm::moveArmLeft(){
listMoves+= "Arm moved to the left\n";
return true;}
//***************************************************************
bool Arm::moveArmRight(){
listMoves+= "Arm moved to the right\n";
return true;}
//***************************************************************
bool Arm::spinArmLeft(){
listMoves+= "Arm spinned to the left\n";
return true;}
//***************************************************************
bool Arm::spinArmRight(){
listMoves+= "Arm spinned to the right\n";
return true;}
//***************************************************************
void Arm::displayMoves(QLabel *ptrQLabel){
ptrQLabel -> setText(listMoves);
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "arm.h"
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;}
class MainWindow : public QMainWindow{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QPushButton *button0;
QPushButton *button1;
QPushButton *button2;
QPushButton *button3;
QPushButton *button4;
QPushButton *button5;
QLabel *label;
Arm arm;
private slots:
void useVector0();
void useVector1();
void useVector2();
void useVector3();
void useVector4();
void useVector5();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui -> setupUi(this);
this -> setGeometry(0,0,800,700);
this -> setStyleSheet("background-color:rgb(188, 198 ,204)");
button0 = new QPushButton("Move forward", this);
button0 -> setGeometry(50,50, 100,50);
button0 -> setStyleSheet("background-color:rgb(108, 118, 143)");
connect(button0, SIGNAL (clicked()), this, SLOT (useVector0()));
button1 = new QPushButton("Move backward", this);
button1 -> setGeometry(50,150, 100,50);
button1 -> setStyleSheet("background-color:rgb(108, 118, 143)");
connect(button1, SIGNAL (clicked()), this, SLOT (useVector1()));
button2 = new QPushButton("Move left", this);
button2 -> setGeometry(50,250, 100,50);
button2 -> setStyleSheet("background-color:rgb(108, 118, 143)");
connect(button2, SIGNAL (clicked()), this, SLOT (useVector2()));
button3 = new QPushButton("Move right", this);
button3 -> setGeometry(50,350, 100,50);
button3 -> setStyleSheet("background-color:rgb(108, 118, 143)");
connect(button3, SIGNAL (clicked()), this, SLOT (useVector3()));
button4 = new QPushButton("Spin left", this);
button4 -> setGeometry(50,450, 100,50);
button4 -> setStyleSheet("background-color:rgb(108, 118, 143)");
connect(button4, SIGNAL (clicked()), this, SLOT (useVector4()));
button5 = new QPushButton("Spin right", this);
button5 -> setGeometry(50,550, 100,50);
button5 -> setStyleSheet("background-color:rgb(108, 118, 143)");
connect(button5, SIGNAL (clicked()), this, SLOT (useVector5()));
label = new QLabel("", this);
label ->setStyleSheet("background-color:rgb(0, 0, 0)");
label -> setGeometry(300,50,300,600);
}
//************************************************************************
MainWindow::~MainWindow(){
delete ui;
}
//*************************************************************************
void MainWindow::useVector0(){
arm.vctrMovesFun[0]();
arm.displayMoves(label);}
//*************************************************************************
void MainWindow::useVector1(){
arm.vctrMovesFun[1]();
arm.displayMoves(label);
}
//*************************************************************************
void MainWindow::useVector2(){
arm.vctrMovesFun[2]();
arm.displayMoves(label);
}
//*************************************************************************
void MainWindow::useVector3(){
arm.vctrMovesFun[3]();
arm.displayMoves(label);
}
//*************************************************************************
void MainWindow::useVector4(){
arm.vctrMovesFun[4]();
arm.displayMoves(label);
}
//*************************************************************************
void MainWindow::useVector5(){
arm.vctrMovesFun[5]();
arm.displayMoves(label);
}
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
如您所见,没有什么特别的。 我的问题:
我在MainWindow
类中不了解ui
。 它是什么?对Qt有什么帮助?
当我创建指向函数的指针的向量时,我需要使它们成为静态的,以另一种方式,我不能将它们放入向量中。 为什么? (类Arm
)
MainWindow
构造方法。 通常,构造函数在创建对象时仅被调用一次,那么为什么MainWindow.cpp
connect
方法在整个程序中起作用?
如您所见,有6种方法可以使用我自己的函数。 我将它们命名为: void useVector0()
。 我确实确信这样做非常不好。 应该有一种方法,但是如果我做类似的事情:
void MainWindow::useVector(unsigned short k){ arm.vctrMovesFun[k](); arm.displayMoves(label);
我不能将其用作插槽,因为信号clicked()
没有参数。 怎么解决呢? 重载clicked()
方法?
也许您对我的代码有一般的看法,所以写吧。 我会为每一个批评的话感到高兴。
正如其他人已经指出的那样,您的问题需要改进。 建议您阅读“ 如何提问” ,在哪里可以找到关于如何在这里问以及如何问一个好的问题的良好指导 。
尽管如此,我将给您一个简短的答案,希望它可以让您提出一个更具体的新问题(如果有)。
现在,您正在MainWindow
的构造函数中创建按钮。 对于简单的GUI来说可能没问题,但是您必须“猜测”按钮的位置。
如果使用Qt Designer ,则可以在某些工具的帮助下创建布局。 在设计器中放置了一些元素之后,您将可以从如下代码中访问它们:
ui->label1->setText("hello World");
您可以通过在代码中使用connect()
或通过使用Designer将它们添加到UI文件中,来将这些UI窗口小部件的信号连接到插槽。
看看QSignalMapper 。
它不会像您要求的那样给您一个unsigned short k
,而是一个QString
具体取决于哪个小部件发出信号。
现在,对于Code Review Stack Exchange网站绝对是一个问题。
QMainWindow用作(猜测)主窗口时与QWidget基本相同,值得注意的区别是QWidget期望您的应用程序中只有1个窗口,而QMainWindow则更多地是充当“控制”最重要的窗口所有其余的(例如警报消息框)。 除非您确定甚至需要QMainWindow,否则在大多数情况下,您实际上应该使用QWidget作为基础。
我对此并不完全确定,所以请不要将其视为圣经规则,但如果我没有记错的话:成员类函数不会针对每个对象重复,这意味着该类的每个实例都将调用分配给该函数的唯一地址在课堂创作中。 换句话说-它们是静态的。
注意,程序中的“ 无处不在 ”实际上是在构造函数内部。 极客 大多数Qt编码在创建时都发生在主窗口构造函数的范围内。 如果您习惯于main.cpp内部的main(),则很难理解。 当然,“连接”方法在构造函数内部的任何地方都可以使用,因为构造函数与该类的其他任何方法都在同一范围内(毕竟构造函数也是一种方法)
确实有更好的方法。 qt5的新“连接”版本引用了信号和插槽功能,而不是宏SLOT()和SIGNAL(),这意味着您可以更灵活,更灵活地进行安装。 您应该采用该新版本,或者至少要知道它的存在,因为它很棒。 (您使用的是qt4版本的connect,仍然支持该功能)
不幸的是,您可以将TLDR:D视为批评家。 在您的项目中祝您好运m9
当前,您正在用代码创建GUI。 但是,有些应用程序(例如Qt Creator的“设计”模式)将编写为您创建GUI的代码。 问题在于,如果您随后编辑该代码,Qt Creator将很难协调您的修改与要进行的任何更改。
为避免此问题,请在ui
实例变量中使用该对象。 该对象是Qt Creator生成的,您无需触摸该代码。 取而代之的是,所有的代码进入你的MainWindow
。
静态函数是独立函数。 他们没有与之关联的对象。 另一方面,成员函数(对象中的非静态函数)具有“ this”。 因此,要调用独立函数,只需调用MyFunction( 1 )
或其他任何方法,而要调用成员函数,则需要告诉它要调用哪个对象的成员函数( myObject->MyMemberFunction( 1 )
)。
您的定义是保留指向独立函数的指针,因此没有空间来存储对象指针与成员函数一起使用。
如果您想了解有关成员函数指针的更多信息,请在任何优秀的C ++教科书中查找该主题。 也就是说,Qt将C ++的指向成员函数的指针隐藏在插槽和信号后。 因此,您可能只想不保留一个数组,而是定义一个数组。
您的项目中只有一个MainWindow对象,它是在main()
的开始处创建的,并且仅在main()
退出后才消失。 因此,它的寿命与整个应用程序一样长。
我认为您需要使用QSignalMapper: 将参数传递到插槽
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.