QT-窗口组件(QWidget),QT坐标系统,初探消息处理(信号与槽)

本章主要内容如下:

  • 1) 窗口组件(QWidget)
  • 2) QT坐标系统
  • 3) 消息处理(信号与槽)

窗口组件(QWidget)

介绍

  • Qt以组件对象的方式构建图形用户界面
  • Qt中没有父组件的顶级组件,则被叫做窗口
  • 组件的类型分为:
  • 容器类(父组件) : 用于包含功能的界面组件
  • 功能类(子组件) : 用于实现特定的交互功能

组件继承

Qt中所有窗口组件继承于QWidget类,而QWidget类继承于QObject类QPaintDevice类.

QWidget组件介绍

  • QWidget能够绘制自己(因为继承了QPaintDevice类),也能够处理用户的输入,比如点击按钮
  • QWidget是Qt窗口组件类的父类
  • Qt中每个窗口组件都可以当做一个QWidget (因为子类可以初始化父类)
  • QWidget类对象常作为父组件顶级组件使用

初探QWidget

1)新建工程,选择Qt Gui应用,设置类信息:

 本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

2)生成QWidget模板

运行模板:

 

可以看到生成了一个窗口,然后我们来看看模板代码,是如何生成的.

3)模板代码如下所示

#include <QtGui/QApplication>

#include "widget.h"

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    QWidget w;                 //创建QWidget类对象

    w.show();                  //显示QWidget类对象

   

    return a.exec();

}

根据之前讲的内容可以发现,由于上面的QWidget w对象没有父组件,所以QWidget w便成为了没有父组件的顶级组件,从而生成了窗口.

Qt坐标系统

介绍

  • Qt使用统一的坐标系统定位窗口部件的位置和大小
  • QWidget类为组件类提供了窗口部件所需的坐标系统成员函数

在Qt里,坐标类型分为

  • 顶级窗口部件的定位 : 父类的坐标位置
  • 窗口内部件的定位 : 子类的坐标位置
  • 窗口部件的大小设置 : 自己的坐标位置

QWidget类提供的常用坐标系统成员函数有:

  • resize() : 设置窗口内部的宽高( width()和height()值)
  • move() : 设置整个窗口的x,y坐标( x()和y()值)
  • setGeometry() : 设置窗口内部的x,y,w,h(不包括标题和窗口边框)
  • size() : 获取窗口部件的大小
  • pos() : 获取窗口部件的位置
  • x() : 获取整个窗口x坐标
  • y() : 获取整个窗口y坐标
  • width() : 获取窗口内部的宽度(不包括外边框的宽度)
  • height() : 获取窗口内部的高度(不包括窗口标题栏的高度)
  • const QRect& geometry () : 获取窗口内部的x,y,w,h(不包括标题和窗口边框)
  • const QRect& framgeometry () : 获取整个窗口的x,y,w,h

可以参考下图所示(Window and Dialog Widgets)

 

注意: 在代码里,执行show()后, 再获取 x,y,w,h坐标 才有效

接下来我们通过3组不同的获取坐标函数,来打印(x,y,w,h)坐标信息

代码如下所示:

#include <QtGui>
#include "widget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    QPushButton b("button",&w);   //生成 QPushButton对象, 其父组件为 QWidget

    /*设置窗口大小位置*/
    w.resize(200,300);
    w.move(300,300);

    /*设置按钮大小位置*/
    b.resize(100,50);
    b.move(50,100);
    w.show();

    qDebug()<<"QWidget:";
    qDebug()<<"x()="<<w.x();
    qDebug()<<"y()="<<w.y();
    qDebug()<<"width()="<<w.width();
    qDebug()<<"height()="<<w.height();
    qDebug()<<"QWidget::geometry()";
    qDebug()<<"x="<<w.geometry().x();
    qDebug()<<"y="<<w.geometry().y();
    qDebug()<<"w="<<w.geometry().width();
    qDebug()<<"h="<<w.geometry().height();
    qDebug()<<"QWidget::frameGeometry()";
    qDebug()<<"x="<<w.frameGeometry().x();
    qDebug()<<"y="<<w.frameGeometry().y();
    qDebug()<<"w="<<w.frameGeometry().width();
    qDebug()<<"h="<<w.frameGeometry().height();
    return a.exec();
}

