Qt学习01-基础

前言

由于相关的工作和学习需要使用到Qt,因此,接下来的一段时间就对Qt进行学习并做记录。

基础

首先,对于Qt是什么、干嘛的,就不赘述了,也没什么意思。
在从官网上下载了Qt之后,我们直接在本地得到了Qt Creater这个专门用来开发Qt相关程序的IDE。
不过现在VS也是支持Qt,之后我们也需要转到VS上来使用Qt。

HelloWorld

对于Qt,它的Hello World,就是输出一个标题为Hello World的窗口罢了。

首先,打开Qt后,新建项目,然后选择一个空的qmake project,就可以进行代码的尝试和学习了。

打开后,会有一个.pro的文件。
此时,右键新建一个文件,选择.cpp,可以将其命名为main,来作为我们的主函数。
main.cpp中,代码如下:

//学习HelloWork与按钮机制

//应用程序抽象类
#include <QApplication>
//窗口类
#include <QWidget>
//按钮类
#include <QPushButton>

int main(int argc, char* argv[])
{
    QApplication app(argc,argv);//构建了一个应用程序

    QWidget w;//w是一个窗口对象
    
    //注意,按钮也是一个窗口
    //如果我们不去构建父子关系,那么按钮和上面的窗口会独立的显示
    //控件,都是窗口
    QPushButton button;
    button.setText("button!");
    //窗口对象的父子关系,会影响显示的位置
    //没有父亲窗口的窗口,称之为主窗口
    button.setParent(&w);   //这里,构建了一个对象的父子关系

    //当button被点击时,窗口就被关闭了
    //此为Qt对C++的拓展
    //前两个参数称为信号
    //后两个参数称为槽
    //调用信号函数时,会导致槽函数被调用
    //用第三方的方式,将两个模块联系起来
    QObject::connect(&button, SIGNAL(clicked()), &w, SLOT(close()));

    w.setWindowTitle("hello");
    //显示窗口
    w.show();

    return app.exec();  //其中是一个死循环——消息循环
}

但是,当我们添加过上面所写的头文件:

//应用程序抽象类
#include <QApplication>
//窗口类
#include <QWidget>
//按钮类
#include <QPushButton>>

此时是会报错的,我们需要打开.pro文件,此时在其中已经有了:

SOURCES += \
    main.cpp

我们只需要添加一段代码,完整版如下:

SOURCES += \
    main.cpp

QT += widgets gui

这样,代码就能顺利通过编译了。

在上面的例子中,需要注意的是:

  • 头文件不要写错了。
  • .pro文件内的代码一定要进行添加,否则头文件会报错。
  • 所有的控件都是一种窗体。
  • 对象的父子关系,需要搞清楚。如果不声明这种父子关系,就会让每个窗体都成为主窗口。
  • 信号和槽机制是Qt的一大特点,也是对C++的一个拓展。
  • w.show()语句一定要在没有什么要改变和声明时,再写。
  • app.exec()是一种消息循环,即一种死循环;其功能有点像C++中的system("pause");

EditLine

在此之后, 对Qt中的输入窗体学习一下。
首先,在.pro文件内的代码是不变的。
一样的,创建一个main.cpp,其中,代码如下:

//学习输入窗体

//应用程序抽象类
#include <QApplication>
//窗口类
#include <QWidget>

#include <QLineEdit>

#include <QCompleter>

int main(int argc, char* argv[])
{
    QApplication app(argc,argv);//构建了一个应用程序

    QWidget w;//w是一个窗口对象


    QLineEdit edit;
    edit.show();
    edit.setParent(&w);

    //输入密码
    //edit.setEchoMode(QLineEdit::Password);
    //edit.setPlaceholderText("please input text"); //在输入框中显示信息

    //自动补全
    QCompleter completer(QStringList()<<"lan"<<"apple"<<"bri");
    //设置匹配规则,如果不设置,默认以开头做匹配;这里设置的是以包含做匹配
    completer.setFilterMode(Qt::MatchContains); 
    edit.setCompleter(&completer);    //提示并自动补全

    w.setWindowTitle("hello");
    //显示窗口
    w.show();

    return app.exec();  //其中是一个死循环——消息循环
}

