QT创建界面二

本篇文章不依赖UI设计界面,而是用继承窗口的办法实现界面的设计,本文重点介绍信号和槽函数的使用。

一:创建工程


这种工程创建的办法相对于上一篇没有出现ui界面那个文件夹:so界面的设计和槽函数的设计和关联都需要手动进行。

二:窗口部件介绍

基础窗口部件QWidget类是所有用户界面对象的基类,窗口和控件都是直接或间接继承自 QWidget。

QWidget的构造函数中有两个参数:QWidget* parent=0 和 Qt::WidowFlags f=0,前面的parent指的是父窗口部件,默认为哦,表明没有父窗口,而后面的f参数是Qt::WindowFlags类型,是Qt::WindowType枚举类型值或者组合。0表示Qt::Widget,默认的类型。

QMainWindow、QWidget、QDialog 三个类就是用来创建窗口的,可以直接使用也可以继承后再使用。

QMainWindow 窗口可以包含菜单栏、工具栏、状态栏、标题栏等,是最常见的窗口形式,可以作为GUI程序的主窗口。如下图所示:



QDialog 是对话框窗口的基类。对话框主要用来执行短期任务,或与用户进行互动,它可以是模态的也可以是非模态的。QDialog 没有菜单栏、工具栏、状态栏等,如下所示:


如果是主窗口,就使用 QMainWindow;如果是对话框,就是用 QDialog;如果不确定,或有可能作为顶级窗口,也有可能嵌入到其他窗口中,那么使用 QWidget。

需要注意的是,窗口和控件都继承自 QWidget,如果不为控件指定父对象,它就会被作为窗口处理,这时 setWindowTitle() 和 setWindowIcon() 函数就会生效。请看下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <QApplication>
#include <QLabel>
#include <QPushButton>
 
int  main( int  argc,  char  *argv[])
{
     QApplication app(argc, argv);
 
     QLabel label( "这是Label控件" );   //没有父对象
     label.setWindowTitle( "Label控件作为顶级窗口" );
     label.setGeometry(100, 50, 360, 160);
     label.setAlignment(Qt::AlignCenter);
     label.show();
 
     QPushButton btn;   //没有父对象
     btn.setWindowTitle( "PushButton控件作为顶级窗口" );
     btn.setText( "这是个大大的按钮" );
     btn.setGeometry(480, 50, 360, 160);
     btn.show();
 
     return  app.exec();
}

运行代码,会在距离显示器 x=100, y=50 的位置弹出两个窗口,如下图所示:


可以发现,窗口和控件没有绝对的区别,控件也可以成为窗口,这取决于它有没有父对象。

三:信号和槽

GUI 程序除了要绘制控件,还要响应系统和用户事件,例如重绘、绘制完成、点击鼠标、敲击键盘等。当事件发生时,UI 会产生相应的变化,让用户直观地看到。
大部分编程(例如Win SDK、Web前端)中使用回调函数来响应事件,而 Qt 却独创了信号和槽机制。所谓回调函数,就是程序员提前定义一个函数,当事件发生时就调用该函数。
信号和槽是Qt的核心,它让两个互不相干的对象连接起来,当一个对象的状态改变时,可以通知另一个对象。

我们先通过例子来演示一下信号和槽:

测试用例如下 ps备注:这里用的是自带的槽函数和响应函数,这些都是自己可以写的。


#include "mainwindow.h"
#include <QApplication>
#include <QMainWindow>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QMainWindow w;
    w.setWindowTitle("微浪游戏");
    w.resize(325, 120);

    QLineEdit lineEdit(&w);
    lineEdit.setGeometry(30, 20, 180, 36);
    lineEdit.setPlaceholderText("请输入文本");

    QPushButton btn("取消", &w);
    btn.setGeometry(220, 20, 70, 36);

    QLabel label(&w);
    label.setGeometry(30, 70, 250, 30);

    //连接clicke()信号和quit()槽
    QObject::connect(&btn, SIGNAL(clicked()), &app, SLOT(quit()));
    //连接textChanged()信号和setText()槽
    QObject::connect(&lineEdit, SIGNAL(textChanged(QString)), &label, SLOT(setText(QString)));

    w.show();
    return app.exec();
}

点击“取消”按钮,程序就关闭了,这是第26行代码的作用;在文本输入框中输入一段文本,下面的 Label 会随时显示出来,这是第28行代码的作用。

这两个对象都是通过信号和槽连接起来的,信号和槽用于两个对象之间的通信。信号和槽是QT的核心特征,当一个特殊的事情发生时便可以发射一个信号,比如demo中的取消按钮被点击时,就会发射clicked()信号;而槽就是一个函数,它在信号发射后被调用来响应这个信号,Qt的部件类中已经定义了一些信号和槽,但是更常用的做法是子类化部件,然后添加自定义的信号和槽来实现想要的功能。

信号是只有函数声明、没有函数体的成员函数。槽是拥有完整函数体的普通成员函数,你可以在槽函数中实现各种功能,与普通函数相比并没有区别,例如 quit() 的作用就是退出程序。

connect() 是 QObject 类的静态成员函数;QObject 是 Qt 中所有类的基类,它就像“树根”,从这里派生出了所有其他“树枝”。
需要注意的是,信号不是事件。当用户点击“取消”按钮时,Qt 会捕获该点击事件,进行预处理,然后发射 clicked() 信号; clicked() 和 quit() 关联起来了,接下来就会调用 quit() 函数。
信号和槽机制归根结底也是回调函数,只不过绕了个圈子。在这种机制下,程序员有两次处理事件的机会,一是在捕获事件后发射信号前进行预处理(事件不符合预期可以不发射信号),二是在槽函数中进行主要处理。
再来看第27行。textChange() 信号会在文本改变时发出,setText() 槽用来设置 Label 的文本,QString 是要传递的数据的类型。当用户输入文本时,lineEdit 会发出 textChange() 信号,该信号将携带数据,数据类型为 QString,数据内容为输入的文本;setText() 槽接收到信号后先解析信号携带的数据,获取用户输入的文本,然后填充到 Label 中。





























猜你喜欢

转载自blog.csdn.net/runner668/article/details/80510760
今日推荐