命令父窗口变颜色_Qt窗口系统

一、Qt窗口坐标体系

  • 以左上角为原点,X向右增加,Y向下增加;

  • 对于嵌套窗口,其坐标 是相对于父窗口来说的。

fac5bd19c6b0b9799542f8b2143d4a9c.png

二、基础窗口部件QWidget

QWidget类是所有用户界面对象的基类,被称为基础窗口部件。

所有窗口及窗口控件都是从QWidget直接或者间接派生出来的。

  • QWidget继承自QObject类和QPaintDevice类

    • QObject类是所有支持Qt对象模型(Qt Object Model)的对象的基类

    • QPaintDevice类是所有可以绘制的对象的基类

可以通过Qt助手(Qt Assistant)中的索引搜索

cf6e291be938b1dcaa10ef35e555cd16.png

1.代码书写位置

  • 向导方式创建项目

    bedea17ec6868b0e8576925aec56a24a.png

    61d77fecfa4db94ca1f084df3fea59aa.png

  • 推荐写在mywidget.cpp中

    #include "mywidget.h"MyWidget::MyWidget(QWidget *parent)    : QWidget(parent){    //构造方法,代码推荐写在这里    //设置窗口标题    this->setWindowTitle("我的一个Widget");    //设置窗口大小(可变大小)    //this->resize(800,600);    //设置窗口大小(不可变大小)    this->setFixedSize(400,300);    //设置窗口的背景颜色    this->setAutoFillBackground(true);    //QPalette类包含每个小部件状态的颜色组    QPalette pa = this->palette();    //将给定颜色角色的笔刷设置为调色板中所有组的指定笔刷    pa.setBrush(QPalette::Background, QBrush(Qt::green));    setPalette(pa);    //设置窗口透明度,0-1    this->setWindowOpacity(0.5);}MyWidget::~MyWidget(){}
    • 代码中包含.h头文件#include "mywidget.h"

      #ifndef MYWIDGET_H#define MYWIDGET_H#include class MyWidget : public QWidget{    Q_OBJECTpublic:    MyWidget(QWidget *parent = 0);    ~MyWidget();};//1、如果parent=0 ( 默认值),则新建的窗口部件一定将是一个窗口;//2、如果parent != 0,则新建的窗口部件可能是子窗口部件也有可能是一个窗口,由它参数Qt::WindowFlags属性决定;#endif // MYWIDGET_H

在.h头文件中,包含头文件#include ,因为下面所有要用到的类,如QApplication,QWidget等,都包含在QtWidgets模块中,为了简便,只包含了QtWidgets的头文件。

窗口部件(Widget)简称部件,是Qt中建立用户界面的主要元素。像主窗口、对话框、标签、还有以后要介绍到的按钮、文本输人框等都是窗口部件。这些部件可以接收用户输入、显示数据和状态信息,并且在屏幕上绘制自己。有些也可以作为一个容器来放置其他部件。Qt中把没有嵌入到其他部件中的部件称为窗口,一般窗口都有边框和标题栏,就像程序中的widget一样。QMainWindow和大量的QDialog子类是最一般的窗口类型。

窗口就是没有父部件的部件,所以又称为顶级部件( top-level wid-get);与其相对的是非窗口部件,又称为子部件(child widget)。在Qt中大部分部件被用作子部件,嵌入在别的窗口中。这部分内容可以查看关键字QtWidgets和 Window and Dialog Widgets。

    QWidget提供了自我绘制和处理用户输入等基本功能,Qt提供的所有界面元素不是QWidget的子类就是与QWidget的子类相关联。要设计自己的窗口部件,可以继承自QWidget或者是它的子类。

2.按钮的创建

父窗口和子窗口

如果把一个窗口作为某个容器窗口的子窗口,那么该窗口将被束缚在其父窗口的内部,并伴随父窗口一起移动、隐藏、显示和关闭,否则该窗口将作为独立窗口显示在屏幕上,且游离于其它窗口之外。