运行打印:

QWidget:
x()= 300
y()= 300
width()= 200
height()= 300

QWidget::geometry()
x= 308
y= 330
w= 200
h= 300

QWidget::frameGeometry()
x= 300
y= 300
w= 216
h= 338

可以看到,获取的窗内坐标(x,y)永远比窗外坐标大,窗外大小(w,h)永远比窗内大小大

初探消息处理(信号与槽)

Qt中定义了与系统信息相关的概念

信号(signal)

  • 由操作系统产生的消息,比如按键消息

槽(slot)

  • 程序中的消息处理函数,用来处理信号,比如处理按键点击信号

连接(Connect)

  • 将系统信息绑定到信息处理函数(信号到槽的连接),通过connect()函数实现,且必须发生在两个Qt类对象之间,如下图所示:

 

connect()函数原型

bool QObject::connect (
        const QObject * sender,                 //发送对象
        const char * signal,                     //消息名(信息)
        const QObject * receiver,                //接收对象
        const char * method,                     //接收对象的成员函数(槽)
        Qt::ConnectionType type = Qt::AutoConnection ) ;   //正常情况不需要设置

//当出现sender对象的signal信号,则会自动调用receiver对象的method
//连接成功,则返回true;否则返回false。

在信号与槽里,Qt引进了几个新的关键字:

  • SIGNAL :指定消息名(信号),用于connect()函数里
  • SLOT : 指定消息处理函数名(槽),用于connect()函数里
  • Q_OBJECT : 指定该类拥有槽(消息处理),在类声明的内部开始处加上Q_OBJECT即可
  • slots : 用于在类中声明消息处理函数,比如:
private slots:
         void buttonCliked();

初探信号与槽

通过点击按钮,使程序自动退出,代码如下所示:

#include <QtGui>
#include <QApplication>
#include <QPushButton>

int main(int argc,char * argv[])
{
  QApplication app(argc,argv);
  QPushButton *quitButton = new QPushButton("Quit");

  QObject::connect(quitButton, SIGNAL(clicked()), &app, SLOT(quit()));
  //*quitButton(发送对象), &app(接收对象)
  //quit()作用是退出程序, QApplication的成员函数
  //clicked()作用是鼠标点击, 很多常用组件的成员函数

    quitButton->show();
    return app.exec();
}

其中上面的quit() 和clicked()都是系统预定义好的,接下来我们自定义槽

首先需要注意

    • 类中声明槽(处理信号的成员函数)时,需要slots声明
    • 槽和信号的函数参数必须一致,比如clicked()和quit()都是无参数的
    • SIGNAL和SLOT指定的函数(信号和槽)只能包含参数类型,不能包含参数名

开始试验,通过不同按钮点击,来打印不同的信息

写QButtonDebug.h:

#ifndef QBUTTONDEBUG_H
#define QBUTTONDEBUG_H

#include <QWidget>
#include <QPushButton>

class QButtonDebug : public QWidget
{
    Q_OBJECT       //指定该类拥有slots(槽)

private:
    QPushButton *mbton1;
    QPushButton *mbton2;

private slots:              //通过slots 声明 槽
    void buttonCliked();

public:
    explicit QButtonDebug(QWidget *parent=0,Qt::WindowFlags f=0);
};

#endif 

写QButtonDebug.cpp:

#include "QButtonDebug.h"
#include <QDebug>

