将一个 QWidget 链接到另一个新创建的 QWidget

Linking a QWidget to another QWidget new created

我正在尝试通过在主 QWidget 中按下一个按钮来创建一个新的 QWidget。在那个新创建的 QWidget 中,我想将一个按钮连接到主 QWidget 的插槽。

class UI : public QWidget
{
public:
    UI(){connection();};
private:
    QPushButton* all = new QPushButton{ "ALL" };
    void connection(){
       QObject::connect(all,QPushButton::clicked,[](){
             SmallGUI* s=new SmallGUI{};
             s->show();
       });
    }

    void something(){
       //something
    }

和第二个class

class SmallGUI1 :
    public QWidget
{
public:
    SmallGUI(){connection();};
private:
     QPushButton* N =new QPushButton;
     
     void connection(){
       //to connect N to something()
     }

我想将 N 连接到 something() 。

在我们开始之前,您的代码还有一些其他问题。

请注意,在您的第二个 class 中, 构造函数的名称与 class 不同,这会导致一些...问题。 您还忘记为您的按钮设置一个父级(这可能会导致一些意想不到的结果)并且为您的小部件(这又不是一个好主意想法)。

话虽如此,让我们进入正题。

我倾向于只在 .h 文件中放置原型和声明属性以使代码更清晰,但您当然可以根据自己的需要或自己的编程约定进行调整。

有几种方法可以做这样的事情,但最简单的应该是这样的:

SmallGUI1.h :

#include "UI.h" //The file in which the class UI is declared
//OR :
//class UI; //If you need to include this file in UI.h

class SmallGUI1 : public QWidget{

            Q_OBJECT //Q_OBJECT macro, check the doc for more explainations about it

public:
    explicit SmallGUI1(UI *parent = nullptr); //Explicit means that this constructor cannot be used for implicit casts
    ~SmallGUI1();//Destructor needed because I only put the constructor above
private:
     QPushButton* N; //Not very good looking to initialize attributes in the .h in my opinion, but works fine.

     }
 

SmallGUI1.cpp :

SmallGUI1::SmallGUI1(UI *parent) : QWidget(parent){
    
    N = new QPushButton(tr("Some text on the button") , this); //tr to enable translation on this string
    
    
    //************* If I understood your question correctly, this is what you are looking for *************
    connect(N , &QPushButton::clicked , parent , &UI::doSomething); //Select the signal you want
    
    /*
    Some code here
    */
    
    show();
    
}

SmallGUI1::~SmallGUI1(){qDeleteAll(children());}

UI.h :

class UI : public QWidget{
    
        Q_OBJECT
    
public:
    explicit UI(QWidget *parent = nullptr);
    ~UI();
private:
    QPushButton* all;

private slots :
    void createSmallGUI1();
    void doSomething();
}

UI.cpp :

#include "SmallGUI1.h"

UI::UI(QWidget *parent) : QWidget(parent){
    
    all = new QPushButton(tr("ALL") , this);
        
        
    connect(all , &QPushButton::clicked , this , &UI::createSmallGUI1);
    /*
    Some code here
    */
    
    
}

UI::~UI(){qDeleteAll(children());}

void UI::createSmallGUI1(){SmallGUI1 *gui = new SmallGUI1(this);}

void UI::doSomething(){
    
    /*
    Clever code here
    */
    
}

您可以将第二个小部件定义为主要小部件的子部件以简化操作:

class UI : public QWidget {
...
 private:
  SmallGUI* s;
...

然后在 UI 构造函数中初始化它,连同你的 all 按钮。您最初可以隐藏子窗口小部件或禁用它:

   UI() {
    all = new QPushButton{"ALL", this};
    setWindowTitle("UI");  // just for clarification
    s = new SmallGUI(this);
    s->hide();
    connection();
  };

和'show'它带有按钮点击信号

connect(all, &QPushButton::clicked, s, &SmallGUI::show);

这样做可以让您选择将 N 按钮的点击信号连接到父 class

中的 something 函数
connect(s->N, &QPushButton::clicked, this, &UI::something);

完整的程序如下,

#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QWidget>

class SmallGUI : public QWidget {
 public:
  SmallGUI(QWidget* parent) : QWidget(parent) {
    N = new QPushButton{"btn2", this};
    connection();
  };
  QPushButton* N;

 private:
  void connection(){};
};

class UI : public QWidget {
 public:
  UI() {
    all = new QPushButton{"ALL", this};
    setWindowTitle("UI");  // just for clarification
    s = new SmallGUI(this);
    s->hide();
    connection();
  };

 private:
  SmallGUI* s;
  QPushButton* all;
  void connection() {
    connect(all, &QPushButton::clicked, s, &SmallGUI::show);

    connect(s->N, &QPushButton::clicked, this, &UI::something);
  }

  void something() { QMessageBox::information(this, "Hello", "Hello"); }
};

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

  UI w;
  w.show();

  return a.exec();
}

从“嵌套”class 连接到父级插槽不是个好主意,因为 SmallGUI1 将绑定到 class UI。 我认为这是更好的解决方案:

class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
   QObject::connect(all,QPushButton::clicked,[](){
         SmallGUI1* s=new SmallGUI1;
         connect(s,&USmallGUI1::button_clicked,this,&UI::something);
         s->show();
   });
}

void something(){
   //something
}

和小GUI1 class:

class SmallGUI1 :
    public QWidget
{
public:
    SmallGUI1(){connection();};
signals:
void button_clicked();
private:
     QPushButton* N;
     
     void connection(){
       //to connect N to something()
       N = new QPushButton;
       connect(N,&QPushButton::clicked,this,&SmallGUI1::button_clicked)
     }

这样,您就可以将来自 SmallGUI1 的 QPusButton::clicked 信号连接到信号 SmallGUI1::button_clicked()。不需要实现额外的插槽,只需将信号连接到信号即可。 在 UI 中,您将 button_clicked() 信号连接到插槽 dosomething()

不要忘记 SmallG 的构造函数UI1!在你的代码中,SmallGUI()只是一个方法,在实例化SmallGUI1时不会被调用,你必须自己调用它。