一、HelloQt(从空向项目开始)
- 创建一个新的项目,选择其他选项,选择创建一个空项目HelloQt
- 在HelloQt.pro添加内容,表示使用图形界面(注意后面没有分号)
Qt += widgets
- 编写第一个Widget窗体, 导入qtextcodec.h来解决中文乱码问题
#include <QApplication>
#include <QWidget>
#include "qtextcodec.h"
int main(int argc, char **argv){
QApplication app(argc, argv);
// 解决中文乱码
QTextCodec *codec = QTextCodec::codecForName("GBK");
QWidget widget;
widget.setWindowTitle(codec->toUnicode("这是中文标题的写法"));
widget.show();
app.exec();
return 0;
}
- 给控件指定父对象的方法
- setParent()
- 通过构造函数传参
// QPushButton b(&widget); QPushButton b; b.setParent(&widget); b.setText("^_^"); b.move(100, 100); b.show();
二、信号和槽 (Signal&Slot)
-
简单的点击按钮关闭窗口
widget.h#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT // 使用信号和槽所需要的 public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; QPushButton b1; // 定义两个按钮 QPushButton *b2; // 定义指针按钮调用的时候需要进行赋值 }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); b1.setParent(this); b1.setText("^-^"); b1.move(100, 100); b2 = new QPushButton(this); b2->setText("^!^"); b2->move(200, 200); /** &b1: 信号发出者,指针类型 &QPushButton::clicked 处理信号, &信号发送者类名::信号名 &this: 信号接受者 &MainWidget::close 槽函数,信号处理函数 &接受的类名:槽函数名 */ connect(&b1, &QPushButton::clicked, this, &Widget::close); } Widget::~Widget() { delete ui; }
-
自定义信号和槽
自定义槽: 普通函数的用法
Qt5: 任意的成员函数,普通全局函数,静态函数
槽函数的 参数和返回值 需要和信号函数的一致
由于信号没有返回值,所以槽函数也没有返回值widget.h中添加void自定义有槽函数
public: explicit Widget(QWidget *parent = 0); ~Widget(); void mySlot();
/** &b1: 信号发出者,指针类型 &QPushButton::clicked 处理信号, &信号发送者类名::信号名 &this: 信号接受者 &MainWidget::close 槽函数,信号处理函数 &接受的类名:槽函数名 */ connect(&b1, &QPushButton::clicked, this, &Widget::close); // b2本来就是一个指针,因此这里不需要添加地址引用符 connect(b2, &QPushButton::released, this, &Widget::mySlot); // 按下b2后隐藏b1 connect(b2, &QPushButton::released, &b1, &QPushButton::hide);
三、两个独立窗口
- 新建.class,会自动生成.h和.cpp两个文件,基类选择QWidget,新建一个Subwidget,主窗口定义一个按钮,点击按钮隐藏主窗口,显示子窗口。在Subwidget中定义一个按钮,点击按钮隐藏子窗口,显示主窗口
subwidget.h /**sendSlot用于发送子窗口的信号mySingle*/ #ifndef SUBWIDGET_H #define SUBWIDGET_H #include <QWidget> #include <QPushButton> class SubWidget : public QWidget { Q_OBJECT public: explicit SubWidget(QWidget *parent = nullptr); QPushButton b; void sendSlot(); signals: /**信号必须有 signals关键字来声明 信号没有返回值,但可以有参数 信号就是函数的声明,只需要声明,无需定义 使用:在cpp中使用emit来触发函数 emit mySingal(); */ void mySingal(); public slots: }; #endif // SUBWIDGET_H ================================================================================= subWidget.cpp #include "subwidget.h" SubWidget::SubWidget(QWidget *parent) : QWidget(parent) { this->setWindowTitle("Boos little"); b.setParent(this); b.setText("Change to Boss"); connect(&b, &QPushButton::clicked, this, &SubWidget::sendSlot); } void SubWidget::sendSlot(){ emit mySingal(); // 发送信号 }
- myWidget主窗口中接收子窗口传递来的信(定义一个connect会一直监听)
/**sub是子窗口subwidget的实例 delSub是主窗口用来处理子窗口信号的函数 */ // 处理SubWidget中发送过来的信号 connect(&sub, &SubWidget::mySingal, this, &Widget::dealSub); // 处理子窗口信号的函数 void Widget::dealSub(){ this->show(); sub.hide(); }
四、带参数的信号
-
在 subwidget.h中定义两个同名不同参数的信号
subweiget.h signals: /**信号必须有 signals关键字来声明 信号没有返回值,但可以有参数 信号就是函数的声明,只需要声明,无需定义 使用:在cpp中使用emit来触发函数 emit mySingal(); */ void mySignal(); void mySignal(int, QString); subweiget.cpp #include "subwidget.h" SubWidget::SubWidget(QWidget *parent) : QWidget(parent) { this->setWindowTitle("Boos little"); b.setParent(this); b.setText("Change to Boss"); connect(&b, &QPushButton::clicked, this, &SubWidget::sendSlot); } void SubWidget::sendSlot(){ emit mySignal(); // 发送信号 // 信号有几个参数,槽函数也得要有对应的参数进行处理 emit mySignal(250, "我是子窗口"); }
Weiget.cpp 定义两个处理subWeiget中传输信号的函数, 使用函数指针指定要调用的是有参函数还是无参函数 // 处理SubWidget中发送过来的信号 void (SubWidget::*NoArgSignal)() = &SubWidget::mySignal; connect(&sub, NoArgSignal, this, &Widget::dealSub); // 处理带有参数的槽函数,这里区分同名带参数的函数和的带参数的函数,现需要使用函数指针 void (SubWidget::*HaveArgSignal)(int, QString) = &SubWidget::mySignal; connect(&sub, HaveArgSignal, this, &Widget::dealSlot); // 处理子窗口信号的函数 void Widget::dealSub(){ this->show(); sub.hide(); } // 处理带有参数的信号 void Widget::dealSlot(int a, QString str){ // str.toUtf8() 转换为字节数组 QByteArray // .data() 将字节数组QByteArray->char * qDebug() << a << "==" << str.toUtf8().data(); }
五、Lamda表达式和信号的功能
-
在项目文件 .pro中添加新的配置 CONFIG += C++11
Lambad表达式,匿名函数对象, C++11中新添加的特性, 和Qt信号配合使用 -
/** * []中添加b4就可以在lambda表达式中访问外部按钮b4了 [=] 将外部所有局本部变量、类中所有成员以值的方式传递,但是默认传递的值是不可以修改的, 是只读属性 [this]: 类中所有成员以值的方式传递 [&]: 把外部所有局部变量,引用符号传递 [=]() mutable:添加mutable就可以修改传进来的外部参数 */ connect(b4, &QPushButton::released, [=]() mutable { qDebug() << "111111"; b4->setText("123"); } );