只有QWidget及其子类的对象可以做为其它窗口的容器

父窗口的析构函数负责销毁其所有的子窗口对象,因此即使子窗口对象是通过new运算符动态创建的,也无需因为没有显式地delete它们而担心内存泄漏的风险(在Qt中销毁父对象的时候会自动销毁子对象)。

析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。

设置窗口的位置和大小

  • void move (int x, int y);

  • void resize (int w, int h);

常用的父窗口类有如下三个:

  • QWidget

  • QMainWindow(主窗口,通常由标题栏、菜单栏、工具条、状态栏以及中央客户区组成) //QWidget的直接子类

  • QDialog(对话框类,管理多个不同种类的交互式部件)//QWidget的直接子类

案例操作:

  • 在构造函数中添加(运行后发现Button一闪而过,没有出现在窗口上)

    #include "mywidget.h"#include MyWidget::MyWidget(QWidget *parent)    : QWidget(parent){    //构造方法,代码推荐写在这里    //设置窗口标题    this->setWindowTitle("我的一个Widget");    //设置窗口大小(可变大小)    //this->resize(800,600);    //设置窗口大小(不可变大小)    this->setFixedSize(400,300);    //设置窗口的背景颜色    this->setAutoFillBackground(true);    //QPalette类包含每个小部件状态的颜色组    QPalette pa = this->palette();    //将给定颜色角色的笔刷设置为调色板中所有组的指定笔刷    pa.setBrush(QPalette::Background, QBrush(Qt::green));    setPalette(pa);    //设置窗口透明度,0-1    this->setWindowOpacity(0.9);    QPushButton button;    button.show();}MyWidget::~MyWidget(){}

    aa8467b264f4e5b931838fe72423c082.png

  • 改进:在.h头文件中加入QPushButton指针(未指定父对象,按钮窗口会单独显示)

    #ifndef MYWIDGET_H#define MYWIDGET_H#include #include class MyWidget : public QWidget{    Q_OBJECTpublic:    MyWidget(QWidget *parent = 0);    ~MyWidget();     //按钮指针    QPushButton *button;};//1、如果parent=0 ( 默认值),则新建的窗口部件一定将是一个窗口;//2、如果parent != 0,则新建的窗口部件可能是子窗口部件也有可能是一个窗口,由它参数Qt::WindowFlags属性决定;#endif // MYWIDGET_H
    #include "mywidget.h"#include MyWidget::MyWidget(QWidget *parent)    : QWidget(parent){    //构造方法,代码推荐写在这里    //设置窗口标题    this->setWindowTitle("我的一个Widget");    //设置窗口大小(可变大小)    //this->resize(800,600);    //设置窗口大小(不可变大小)    this->setFixedSize(400,300);    //设置窗口的背景颜色    this->setAutoFillBackground(true);    //QPalette类包含每个小部件状态的颜色组    QPalette pa = this->palette();    //将给定颜色角色的笔刷设置为调色板中所有组的指定笔刷    pa.setBrush(QPalette::Background, QBrush(Qt::green));    setPalette(pa);    //设置窗口透明度,0-1    this->setWindowOpacity(0.9);//    QPushButton button;//    button.show();    button = new QPushButton;    button->show();}MyWidget::~MyWidget(){}

    062d496c70e0522e1d78c8033560b56a.png

  • 指定按钮的父类是窗口

    #include "mywidget.h"#include MyWidget::MyWidget(QWidget *parent)    : QWidget(parent){    //构造方法,代码推荐写在这里    //设置窗口标题    this->setWindowTitle("我的一个Widget");    //设置窗口大小(可变大小)    this->resize(800,600);    //设置窗口大小(不可变大小)    //this->setFixedSize(400,300);    //设置窗口的背景颜色    this->setAutoFillBackground(true);    //QPalette类包含每个小部件状态的颜色组    QPalette pa = this->palette();    //将给定颜色角色的笔刷设置为调色板中所有组的指定笔刷    pa.setBrush(QPalette::Background, QBrush(Qt::green));    setPalette(pa);    //设置窗口透明度,0-1    this->setWindowOpacity(0.9);//    QPushButton button;//    button.show();    button = new QPushButton;    button->show();    button->setParent(this);}MyWidget::~MyWidget(){}

    d15eb5a281efc4667008739469fa370e.png

  • 可以设置button的一些属性resize、move等,此处略

