工作原因需要用到VS和Qt,在网上搜索了很久都没找到比较全面的在VS下联合开发Qt的教程。使用QT Creater单独开发能通过转到槽函数/双击插件,进行跳转一个插件的响应函数,但是VS上没有转到槽这一项,就挺烦人的。而且说是用过MFC的人转到Qt挺快的,本渣渣表示并不是啊,看其他博客我还是看的可蒙圈。于是本渣渣决定还是自己一边学,一边把要注意的点记录下来,希望能给和我有一样困惑的小伙伴们提供一些帮助吧。
接着上一篇来讲窗口。这一篇主要是会讲到父子窗口的设计。还是老规矩,通过例子来理解父子窗口。
例子:简易父子窗口设计
步骤1:新建一个Qt Widgets Application项目
步骤2:双击FatherWindow.ui文件打开UI界面,这个例子的UI界面暂时不需要添加什么控件。关闭UI界面,在VS解决方案中选中方案,右键->Qt->Refresh intelliSense进行刷新,在VS解决方案中右键 .ui 文件 -> "编译",会生成对应的 ui_XX.h 头文件。
步骤3:修改.cpp文件和.h文件实现对应窗口功能。
main.cpp
#include "FatherWindow.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FatherWindow w;
w.show();
return a.exec();
}
SubWidget.h
#pragma once
#include <QWidget>
#include <QPushButton>
class Subwidget : public QWidget
{
Q_OBJECT
public:
explicit Subwidget(QWidget* parent = 0);
void sendSlot();
signals:
void mySignal();
public slots:
private:
QPushButton b;
};
FatherWindow.h
#pragma once
#include <QtWidgets/QWidget>
#include <QPushButton>
#include "ui_FatherWindow.h"
#include "SubWidget.h"
class FatherWindow : public QWidget
{
Q_OBJECT
public:
FatherWindow(QWidget *parent = nullptr);
~FatherWindow();
void mySlot();
void changeWindow();
void dealSub();
private:
QPushButton b1;
QPushButton *b2;
QPushButton b3;
Ui::FatherWindowClass ui;
Subwidget w;
};
SubWidget.cpp
#include "SubWidget.h"
Subwidget::Subwidget(QWidget* parent) : QWidget(parent)
{
this->setWindowTitle(QStringLiteral("子窗口"));
b.setParent(this);
b.setText(QStringLiteral("切换到父窗口"));
b.move(50, 50);
connect(&b, &QPushButton::clicked, this, &Subwidget::sendSlot);
resize(300, 400);
}
void Subwidget::sendSlot()
{
emit mySignal();
}
FatherWindow.cpp
#include "FatherWindow.h"
FatherWindow::FatherWindow(QWidget* parent)
: QWidget(parent)
{
setWindowTitle(QStringLiteral("父窗口"));
b1.setParent(this);
b1.setText("close");
b1.move(100, 100);
b2 = new QPushButton(this);
b2->setText("open");
b2->move(100, 0);
connect(&b1, &QPushButton::pressed, this, &FatherWindow::close);
connect(b2, &QPushButton::released, this, &FatherWindow::mySlot);
connect(b2, &QPushButton::released, &b1, &QPushButton::hide);
b3.setParent(this);
b3.setText(QStringLiteral("切换到子窗口"));
b3.move(100, 50);
connect(&b3, &QPushButton::released, this, &FatherWindow::changeWindow);
connect(&w, &Subwidget::mySignal, this, &FatherWindow::dealSub);
resize(300, 400);
}
void FatherWindow::mySlot()
{
b2->setText("123");
}
void FatherWindow::changeWindow()
{
w.show();
this->hide();
}
void FatherWindow::dealSub()
{
w.hide();
this->show();
}
FatherWindow::~FatherWindow()
{}
这里主要用到了setParent函数来实现父子窗口。先简单介绍一下这个函数:
setParent可以用来切换一个QWidget所对应的父窗口,因为Qt中所有的widget都是基于父子关系的,所以如果是布局在一个上面的,那么其子控件的parent应该是上层的QWidget。
setParent有两个接口的,一个是setParent(QWidget *parent),一个是setParent(QWidget* parent, Qt::WindowFlags f),其中如果调用第一个参数的话,parent会重新设置窗口的标志位,如果希望保持原来的窗口标志位,则必须要指定一个参数。举一个简单的例子,如果你原来的窗口的标志位是Qt::Window|Qt::FramelesssWindowHint(一个自由窗体,不带边框),那么你需要将这个参数带到flags中,如果不指定的话,则会将其窗口属性修改为QWidget了(会跟父窗口合并,并且会将窗口的位置移动到(0,0)的位置。
这里再介绍一下emit和move:
emit是不同窗口/类间的触发信号。当对象改变其状态时,信号就由该对象发射 (emit) 出去,通过槽函数实现用户想要的效果。比如我们想要通过子窗口subwindow的按钮,对父窗口fatherwindow进行操作,实现用户想要的效果。首先我们要明白谁是发射端,谁是接收端。
按照上面的例子来说,发射端就是子窗口,接收端是主窗口。
QObject::connect: (sender name: ‘childwindow’)
QObject::connect: (receiver name: ‘MainWindow’)
.move是常见的QT窗口操作函数。如果有父窗口,则是在父窗口的相对坐标位移,如果没有父窗口则是在屏幕坐标系位移。
void move(int x, int y);
其中move的原点是父窗口的左上角,x往右递增,y往下递增。
运行结果
父子窗口
代码我传到GitHub上了(key-cc/QT_EX: This repository is about some exercise code of QT while learning, hope this can help you for QT learning. (github.com)),大家可以自行下载。不方便上GitHub的话,CSDN我也传了一份(QT父子窗口的设计(简易版)资源-CSDN文库)。关于GitHub加速的问题,我在另外一篇博文(Github访问速度慢的解决方案-CSDN博客)里有写到方法,希望对大家有帮助。