设计两个窗口,每个窗口中都包含一个按钮,最开始的时候只显示窗口1,当按下窗口1中的按钮时,窗口1隐藏(hide),同时窗口2显示(show),当按下窗口2中的按钮时,窗口2隐藏,窗口1显示。
这个案例最关键的是,如何让两个窗口建立连接(connect),最开始学QT的时候,我们都是在Widget的构造函数中调用connect函数,但这里不能直接这样做,因为创建的时候,你拿不到另一个Widget对象,如果通过构造函数的参数传进来,则传进来的那个Widget该如何构建?解决这个问题可以使用两种方法:
1 重载构造函数,例如w1通过无参构造函数创建,w2通过有参,w2在创建的时候将w1传进去,然后在有参构造函数中建立联系(connect)
2 新建一个类A,这个类A必须直接或间接继承QObject,这样才能获得connect函数(因为connect是QObject的成员函数),然后将w1和w2都作为A的成员变量,并在A的构造函数中实现两个窗口的连接
需要注意的一点是,信号的发送者是QPushButton指针,而不是窗口对象,并且,为了建立两个窗口的联系,最好将QPushButton指针作为Widget类的成员变量,这样通过窗口就能拿到信号发送者,详见下面的代码。
widget.h内容如下:
#ifndef WIDGET_H
#define WIDGET_H#include
#include "QPushButton"class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();Widget(const Widget& w2, QWidget *parent = nullptr);public:QPushButton * btn;
};
#endif // WIDGET_H
widget.cpp内容如下,为什么用lambda表达式不行,我想了很久都不知道,最后没有使用lambda表达式,不过后面我找到原因了,就是const,具体问题可以看注释:
#include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent)
{btn = new QPushButton("button", this);btn->move(300, 300);
}Widget::~Widget()
{
}Widget::Widget(const Widget& another_w, QWidget *parent) : QWidget(parent)
{this->btn = new QPushButton("button", this);this->btn->move(300, 300);/* //下面的代码为何会报错?connect(this->btn, &QPushButton::clicked, [=](){this->hide();another_w.show();});//another_w在lambda函数中是常对象,不能调用非常成员函数,this是常指针,因此可以调用hide//1 能不能添加mutable选项(即[=]()mutable),让another_w可以在函数内部调用show?// 不能,因为another_w是通过构造函数传入,它已经被声明为了const,这里用mutable会冲突//2 能不能在调用connect之前,对another_w先进行取址操作,然后在lambda函数内部通过指针调用show,像this一样?// 不能,因为another_w在传入时就已经被声明为了const,无法进行取址操作,除非修改函数声明和定义,去掉const*/connect(this->btn, &QPushButton::clicked, this, &QPushButton::hide);connect(this->btn, &QPushButton::clicked, &another_w, &QPushButton::show);connect(another_w.btn, &QPushButton::clicked, &another_w, &QPushButton::hide);connect(another_w.btn, &QPushButton::clicked, this, &QWidget::show);
}
main.cpp内容如下:
#include "widget.h"#include int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w1;Widget w2(w1);w1.setGeometry(100, 100, 600, 600);w1.setWindowTitle("窗口1");w2.setGeometry(1000, 100, 600, 600);w2.setWindowTitle("窗口2");w1.show();return a.exec();
}
widget.h内容:
#ifndef WIDGET_H
#define WIDGET_H#include
#include "QPushButton"class widget : public QWidget
{Q_OBJECT
public:explicit widget(QWidget *parent = nullptr);public:QPushButton* btn;
signals:};#endif // WIDGET_H
widget.cpp内容
#include "widget.h"widget::widget(QWidget *parent) : QWidget(parent)
{btn = new QPushButton("button", this);btn->move(300, 300);
}
mainwindow.h 内容如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include
#include "widget.h"
class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();public:widget w1, w2;
};
#endif // MAINWINDOW_H
mainwindow.cpp内容如下:
#include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{connect(w1.btn, &QPushButton::clicked, [=](){ //如果写成 [w1, w2]企图捕获类的成员变量w1和w2,会报错//mainwindow.cpp:6:45: error: 'w2' in capture list does not name a variablethis->w1.hide();this->w2.show();});connect(w2.btn, &QPushButton::clicked, [this](){ //将this指针写到捕获参数列表时,函数内部可以直接使用成员函数和成员变量w2.hide(); //使用w2和w1,无需通过this指针w1.show();});w1.setGeometry(100, 100, 600, 600);w1.setWindowTitle("窗口1");w2.setGeometry(1000, 100, 600, 600);w2.setWindowTitle("窗口2");
}MainWindow::~MainWindow()
{
}
main.cpp内容如下:
#include "mainwindow.h"#include int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow mw;mw.w1.show();return a.exec();
}