3.编码

#include "mainwindow.h"#include #include #include #include int main(int argc, char *argv[]){    QApplication a(argc, argv);    // 创建编码对象    QTextCodec* codec = QTextCodec::codecForName("gbk");    // 将要显示的gbk编码的字符串转换成unicode    QLabel label(codec->toUnicode("我是标签"));    label.show();    QPushButton btn(codec->toUnicode("我是按钮"));    btn.show();    return a.exec();}

ae9304ea2c8274ada38336288793610a.png

如果想把两个窗口整合到父窗口上

#include "mainwindow.h"#include #include #include #include int main(int argc, char *argv[]){ QApplication a(argc, argv); QMainWindow w; w.resize(400,400); // 创建编码对象 QTextCodec* codec = QTextCodec::codecForName("gbk"); // 将要显示的gbk编码的字符串转换成unicode QLabel label(codec->toUnicode("我是标签"),&w); label.move(100,100); QPushButton btn(codec->toUnicode("我是按钮"),&w); btn.move(200,200); w.show(); return a.exec();}

三、信号和槽机制

1. 什么是信号和槽

  • 信号和槽是QT自行定义的一种通信机制,用于两个对象之间的通信,实现对象之间的数据交互

  • 当用户或系统触发了一个动作,导致某个控件的状态发生了改变,该控件就会发射一个信号(signal),即调用其类中一个特定的成员函数(信号),同时还可能携带有必要的参数。

  • 槽(slot)和普通的成员函数几乎没有太多区别,可以是公有的、保护的或私有的,可以被重载,也可以被覆盖,其参数可以是任意类型,并可以像普通成员函数一样调用。

  • 槽函数与普通成员函数的差别并不在于其语法特性,而在于其功能。槽函数更多体现为对某种特定信号的处理,可以将槽和其它对象信号建立连接(connect),这样当发射信号时,槽函数将被触发和执行,进而来完成具体功能。


2.信号的定义

