#include
#include
class Widget :public QWidget
{
Q_OBJECT
public:
Widget(QWidget* parent =nullptr):QWidget(parent)
{
}
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
//如果把类和main这个文件写在了同一个文件,那么必须在代码最后加上#include[空格]"文件名.moc"
//这行预处理指令,告诉moc这个文件需要进行元编译,以实现Q_OBJECT宏中声明的函数
#include "main.moc"
#include
#include
#include
class Widget :public QWidget
{
//只要用到信号与槽就必须加这个宏
Q_OBJECT
public:
Widget(QWidget* parent =nullptr):QWidget(parent)
{
//设置窗口大小
resize(600, 600);
//添加按钮,放到在自己主屏幕上
QPushButton *btn = new QPushButton(this);
//添加文本
btn->setText("小瓜");
//移动按钮位置
btn->move({300,300});
//当点击按钮的时候进行自定义操作
connect(btn, &QPushButton::clicked, this, &Widget::on_btn_clicked);
}
//槽函数
void on_btn_clicked()
{
qDebug() << "你点击了小瓜";
}
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
//如果把类和main这个文件写在了同一个文件,那么必须在代码最后加上#include[空格]"文件名.moc"
//这行预处理指令,告诉moc这个文件需要进行元编译,以实现Q_OBJECT宏中声明的函数
#include "main.moc"
信号与槽:实际就是一个观察者模式(发布-订阅模式),例如按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。这样就让互不干扰的对象建立了联系
槽实际上就是普通的函数,成员函数、全局函数、静态函数、lambda函数都可以!
当我们把对象的信号和槽绑定在一起之后,当信号触发时,与之绑定的槽函数将会自动调用,并把信号的参数传递给槽函数
QObject::connent()
函数实现,其基本格式如下: [static] QMetaObject::Connection connect(
const QObject *sender,
const QMetaMethod &signal,
const QObject *receiver,
const QMetaMethod &method,
, Qt::ConnectionType type = Qt::AutoConnection)
[static] QMetaObject::Connection connect(
const QObject *sender,
PointerToMemberFunction signal,
Functor functor)
Contents
中寻找关键字 signals
,信号的意思,但是我们发现并没有找到,这时候我们应该看当前类从父类继承下来了哪些信号,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个QObject::disconnect(m_btn, &QPushButton::released, this, &Widget::on_btn_released);
QMetaObject::Connection con = QObject::connect(m_btn,&QPushButton::clicked,this,&Widget::on_btn_released);
QObject::disconnect(con);
#include
#include
#include
class Widget :public QWidget
{
//只要用到信号与槽就必须加这个宏
Q_OBJECT
public:
//初始化按钮成员
Widget(QWidget* parent =nullptr):QWidget(parent),m_btn(new QPushButton("小瓜", this))
{
//设置窗口大小
resize(300, 300);
//连接m_btn信号
m_con = connect(m_btn, &QPushButton::clicked, this, &Widget::on_btn_clicked);
connect(m_btn, &QPushButton::pressed, this, &Widget::on_btn_pressed);
connect(m_btn, &QPushButton::released, this, &Widget::on_btn_released);
}
//槽函数
void on_btn_clicked()
{
qDebug() << "click";
}
void on_btn_pressed()
{
//如果按钮按下,断开released信号连接
disconnect(m_btn, &QPushButton::released, this, &Widget::on_btn_released);
//使用连接标识断开连接
disconnect(m_con);
qDebug() << "press";
}
void on_btn_released()
{
qDebug() << "releas";
}
protected:
QPushButton* m_btn{};
//使用连接标识断开连接
QMetaObject::Connection m_con{};
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
//如果把类和main这个文件写在了同一个文件,那么必须在代码最后加上#include[空格]"文件名.moc"
//这行预处理指令,告诉moc这个文件需要进行元编译,以实现Q_OBJECT宏中声明的函数
#include "main.moc"
#include
#include
#include
void on_btn_clicked_global()
{
qDebug() << __FUNCTION__;
}
class Widget :public QWidget
{
//只要用到信号与槽就必须加这个宏
Q_OBJECT
public:
//初始化按钮成员
Widget(QWidget* parent =nullptr):QWidget(parent),m_btn(new QPushButton("小瓜", this))
{
//设置窗口大小
resize(300, 300);
//连接m_btn信号
m_con = connect(m_btn, &QPushButton::clicked, this, &Widget::on_btn_clicked);
connect(m_btn, &QPushButton::pressed, this, &Widget::on_btn_pressed);
connect(m_btn, &QPushButton::released, this, &Widget::on_btn_released);
//把静态函数作为槽函数
connect(m_btn, &QPushButton::released, this, &Widget::on_btn_clicked_static);
//全局函数作为槽函数
connect(m_btn, &QPushButton::released, on_btn_clicked_global);
//lambda表达式作为槽函数
connect(m_btn, &QPushButton::clicked, []() {qDebug() << "lambda"; });
//lambda捕获组件中的文本
connect(m_btn, &QPushButton::clicked, [this]() {qDebug() << m_btn->text(); });
//获取信号传递的参数
connect(m_btn, &QPushButton::clicked, [this](bool checked) {qDebug() << m_btn->text() << checked; });
m_btn->setCheckable(true);//设置按钮可以选中
}
//一般槽函数都加上slots这个标识宏
public slots:
void on_btn_clicked()
{
qDebug() << "click";
}
void on_btn_pressed()
{
//如果按钮按下,断开released信号连接
disconnect(m_btn, &QPushButton::released, this, &Widget::on_btn_released);
//使用连接标识断开连接
disconnect(m_con);
qDebug() << "press";
}
void on_btn_released()
{
qDebug() << "releas";
}
static void on_btn_clicked_static()
{
qDebug() << __FUNCTION__;
}
protected:
QPushButton* m_btn{};
//使用连接标识断开连接
QMetaObject::Connection m_con{};
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
//如果把类和main这个文件写在了同一个文件,那么必须在代码最后加上#include[空格]"文件名.moc"
//这行预处理指令,告诉moc这个文件需要进行元编译,以实现Q_OBJECT宏中声明的函数
#include "main.moc"
emit mysignals(); //发送信号
#include
#include
#include
#include
class Login :public QWidget
{
Q_OBJECT
public:
//初始化登录界面的组件
Login(QWidget* parent = nullptr) :QWidget(parent)
, userNameEdit(new QLineEdit(this))
, passwordEdit(new QLineEdit(this))
, login(new QPushButton("登录", this))
{
//设置窗口大小
resize(600, 400);
//设置控件位置居中位,窗口宽度-控件的宽度/2,高度就自行设置
userNameEdit->move((width() - userNameEdit->width()) / 2, 50);
passwordEdit->move((width() - passwordEdit->width()) / 2, 100);
login->move((width() - login->width()) / 2, 150);
//连接信号与槽
connect(login, &QPushButton::clicked, [=]()
{
auto userName = userNameEdit->text();
auto password = passwordEdit->text();
//是否验证成功
if (1)
{
emit sig_loginSucceed();//emit无任何作用,仅作为标识
emit sig_loginSucceed(userName, password);
}
});
//信号转发
connect(this, QOverload<>::of(&Login::sig_loginSucceed),this, &Login::login_OK);
}
//signals 下面只能放信号
signals:
void sig_loginSucceed();
void sig_loginSucceed(const QString& userName,const QString& password);
void login_OK();
protected:
QLineEdit* userNameEdit{};
QLineEdit* passwordEdit{};
QPushButton* login{};
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Login w;
w.show();
//信号重载的二义性问题
//1.使用函数指针解决
void (Login:: * sig_loginSucceed_ptr)(const QString & userName, const QString & password) = &Login::sig_loginSucceed;
QObject::connect(&w, sig_loginSucceed_ptr, [](const QString& userName, const QString& password)
{
qDebug() << "登录成功" << "用户名:" << userName << "密码:" << password;
});
//2.使用QOverload类解决
QObject::connect(&w, QOverload<const QString&,const QString&>::of(&Login::sig_loginSucceed), [](const QString& userName, const QString& password)
{
qDebug() << "登录成功2" << "用户名:" << userName << "密码:" << password;
});
//信号转发
QObject::connect(&w, &Login::login_OK, []()
{
qDebug() << "login_Ok";
});
return a.exec();
}
//如果把类和main这个文件写在了同一个文件,那么必须在代码最后加上#include[空格]"文件名.moc"
//这行预处理指令,告诉moc这个文件需要进行元编译,以实现Q_OBJECT宏中声明的函数
#include "main.moc"
#ifndef WIDGET_H_
#define WIDGET_H_
#include
#include
#include "SubWidget.h"
class Widget :public QWidget
{
Q_OBJECT
public:
Widget(QWidget* parent = nullptr);
protected:
//初始化为空指针
SubWidget* m_subWidget{};
QPushButton* m_curBtn{};
};
#endif // !WIDGET_H_
#include "Widget.h"
Widget::Widget(QWidget* parent) :QWidget(parent)
,m_subWidget(new SubWidget)
,m_curBtn(new QPushButton("切换到子窗口",this))
{
//设置标题
setWindowTitle("主窗口");
resize(600, 400);
connect(m_curBtn, &QPushButton::clicked, [=]()
{
//隐藏主窗口组件
this->hide();
//切换到子窗口
m_subWidget->show();
}
);
//接收信号,切换回主窗口
connect(m_subWidget, &SubWidget::showMainWidget, [=]()
{
this->show();
m_subWidget->hide();
});
}
#ifndef SUBWIDGET_H_
#define SUBWIDGET_H_
#include
#include
class SubWidget :public QWidget
{
Q_OBJECT
public:
SubWidget(QWidget* parent = nullptr);
signals:
//切换窗口信号
void showMainWidget();
protected:
QPushButton* m_btn{};
};
#endif // !WIDGET_H_
#include "SubWidget.h"
SubWidget::SubWidget(QWidget* parent):QWidget(parent)
,m_btn(new QPushButton("切换到主窗口",this))
{
//设置标题
setWindowTitle("子窗口");
resize(600, 400);
connect(m_btn, &QPushButton::clicked, [=]() {
this->hide();
//发送切换窗口信号
emit showMainWidget();
});
//或者一句话搞定,和上面一样
//connect(m_btn, &QPushButton::clicked, this, &SubWidget::showMainWidget);
}