在上面的例子中,需要注意的是:

  • 需要添加的新的头文件为#include <QLineEdit>#include <QCompleter>
  • 当我们想要输入密码时,即输入的是黑色的、不可见的点,实现的语句为edit.setEchoMode(QLineEdit::Password);其中,Password为一个关键字,可以换成别的关键字以实现不同的密码键入类型。
  • 实现自动补全时,不能在密码模式里。(废话
  • 上面的completer也是一个对象,其中,在构造函数时,定义了它用于自动联想的一种字符串表。
  • completer.setFilterMode(Qt::MatchContains);中,MatchContains也是一种匹配关键字。
  • 仔细想想,就是常见一个对应类型的对象,然后在调用它们各自对应类型内的函数与方法而已。很像Unity3D的模式。

Cood

接着,对Qt中的坐标系统进行一些学习:

//学习相关的坐标系统

//应用程序抽象类
#include <QApplication>
//窗口类
#include <QWidget>
//按钮类
#include <QPushButton>

int main(int argc, char* argv[])
{
    QApplication app(argc,argv);//构建了一个应用程序

    QWidget w;//w是一个窗口对象

    QPushButton button;
    button.setText("button!");
    //窗口对象的父子关系,会影响显示的位置
    //没有父亲窗口的窗口,称之为主窗口
    button.setParent(&w);   //这里,构建了一个对象的父子关系

    //设置button的坐标与大小
    //其中,坐标体系的值是基于父对象的坐标体系的值
    button.setGeometry(30,30,100,30);


    QObject::connect(&button, SIGNAL(clicked()), &w, SLOT(close()));

    w.setWindowTitle("hello");
    w.show();

    return app.exec();  //其中是一个死循环——消息循环
}

值得注意的是:

  • 坐标系统不需要单独的头文件,是包含在窗体的一个setGeometry()方法。
  • 在这个setGeometry()方法中,有四个参数:前两个参数是对应的窗体的坐标;后两个参数则是窗体对应得大小。单位为像素
  • 坐标体系的值是基于父对象的坐标体系的值。

Layout

如果我们每次都使用setGeometry()方法来设置窗体的位置,未免太过于麻烦。因此,在Qt中,还有一个Layout可供使用:

//学习Layout
//应用程序抽象类
#include <QApplication>
//窗口类
#include <QWidget>
//按钮类
#include <QPushButton>
//标签类
#include <QLabel>

//以竖直的方式进行排列的layout
#include <QVBoxLayout>
//以水平的方式进行排列的layout
#include <QHBoxLayout>
//带有网格的layout
#include <QGridLayout>

#include <QLineEdit>
int main(int argc, char* argv[])
{
    QApplication app(argc,argv);//构建了一个应用程序

    QWidget w;//w是一个窗口对象

    QPushButton button;
    button.setText("button!");
    //button.setParent(&w);

    QLineEdit edit;
    //edit.setParent(&w);

    //同时,我们也可以将button和edit对于w的父子关系的声明给取消
    //因为两个子窗口包含在了layout中,而layout又在w中

    //但是,需要注意的时,layout本身不是一个窗口
    //layout继承自QObject

#if 0   //表示将代码注释
    //QVBoxLayout layout;
    QHBoxLayout layout;
    //添加了一根弹簧
    //这样,当我们拖动窗口时,子窗口部件就不会随着窗口变化而变化了
    layout.addStretch(1);
    layout.addWidget(&edit,1);
    layout.addSpacing(50);  //在两个窗体中间添加一点距离
    layout.addWidget(&button,1);
    layout.addStretch(1);
    //当我们左右都添加了弹簧后,子窗体自然就被挤到中间了

    //同时,在addWidget中,我们也可以设置第二个参数
    //第二个参数也是stretch,表示当前窗体所占比例
    //如面所示,此时,相当于一种四分天下
#endif

#if 0
    //带有网格的layout
    //其中,参数表示第几行、第几列
    QGridLayout layout;
    layout.addWidget(&button,0,0);
    layout.addWidget(&edit,0,1);
    layout.addWidget(new QPushButton("aaa"),1,0 );
    layout.addWidget(new QPushButton("bbb"),1,1);

    //后面两个参数,表示按钮所占的大小
    //即,占有一行两列
    layout.addWidget(new QPushButton("ccc"),2,0,1,2);

    //设置行和列的弹簧,将四个子窗口挤到左上角
    layout.setColumnStretch(2,1);//设置第2列的弹簧,弹簧的比重是1
    layout.setRowStretch(3,1);   //设置第3行的弹簧,弹簧的比重是1

    //需要注意的是
    //因为带有网格的layout是有坐标的,
    //因此,我们就不需要像前面所说的两类layout那样,必须注意先后顺序
#endif

    QGridLayout layout;
    QLineEdit *password;
    layout.setColumnStretch(3,1);
    layout.setRowStretch(4,1);
    layout.setColumnStretch(0,1);
    layout.setRowStretch(0,1);

    layout.addWidget(new QLabel("Username "),1,1);
    layout.addWidget(new QLineEdit(),1,2);
    layout.addWidget(new QLabel("Password "),2,1);
    layout.addWidget(password = new QLineEdit(),2,2);
    password->setEchoMode(QLineEdit::Password);
	
	//用layout的方法书写一个登陆界面
	//layout可以被嵌套
    QHBoxLayout *hBox;
    //在一个layout中添加另一个layout,以实现单独的操作
    layout.addLayout(hBox = new QHBoxLayout,3,2);   
    hBox->addStretch(1);
    hBox->addWidget(new QPushButton("Login"));



    w.setWindowTitle("hello");
    w.show();
    w.setLayout(&layout);

    //此时,层次关系如下:
    //窗口之中有一个layout
    //layout中有两个子窗口
    //在layout中的窗口,都会自动的根据layout中的规则来进行排列
    QObject::connect(&button, SIGNAL(clicked()), &w, SLOT(close()));

    return app.exec();
}

Layout中的点比较多,值得注意的如下:

  • Layout需要头文件。不同形式的Layout所需要的头文件也各不相同。具体可以见上述的代码。
  • #if 0endif是一种注释方法。
  • Layout是可以被嵌套的。形式见上面的代码。
  • Layout其实就是相当于一种已经内嵌好的排列办法,当声明使用了这样的Layout之后,系统会自动的帮助你进行排列。
  • 实现的层次关系:窗口之中包含了一个layout,而layout之下又嵌套了一个layout和两个窗口。因此,子窗口对于父窗口的声明关系可以不写,因为已经包含在了layout之中。
  • 不过,layout本身并不是一个窗口,它继承自QObject
  • 上述代码实现的结果图:
  • 在这里插入图片描述
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值