class XX:public QObject{    Q_OBJECTsignals:    void signal_func(..); //信号函数};

注:信号函数只需声明,不能写定义

3.槽的定义

class XX:public QObject{    Q_OBJECTpublic slots:    void slot_func(...){...}//槽函数};

注:槽函数可以连接到某个信号上,当信号被发射时,槽函数将被触发和执行,另外槽函数也可以当做普通的成员函数直接调用

信号和槽连接起来,是通过QObject类的connect(成员函数完成的

Qobject :: connect(        const Qobject * sender,        const char * signal,        const Qobject * receiver,        const char * mothod);
  • sender:信号发送对象指针

  • signal:要发送的信号函数,可以使用“SIGNAL(..)” 宏进行类型转换

  • receiver:信号的接收对象指针

  • method:接收信号后要执行的槽函数,可以使用“SLOT(..)” 宏进行类型转换

4.案例1

创建Qt应用程序,包含标签和按钮两个控件,实现点击按钮关闭标签

  • 按钮点击时发送信号:clicked()

  • 实现标签关闭功能的槽:close()

#include "widget.h"#include #include #include int main(int argc, char *argv[]){    QApplication a(argc, argv);    QWidget parent;    parent.resize(400,400);    QLabel label("信号和槽",&parent);    label.move(150,150);    QPushButton button("关闭",&parent);    button.move(300,300);    button.resize(100,100);    parent.show();    QObject::connect(&button,SIGNAL(clicked()),&a,SLOT(closeAllWindows()));    return a.exec();}

进阶版

#include "dialog.h"#include #include #include #include int main(int argc, char *argv[]){    QApplication app(argc, argv);    Dialog parent;    parent.move(100,100);    parent.resize(300,200);    QLabel label("标签",&parent);    label.move(50,30);    label.resize(100,35);    QLabel label2("标签",&parent);    label2.move(180,30);    label2.resize(100,35);    QPushButton btn("关闭label",&parent);    btn.move(50,100);    btn.resize(100,35);    QPushButton btn2("关闭所有",&parent);    btn2.move(180,100);    btn2.resize(100,35);    parent.show();    QObject::connect(&btn,SIGNAL(clicked(void)),                     &label,SLOT(close(void)));    QObject::connect(&btn,SIGNAL(clicked(void)),                     &label2,SLOT(close(void)));    QObject::connect(&btn2,SIGNAL(clicked(void)),                     &app,SLOT(closeAllWindows(void)));    return app.exec();}

5.信号和槽连接的语法要求

  • 信号和槽参数要一致

    QObject::connect(A,SIGNAL(sigfun(int)), B,SLOT(slotfun(int)));//okQObject::connect(A,SIGNAL(sigfun(int)), B,SLOT(slotfun(int,int)));//error
  • 可以带有缺省参数

    QObject::connect(A,SIGNAL(sigfun(int)), B,SLOT(slotfun(int,int=0)));//ok
  • 信号函数的参数可以多于槽函数,多余参数将被忽略

    QObject::connect(A,SIGNAL(sigfun(int,int)), B,SLOT(slotfun(int)));//ok

6.信号和槽连接的应用

  • 一个信号可以被连接到多个槽(一对多)

    QObject::connect(A,SIGNAL(sigfun(int)), B1,SLOT(slotfun1(int)));//okQObject::connect(A,SIGNAL(sigfun(int)), B2,SLOT(slotfun2(int)));//ok
  • 多个信号也可以连接到同一个槽(多对一)

    QObject::connect(A1,SIGNAL(sigfun1(int)), B,SLOT(slotfun(int)));//okQObject::connect(A2,SIGNAL(sigfun2(int)), B,SLOT(slotfun(int)));//ok
  • 两个信号可以直接连接(信号级联)//了解

    QObject::connect(A1,SIGNAL(sigfun1(int)), A2,SIGNAL(sigfun2(int)));//ok

7.案例2

创建Qt应用程序,包含滑块(QSlider)和选值框(QSpinBox),通过信号和槽的机制,保持同步运行

  • QSlider//滑块

    void setRange (int min, int max); // 设置滑动范围void setValue (int)[slot]; // 设置当前位置void valueChanged (int value) [signal]; // 滑块滑动时发送信号
  • QSpinBox//选值框

    void setRange (int min, int max); // 设置数值改变范围void setValue (int)[slot]; // 设置当前数值void valueChanged (int value) [signal]; // 选值框数值改变时发送信号

代码:

#include "dialog.h"#include //滑块#include //选值框#include int main(int argc, char *argv[]){    QApplication app(argc, argv);    Dialog parent;    parent.resize(300,300);    //水平    QSlider slider(Qt::Horizontal,&parent);    slider.resize(150,30);    slider.move(50,50);    //设置取值的范围    slider.setRange(0,100);    //滑块的当前值,在取值范围之内    slider.setValue(50);    QSpinBox spinBox(&parent);    spinBox.move(50,100);    spinBox.resize(150,30);    spinBox.setRange(0,100);    spinBox.setValue(50);    parent.show();    //拖动滑块更改选值    QObject::connect(&slider,SIGNAL(valueChanged(int)),&spinBox,SLOT(setValue(int)));    //更改选值更改滑块位置    QObject::connect(&spinBox,SIGNAL(valueChanged(int)),&slider,SLOT(setValue(int)));    return app.exec();}

b29c21751f036a603b8c2287c296c56a.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值