QButtonDebug:: QButtonDebug(QWidget *parent,Qt::WindowFlags f) :
    QWidget(parent,f)   //显示初始化父类
{
    mbton1 = new QPushButton("button1",this);
    mbton2 = new QPushButton("button2",this);
    /*设置按钮坐标*/
    mbton1->resize(100,50);
    mbton1->move(50,50);
    mbton2->resize(100,50);
    mbton2->move(50,100);
    /*设置连接*/
    QObject::connect(mbton1,SIGNAL(clicked()),this,SLOT(buttonCliked()));
    QObject::connect(mbton2,SIGNAL(clicked()),this,SLOT(buttonCliked()));
    QWidget::show();
}

void QButtonDebug:: buttonCliked()            //消息处理函数
{
    QPushButton* p_buton =dynamic_cast<QPushButton*>(sender());    //获取发送信号的对象   使用
    qDebug()<< p_buton->text();                      //更据不同的按钮 打印不同信息
}

写main.cpp

#include <QtGui>
#include <QApplication>
#include "QButtonDebug.h"

int main(int argc,char * argv[])
{
  QApplication a(argc, argv);

  QButtonDebug b(NULL,Qt::WindowCloseButtonHint);      
                     // Qt::WindowCloseButtonHint:去掉标题按钮提示

  return a.exec();
}

运行测试

如下图所示,可以看到通过点击不同的按钮,便能打印不同的信息出来

 

深入信号槽-自定义信号

介绍

  • 只有Qt类才能定义信号,且该类必须在头文件中声明
  • 信号函数只能通过signals关键字进行声明,不能定义,且返回值必须是void类型
  • 信号函数的属性会被自动设置为protected类型
  • 发送信号时,只需要通过emit关键字调用信号函数即可
  • 如果信号函数的参数多于槽函数时,多于的参数将被忽略
  • 槽函数的返回值必须是void类型,且可以被其它普通成员函数调用


自定义信号示例:

class MySignal : public QObject
{
  Q_OBJECT
signals:     //自定义信号函数
  void SendSignal(int i); 

public:
  void send(int i)
  {
    emit SendSignal(i); //调用信号函数,发送信号
  } 
};

PS 信号如果要设为public,设置如下所示:

class MySignal : public QObject
{
  Q_OBJECT
public:
signals:     //自定义信号函数
  void SendSignal(int i); 

public:
  void send(int i)
  {
    emit SendSignal(i); //调用信号函数,发送信号
  } 
};

自定义槽函数示例:

class MySlot : public QObject
{
  Q_OBJECT
protected slots:
  void RecvSlot(int i)
  {
    qDebug()<<"Send:"<<sender()->objectName(); //打印发送对象名
    qDebug()<<"Recv:"<<i;
    qDebug()<<endl;
  }
};

信号与槽的组合

  • 信号函数可以连接多个槽函数
  • 多个信号函数可以连接一个槽函数
  • 一个信号就可以连接到另一个信号
  • 通过connect函数进行连接,也可以通过disconnect函数取消连接

示例1-多个信号连接一个槽:

    MySignal s1;
    MySignal s2;
    MySlot t;

    s1.setObjectName("Signal1");
    s2.setObjectName("Signal2"); 
    QObject::connect(&s1,SIGNAL(SendSignal(int)),&t,SLOT(RecvSlot(int)));
    QObject::connect(&s2,SIGNAL(SendSignal(int)),&t,SLOT(RecvSlot(int)));

    s1.send(10);
    s2.send(12);

打印:

Send: "Signal1" 
Recv: 10

Send: "Signal2" 
Recv: 12

示例2-信号1连接信号2,信号2连接槽:

    MySignal s1;
    MySignal s2;
    MySlot t;
    s1.setObjectName("Signal1");
    s2.setObjectName("Signal2");
    QObject::connect(&s1,SIGNAL(SendSignal(int)),&s2,SIGNAL(SendSignal(int)));
    QObject::connect(&s2,SIGNAL(SendSignal(int)),&t,SLOT(RecvSlot(int)));
    s1.send(10);
    s2.send(12);

打印:

    Send: "Signal2" 
    Recv: 10 

    Send: "Signal2" 
    Recv: 12

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值