qt三个窗口基本类

qt是一个gui框架,做图形用户界面的,本地可以跑,跟一些web框架那种做好点击网址跳转的不一样,python的web常用的flask和django,python也有gui框架比如pytqt和tkinter,这个专栏讲qt5,用c++写gui

qt三个窗口基本类

在创建项目的时候就是下面这三个

qt三个窗口基本类_第1张图片

他们的关系如下:
qt三个窗口基本类_第2张图片

  • 常用的窗口类有 3 个

    • 在创建 Qt 窗口的时候,需要让自己的窗口类继承上述三个窗口类的其中一个
  • QWidget
    
    • 所有窗口类的基类
    • Qt 中的控件 (按钮,输入框,单选框…) 也属于窗口,基类都是 QWidget
    • 可以内嵌到其他窗口中:没有边框
    • 可以不内嵌单独显示:独立的窗口,有边框
  • QDialog
    
    • 对话框类,有模态和非模态两种显示
    • 不能内嵌到其他窗口中
  • QMainWindow
    
    • 有工具栏,状态栏,菜单栏
    • 不能内嵌到其他窗口中

4.2 窗口的显示

  • 内嵌窗口
    • 依附于某一个大的窗口,作为了大窗口的一部分
    • 大窗口就是这个内嵌窗口的父窗口
    • 父窗口显示的时候, 内嵌的窗口也就被显示出来了
  • 不内嵌窗口
    • 这类窗口有边框,有标题栏
    • 需要调用函数才可以显示
c++
// QWidget是所有窗口类的基类, 调用这个提供的 show() 方法就可以显示将任何窗口显示出来
// 非模态显示
void QWidget::show();	// 显示当前窗口和它的子窗口

// 对话框窗口的非模态显示: 还是调用show() 方法
// 对话框窗口的模态显示
[virtual slot] int QDialog::exec();

给出示例代码:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } //ui 界面的mainwindow类
QT_END_NAMESPACE

class MainWindow : public QMainWindow//QMainWindow Qt的基本窗口类
{
    Q_OBJECT// 这个宏是为了能够使用Qt中的信号槽机制

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;// 定义指针指向窗口的 UI 对象
};
#endif // MAINWINDOW_H

testwidget.h

#ifndef TESTWIDGET_H
#define TESTWIDGET_H

#include 

namespace Ui {
class TestWidget;
}

class TestWidget : public QWidget
{
    Q_OBJECT

public:
    explicit TestWidget(QWidget *parent = nullptr);
    ~TestWidget();

private:
    Ui::TestWidget *ui;
};

#endif // TESTWIDGET_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "testwidget.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //窗口ui 被实例化了,ui界面也是个类其实
{
    ui->setupUi(this);//把cpp的mainwindow类和ui的绑定在一起

    //一般在qt的构造函数中进程初始化操作
    //显示当前窗口的时候,显示另一个窗口,TestWidget
    //我们就在MainWindow的构造函数里面构造TestWidget对象,main只调用MainWindow就行
    //创建窗口对象,没有给w对象指定父对象
    TestWidget* w=new TestWidget;
    w->show(); //显示窗口
}

MainWindow::~MainWindow()
{
    delete ui;
}

testwidget.cpp

#include "testwidget.h"
#include "ui_testwidget.h"

TestWidget::TestWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TestWidget)
{
    ui->setupUi(this);
}

TestWidget::~TestWidget()
{
    delete ui;
}

入口函数:main

#include "mainwindow.h"

#include //应用程序类,后台维护了一个事件循环

int main(int argc, char *argv[])
{
    QApplication a(argc, argv); //创建了一个应用程序的对象,只有一个
    MainWindow w;   //创建了一个窗口对象
    w.show();        //显示窗口
    return a.exec();   //阻塞函数,程序进入了事件循环
}

Qdwidget类

我们去创建一个ui界面类
qt三个窗口基本类_第3张图片

进去选择模板,我选择了一个基类空模板widget类,进去之后自动跳到ui界面,我们就可以拖动控件去定制自己想要的样子
qt三个窗口基本类_第4张图片
qt三个窗口基本类_第5张图片

这么写会发现就是两个窗口

改一下MainWindow构造函数如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //窗口ui 被实例化了,ui界面也是个类其实
{
    ui->setupUi(this);//把cpp的mainwindow类和ui的绑定在一起

    //一般在qt的构造函数中进程初始化操作
    //显示当前窗口的时候,显示另一个窗口,TestWidget
    //我们就在MainWindow的构造函数里面构造TestWidget对象,main只调用MainWindow就行
    //创建窗口对象,没有给w对象指定父对象,他就是独立窗口
    //想要显示他,就得show一下
#if 0
    TestWidget* w=new TestWidget;
    w->show();
#else   //指定父对象,他就不是单独的窗口了
        //这样的话当前父窗口显示的时候,子窗口就一并显示出来
        //这时候子窗口是没有边框的
        //只有独立窗口是有边框的
    TestWidget* w=new TestWidget(this);

#endif
}

会发现只有一个窗口,且窗口内嵌

qt三个窗口基本类_第6张图片

这样一会有边框一会没有,因为我们这个继承的是QWidget类,上面有讲他特性

我们在加个Qdialog类,看看效果

注意:qt里面这些类都是继承关系,你看传this,传的其实是父对象,也就是基类指针指向子类,达到多态的那种感觉

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //窗口ui 被实例化了,ui界面也是个类其实
{
    ui->setupUi(this);//把cpp的mainwindow类和ui的绑定在一起

    //一般在qt的构造函数中进程初始化操作
    //显示当前窗口的时候,显示另一个窗口,TestWidget
    //我们就在MainWindow的构造函数里面构造TestWidget对象,main只调用MainWindow就行
    //创建窗口对象,没有给w对象指定父对象
#if 0
    TestWidget* w=new TestWidget;
    w->show();
#else
    TestWidget* w=new TestWidget(this);
#endif
    
    TestDialog* dlg=new TestDialog(this);//对于他写不写父对象无所谓的,这个this
    //非模态
    dlg->show();
}

qt三个窗口基本类_第7张图片

注意非模态,对于多个子窗口是可以来回切换的

把TestWidget那块if取开,让他走上面那两句代码,因为那两句没有传父类widget对象,这样TestWidget窗口的就不会去嵌入主窗口,你在运行就会有三个窗口且来回鼠标可以去切换,点的动的!

而模态是什么呢?就是子窗口之间不能切换了

对于Dialog的模态模式,需要调用exec这个阻塞函数,跑下面代码,会发现没有主窗口,两个子窗口没法鼠标去切换,这就是模态。那是因为有exec这个函数存在,阻塞在那,dialog这个窗口不退出,相当于主窗口mainwindows没有构造成功,当你把dialog这个窗口关了,主窗口就出来了

这个模态也就dialog能调了,对了还有构造dialog的时候,那个this父类对象传不传都是可以的,对于mainwindowsnew构造的时候来说也是传不传this都一样,毕竟都是从widget继承来的,就widget传和不传才有什么独立和嵌套之分。我上面也有说他们区别

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //窗口ui 被实例化了,ui界面也是个类其实
{
    ui->setupUi(this);//把cpp的mainwindow类和ui的绑定在一起

    //一般在qt的构造函数中进程初始化操作
    //显示当前窗口的时候,显示另一个窗口,TestWidget
    //我们就在MainWindow的构造函数里面构造TestWidget对象,main只调用MainWindow就行
    //创建窗口对象,没有给w对象指定父对象
#if 1
    TestWidget* w=new TestWidget;
    w->show();
#else
    TestWidget* w=new TestWidget(this);
#endif

    TestDialog* dlg=new TestDialog(this);//对于他写不写父对象无所谓的,这个this
    //模态 ,得调一个函数exec(),阻塞程序执行
    dlg->exec();
     //写exec了show自动帮你调了一次show显示
}

qt三个窗口基本类_第8张图片

QMainWinow类

我们创建项目一开始的类,就是继承QMainWinow这个类,算是你的主窗口,菜单栏的这种,去对应的ui界面也能去拖动按钮,控件

qt三个窗口基本类_第9张图片

Qt的坐标

坐标原点在左上角,从左上角向下向右递增

每个窗口都有一个坐标原点,但是点的位置都是基于父窗口的原点去移动构建的

比如父亲是(0,0),,有个儿子是(5,5),这个5,5是相对于父亲0,0的

儿子还有个儿子(10,10),这个(10,10)是相对于(5,5)来说的,相当于说是按照爷爷(0,0)偏移的(15,,15)这个位置

所以注意窗口嵌套的坐标位置都是基于父窗口的坐标系来算的

我们给主窗口构造函数加点控件看看:

#include "mainwindow.h"
#include 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow) //窗口ui 被实例化了,ui界面也是个类其实
{
    ui->setupUi(this);//把cpp的mainwindow类和ui的绑定在一起
    //创建一个按钮,作为当前窗口的子控件
    QPushButton *ba=new QPushButton(this);//内嵌进去
    //通过move去移动控件位置
    ba->move(10,10);  //x y
    //设置大小
    ba->setFixedSize(200,200);//宽度,高度

    QPushButton *ba1=new QPushButton(ba);//注意这里
    //通过move去移动控件位置
    ba1->move(10,10);  //相对于ba的位置
    //设置大小
    ba1->setFixedSize(100,100);
}

qt三个窗口基本类_第10张图片

Qt自带内存回收

因为qt总是来回继承的,很多类都是qobject这个类的子类或者间接子类,qt后台继承会构建一颗继承树,,父类要析构就得先去析构子类,这下就明白吧。。不过这种内存回收前提就是这个类得继承在qobject这个对象树下

综上所述,我们可以得到一个结论: Qt中有内存回收机制, 但是不是所有被new出的对象被自动回收, 满足条件才可以回收 , 如果想要在 Qt 中实现内存的自动回收,需要满足以下两个条件:

  1. 创建的对象必须是 QObject 类的子类 (间接子类也可以)

QObject 类是没有父类的,Qt 中有很大一部分类都是从这个类派生出去的

Qt 中使用频率很高的窗口类和控件都是 QObject 的直接或间接的子类
其他的类可以自己查阅 Qt 帮助文档
2.创建出的类对象,必须要指定其父对象是谁,一般情况下有两种操作方式:

// 方式1: 通过构造函数
// parent: 当前窗口的父对象, 找构造函数中的 parent 参数即可 .h
QWidget::QWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
QTimer::QTimer(QObject *parent = nullptr);

// 方式2: 通过setParent()方法
// 假设这个控件没有在构造的时候指定符对象, 可以调用QWidget的api指定父窗口对象
void QWidget::setParent(QWidget *parent);
void QObject::setParent(QObject *parent);

你可能感兴趣的:(Qt,qt,ui,开发语言)