簡體   English   中英

Qt和C ++-我自己的類和信號/插槽

[英]Qt and C++ - my own class and signals/slots

我已經通過編寫簡單的GUI開始使用C ++學習Qt。 在開始學習信號和插槽的機制后,我決定編寫程序,使我們能夠控制工業機器人手臂。 這樣的想法很簡單:我們有6個按鈕,並根據按下的按鈕而不同,然后出現一個文本,描述我們做了什么。 例如:“手臂移到左側”。

我要進行構建,但是首先我要向您提出一些問題。

這是我的代碼:

Arm.h:

#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

Arm.cpp:

#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);
}

MainWindow.h:

#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

MainWindow.cpp:

#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);
}

main.cpp:

#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow w;
    w.show();

    return a.exec();
}

如您所見,沒有什么特別的。 我的問題:

  1. 我在MainWindow類中不了解ui 它是什么?對Qt有什么幫助?

  2. 當我創建指向函數的指針的向量時,我需要使它們成為靜態的,以另一種方式,我不能將它們放入向量中。 為什么? (類Arm

  3. MainWindow構造方法。 通常,構造函數在創建對象時僅被調用一次,那么為什么MainWindow.cpp connect方法在整個程序中起作用?

  4. 如您所見,有6種方法可以使用我自己的函數。 我將它們命名為: void useVector0() 我確實確信這樣做非常不好。 應該有一種方法,但是如果我做類似的事情:

     void MainWindow::useVector(unsigned short k){ arm.vctrMovesFun[k](); arm.displayMoves(label); 

    我不能將其用作插槽,因為信號clicked()沒有參數。 怎么解決呢? 重載clicked()方法?

  5. 也許您對我的代碼有一般的看法,所以寫吧。 我會為每一個批評的話感到高興。

正如其他人已經指出的那樣,您的問題需要改進。 建議您閱讀“ 如何提問” ,在哪里可以找到關於如何在這里問以及如何問一個好的問題的良好指導

盡管如此,我將給您一個簡短的答案,希望它可以讓您提出一個更具體的新問題(如果有)。


  1. 什么是.ui文件,適合“ Qt-Form-Class”?

    現在,您正在MainWindow的構造函數中創建按鈕。 對於簡單的GUI來說可能沒問題,但是您必須“猜測”按鈕的位置。

    如果使用Qt Designer ,則可以在某些工具的幫助下創建布局。 在設計器中放置了一些元素之后,您將可以從如下代碼中訪問它們:

     ui->label1->setText("hello World"); 

    您可以通過在代碼中使用connect()或通過使用Designer將它們添加到UI文件中,來將這些UI窗口小部件的信號連接到插槽。


  1. 如何創建指向成員函數的指針?

    http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions

  1. 不知道你在這里問什么

  1. 如何根據發件人在插槽中執行不同的代碼?

    看看QSignalMapper

    它不會像您要求的那樣給您一個unsigned short k ,而是一個QString具體取決於哪個小部件發出信號。


  1. 您可以查看我的代碼嗎?

    現在,對於Code Review Stack Exchange網站絕對是一個問題。

  1. QMainWindow用作(猜測)主窗口時與QWidget基本相同,值得注意的區別是QWidget期望您的應用程序中只有1個窗口,而QMainWindow則更多地是充當“控制”最重要的窗口所有其余的(例如警報消息框)。 除非您確定甚至需要QMainWindow,否則在大多數情況下,您實際上應該使用QWidget作為基礎。

  2. 我對此並不完全確定,所以請不要將其視為聖經規則,但如果我沒有記錯的話:成員類函數不會針對每個對象重復,這意味着該類的每個實例都將調用分配給該函數的唯一地址在課堂創作中。 換句話說-它們是靜態的。

  3. 注意,程序中的“ 無處不在 ”實際上是在構造函數內部。 極客 大多數Qt編碼在創建時都發生在主窗口構造函數的范圍內。 如果您習慣於main.cpp內部的main(),則很難理解。 當然,“連接”方法在構造函數內部的任何地方都可以使用,因為構造函數與該類的其他任何方法都在同一范圍內(畢竟構造函數也是一種方法)

  4. 確實有更好的方法。 qt5的新“連接”版本引用了信號和插槽功能,而不是宏SLOT()和SIGNAL(),這意味着您可以更靈活,更靈活地進行安裝。 您應該采用該新版本,或者至少要知道它的存在,因為它很棒。 (您使用的是qt4版本的connect,仍然支持該功能)

  5. 不幸的是,您可以將TLDR:D視為批評家。 在您的項目中祝您好運m9

我在MainWindow類中不了解ui。 它是什么?對Qt有什么幫助?

當前,您正在用代碼創建GUI。 但是,有些應用程序(例如Qt Creator的“設計”模式)將編寫為您創建GUI的代碼。 問題在於,如果您隨后編輯該代碼,Qt Creator將很難協調您的修改與要進行的任何更改。

為避免此問題,請在ui實例變量中使用該對象。 該對象是Qt Creator生成的,您無需觸摸該代碼。 取而代之的是,所有代碼進入你的MainWindow

當我創建指向函數的指針的向量時,我需要使它們成為靜態的,以另一種方式,我不能將它們放入向量中。 為什么? (手臂類)

靜態函數是獨立函數。 他們沒有與之關聯的對象。 另一方面,成員函數(對象中的非靜態函數)具有“ this”。 因此,要調用獨立函數,只需調用MyFunction( 1 )或其他任何方法,而要調用成員函數,則需要告訴它要調用哪個對象的成員函數( myObject->MyMemberFunction( 1 ) )。

您的定義是保留指向獨立函數的指針,因此沒有空間來存儲對象指針與成員函數一起使用。

如果您想了解有關成員函數指針的更多信息,請在任何優秀的C ++教科書中查找該主題。 也就是說,Qt將C ++的指向成員函數的指針隱藏在插槽和信號后。 因此,您可能只想不保留一個數組,而是定義一個數組。

MainWindow中的構造方法。 通常,構造函數在創建對象時僅被調用一次,那么為什么MainWindow.cpp中的connect方法在整個程序中起作用?

您的項目中只有一個MainWindow對象,它是在main()的開始處創建的,並且僅在main()退出后才消失。 因此,它的壽命與整個應用程序一樣長。

如您所見,有6種方法可以使用我自己的函數。 我將它們命名為:void useVector0()。 我確實確信這樣做非常不好。 (...)我不能將其用作插槽,因為信號clicked()沒有參數。

我認為您需要使用QSignalMapper: 將參數傳遞到插槽

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM