Qt——入门
目录
安装
Qt项目
解释
hello world
qt坐标体系
安装
配置Qt环境需要安装三部分:C++编译器如g++,cl.exe等;Qt开发工具包SDK;最后一个Qt的集成开发环境比如Qt提供的Creater,Visual Studio等;但只需要安装Qt官网的SDK,上面的三部分就都包含在里面了;由于国外下载慢,推荐使用镜像源进行下载:/qt/archive/qt/
Qt项目
点击左上角的文件:打开文件
使用Qt写GUI(图形用户界面)程序就默认选择的是第一个,这种传统用来开发GUI的方式叫做 Qt Widgets;选择第二个则是用来开发TUI(终端用户界面)
接下来给上qt项目创建的路径与名字
Qt框架在编译时,会自动调用一系列工具,根据你写的C++代码形成其它的C++代码,再对这些代码进行编译;这时就需要我们选择工具协助Qt编译,也就是下面构建系统的三个工具选择一个:一般选择qmake,多人用且稳定
最后需要选择创建Qt项目时自动生成的类的父类是谁? QMainWinodw类是一个完整程序窗口,比如菜单栏,工具栏等;QWidget类是窗口上的一个控件,比如输入框,按钮,下拉框等;QDialog类是一个对话框;刚开始学选择QWidget,它比较简单
关于form file:Qt中创建图形化界面的方式有两种:一种是使用C++代码直接创建;另一种则是通过Form file:通过 Qt Create对 widget.ui 文件进行编辑就能以图形化的方式方便快捷生成图形界面
设置Qt界面的语言,刚开始不用设置默认为none
工具选择SDK内置的minCV编译器
如果需要使用git就在第二个选择那选择git(前提是你安装了git)
点击完成后就可以看到默认为我们生成的C++代码文件
解释
//main.cc
#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
- 编译一个Qt的图形化界面一定要有这个 a 对象来完成
- Widget 是在前面选择 Qwidget 的子类
- 使用 Widget 创建一个控件对象w,调用 show() 表示让控件给显示出来(父类提供的方法)
- a调用 exec() 意味着把图形化界面构建出来让用户看到
//widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;
};
#endif // WIDGET_H
- Wideget类在这里面的声明,可以看到确实是 QWidget 的子类
- Q_OBJECT 是一个宏,展开会生成一大推的代码,与后面的信号和槽有关联;
- Widget创建对象的参数 parent与对象树有关联:创建的parent对象可以把它挂到对象树上,挂到对象树则是需要指定的父节点才能完成;对象树本质上是树,是多叉树,有什么用也是在后面才理解
- 成员指针ui则与前面选择的Form file的 ui文件有关联
//Widget.cpp#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}
- 保护的第二个头文件是 widget,ui 被 qmake生成的头文件
- ui -> setipUi(this):把form file生成的界面与Widget给关联起来
//widget.ui<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>Widget</class><widget class="QWidget" name="Widget"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>600</height></rect></property><property name="windowTitle"><string>Widget</string></property></widget><resources/><connections/>
</ui>
- 双击点击 widget.ui 文件会进入设计模式,里面有各种控件与属性值给我们选择
- ui文件使用xml格式写出来的,与html类似;只是标签含义有设计者设计,使用不关心
- widget.ui 是去描述程序的界面是什么样的;通过 qmake 去调用一系列工具把 widget.ui 文件生成 C++ 代码:也就是生成 ui_widget.h 文件,在 Ui::Widget *ui 对象就是通过它里面的 Ui_Widget 对象构建出来的
hello world
编写 hello world 有很多种方法:
- 双击 Widget.ui 文件进入设计模式,使用控件 Label 来实现
保存后点击运行程序
- 代码:创建 QLabel 的标签对象,调用 settext() 函数实现
//widget.cppWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//QLabel lab;//推荐new一个QLabel对象QLabel* lab = new QLabel(this);lab->setText("hello world");
}
这里要我们传入QString类对象,其实就是C++的string只是Qt自己封装出来的:因为C++的STL库出现的晚,没有统一标准加上当前的字符串不太好用就自己封装了一套出来
在上面的代码中再堆上申请了一个 QLabel对象怎么没有手动释放掉呢?
new一个对象传入this指针(转成QWidget类型的指针),就把new 出来的对象的生命周期交给对象树:也就是把它挂到对象树上,让对象树在界面关闭时统一释放申请的对象资源,所以不需要我们手动释放
采用在栈上开辟QLabel对象,会出现什么现象呢?
现象是什么也没有创建:在展示界面之前除了Wiget的构造就把la对象给销毁了
怎么能够见一见对象树确实是在界面关闭时自动释放了?
创建一个MyLabel类来继承 QLabel(构造函数进行初始化QLabel后,才能让MyLabel对象挂接到对象树中)通过析构函数里面输出一些消息进行测试
//mylabel.h
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>class MyLabel : public QLabel
{
public:MyLabel(QWidget* parent);~MyLabel();};#endif // MYLABEL_H//mylabel.cpp
#include "mylabel.h"
#include <iostream>MyLabel::MyLabel(QWidget* parent):QLabel(parent){}
MyLabel::~MyLabel()
{std::cout<<"MyLable 销毁"<<std::endl;
}//Widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);MyLabel* label = new MyLabel(this);label->setText("hello worold");
}
出现汉字乱码信息就说明编码方式不统一导致的,中文主要的编码方式有两种:GDK 和 UTF8格式;代码中用到的格式根据是当前文件的编码格式确定的,通常是UTF8格式;也就是说终端是按照GDK编码格式进行处理;主流是选择UTF8格式,但终端要去修改麻烦(没找到),所有通过使用 qDebug()(这个宏中封装了QDebug类对象)来进行日志的打印,此外选择它还有另一个原因:它可以一键式关闭日志信息,这样当开发的代码上线是可以把调试日志统一进行关闭
//mylabel.cpp
#include "mylabel.h"
#include <QtDebug>
MyLabel::MyLabel(QWidget* parent):QLabel(parent){}
MyLabel::~MyLabel()
{qDebug()<<"MyLable 销毁";//std::cout<<"MyLable 销毁"<<std::endl;
}
- 使用控件 Line Edit 实现
- 代码:创建 QLineEdit 对象,调用 SetText() 实现
//Wideget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QLineEdit* line = new QLineEdit(this);line->setText("hello world");
}
- 使用按钮控件:Push Button 实现
按钮可以进行点击,但没有什么变化;所有要使用代码把这个点击操作使用对应的函数来实现点击之后的效果
//Widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//将点击的信号新增一种槽(函数)进行处理connect(ui->pushButton,&QPushButton::clicked,this,&Widget::ClickHandler);// 哪个信号 发送什么信号 谁处理 怎么处理}Widget::~Widget()
{delete ui;
}
//处理实现
void Widget::ClickHandler()
{if(ui->pushButton->text() == "hello world")ui->pushButton->setText("hello qt");elseui->pushButton->setText("hello world");
}
pushButton的变量名就是这个push botton 标签
- 代码:创建 QPushButton 对象来实现(要把对象先声明在Widget的成员变量中,这是为了在处理函数时能够使用)
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);button = new QPushButton(this);button->setText("hello world");connect(button,&QPushButton::clicked,this,&Widget::ClickHandlerCode);
}void Widget::ClickHandlerCode()
{if(button->text() == "hello world")button->setText("hello qt");elsebutton->setText("hello world");
}
纯代码创建的方式与图形化界面的方式的代码看起来差不多,只不过图形化界面的控件对象包含在ui成员中就不需要自己来创建;在实际开发的界面是静态的,使用图形化界面的方式更好些,因为不用频繁去修改;而开发动态界面则推荐纯代码的方式,方便修改
qt坐标体系
为了对某个控件如按钮进行移动,在qt中规定了这样一种坐标体系
某个控件如QPushButton 按照它的父对象QWidget 的左上角作为参照点(0,0),使用坐标(x,y)进行移动,QWidget的父节点为NULL,它就以整个电脑屏幕作为参照物(数学上使用的坐标是右手系坐标,而计算机表示则用左手系坐标)
使用代码则是调用 move() 函数传入坐标参数进行控件的移动,单位是像素(屏幕就是以一个一个的像素点构成的)
//Widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);button = new QPushButton(this);button->setText("按钮");button->move(200,300);connect(button,&QPushButton::clicked,this,&Widget::ClickHandlerCode);}
以上便是全部内容,有问题欢迎在评论区指正,感谢观看!