QT 信号与槽 QT简单加法器的实现
信号与槽
背景:
面向过程
模块之间低耦合设计(高内聚)。
函数调用:
直接调用
回调调用(低耦合)
面向对象
模块之间低耦合设计(高内聚)
对象调用
直接调用
接口调用
QT:
信号与槽解决问题:
对象的成员变量调用?
对象的成员函数调用?
案例:
窗体,有一个文本框
线程,每个一秒改变文本框
问题:
线程类访问窗体组件比较麻烦,需要传递。
在QT中,使用线程程序可能不工作。
代码:
#include<QApplication>
#include “shake.h”
int main(int args , char **argv)
{
QApplication app(args , argv);
ShakeForm dlg;
dlg.setVisible(true);
return app.exec();
}
shake.h
#ifndef SHAKE_H
#define SHAKE_H
#include<QDialog>
#include<QLineEdit>
#include “mythread.h”
class ShakeForm : public QDialog
{
public:
ShakeForm(QWidget * parent=NULL);
~ShakeForm();
private:
QLineEdit *txt;
ShakeThread *th;
};
#endif
shake.cpp
#include “shake.h”
ShakeForm::ShakeForm(QWidget *parent)
{
txt = new QLineEdit(this);
this->resize(400,300);
txt->resize(100,30);
txt->move(10,10);
th=new ShakeThread(txt);
th->start();
}
ShakeForm::~ShakeForm()
{
delete txt;
}
mythread.h
#ifndef SHAKE_THREAD_H
#define SHAKE_THREAD_H
#include<pthread.h>
#include<QLineEdit>
class ShakeThread
{
public:
pthread_t tid;
static void * s_run(void *);
QLineEdit *m_txt;
private:
ShakeThread(QLineEdit *txt);
void start();
virtual void run();
};
#endif
mythread.cpp
#include “mythread.h”
#include<unistd.h>
#include<math.h>
ShakeThread::ShakeThread(QLineEdit *txt)
{
m_txt=txt;
}
void *ShakeThread::s_run(void * data)
{
ShakeThread *st=(ShakeThread*)data;
st->run();
returnNULL;
}
void ShakeThread::start()
{
pthread_create(&tid , 0, s_run ,this);
}
void ShakeThread::run()
{
//实现线程逻辑
intnum;
while(1)
{
//修改文本框
num=rand()%10000000;
m_txt->setText(QString::number(num));
sleep(1);
}
}
注意:全局函数调用成员函数不能通过编译:pthread_create全局函数调用run成员函数不能通过编译,ShakeThread::run(voiddata) 与 void*(*run)(void*) 参数不匹配。解决办法:把成员函数run定义成静态成员函数:staticvoid * run(void * data);
原因:成员函数代码在局部栈中,全局函数在全局栈,静态成员函数代码在全局栈,则可定义为静态成员函数。
案例总结:窗体中编辑框中并没有产生随机数的变化
原因:窗体为了防止界面混乱,为界面加了异步锁,线程很难访问窗体
使用信号与槽
最大的好处,通过参数传递,直接调用对象
以及在对象之间传递数据
1. 头与实现必须分开
2. 必须继承QObject
3. 被调用函数称为槽slot
4. 调用函数称为信号
5. 必须在类引入QObject中一个宏Q_OBJECT
6. 实现与c++完全一样
7. 信号与槽的返回值必须是void
8. 关联的信号与槽原型必须一致,名字可以不同
思考:
信号与槽在对象耦合上有什么优点?
例子:
log.h
#ifndef LOG_H
#define LOG_H
#include<QObject>
class Log :public QObject
{
Q_OBJECT //建议放到类的开始位置
public slots: //槽函数,可以被某个函数调用
void log();
};
#endif
log.cpp
#include “log.h”
#include<iostream>
using namespace std;
void Log::log()
{
cout<<“日志调用”<<endl;
}
biz.h //业务类
#ifndef BIZ_H
#define BIZ_H
#include<QObject>
class Biz : public QObject
{
Q_OBJECT
public:
void biz();
public: signals: //定义一个信号函数,信号函数不需要实现
void siglog();
};
#endif
biz.cpp
#include “biz.h”
#include<iostream>
#include<unistd.h>
using namespace std;
void Biz::biz()
{
while(1)
{
sleep(1);
cout<< “业务处理”<<endl;
//怎么调用槽?
emit siglog(); //调用信号函数,emit发送信号
}
}
main.cpp
#include “biz.h”
#include “log.h”
int main()
{
Log log;
Biz biz;
QObject::connect(
&biz, //信号源对象
SIGNAL(siglog()), //信号函数
&log, //槽目标对象
SLOT(log())); //槽函数
biz.biz();
}
注意:信号和槽函数返回值必须为void
使用信号和槽实现上边的案例:
代码:
#include<QApplication>
#include “shake.h”
int main(int args , char **argv)
{
QApplication app(args , argv);
ShakeForm dlg;
dlg.setVisible(true);
return app.exec();
}
shake.h
#ifndef SHAKE_H
#define SHAKE_H
#include<QDialog>
#include<QLineEdit>
#include “mythread.h”
class ShakeForm : public QDialog
{
Q_OBJECT
public:
ShakeForm(QWidget * parent=NULL);
~ShakeForm();
private:
QLineEdit *txt;
ShakeThread *th;
};
#endif
shake.cpp
#include “shake.h”
ShakeForm::ShakeForm(QWidget *parent)
{
txt = new QLineEdit(this);
this->resize(400,300);
txt->resize(100,30);
txt->move(10,10);
th=new ShakeThread();
QObject::connect(th,SIGNAL(setNumber(QString)),txt,SLOT(setText(QString)));
th->start();
}
ShakeForm::~ShakeForm()
{
delete txt;
}
mythread.h
#ifndef SHAKE_THREAD_H
#define SHAKE_THREAD_H
#include<pthread.h>
#include<QLineEdit>
class ShakeThread : public QObject
{
Q_OBJECT
public:
pthread_t tid;
static void * s_run(void *);
private:
ShakeThread();
void start();
virtual void run();
public : signals:
void setNumber(QString)
};
#endif
mythread.cpp
#include “mythread.h”
#include<unistd.h>
#include<math.h>
ShakeThread::ShakeThread()
{
}
void *ShakeThread::s_run(void * data)
{
ShakeThread *st=(ShakeThread*)data;
st->run();
returnNULL;
}
void ShakeThread::start()
{
pthread_create(&tid , 0, s_run ,this);
}
void ShakeThread::run()
{
//实现线程逻辑
intnum;
while(1)
{
//修改文本框
num=rand()%10000000;
emit setNumber(QString::number(num));
sleep(1);
}
}
总结:QLineEdit类中的setText函数就是个槽函数,只要在线程类中添加个信号函数setNumber ,在线程处理函数中发送信号函数并传值,则setText函数就会修改QLineEdit中的值。
注意:线程类要继承QObject类,并在线程类和窗体类中添加Q_OBJECT宏.
这样就不需要给线程类传递QLineEdit类的对象,而且可以修改文本框中的值了
QT可视化组件(控件)
其中的信号时怎么发出的?
信号时自动发出
案例:
使用按钮的信号
按钮事件发生的时候发出信号
事件->信号->槽
信号与槽解决如下问题:事件发生时,怎么调用用户函数
新的类:
QMessageBox提供一组静态函数弹出对话框
步骤:
1. main.cpp
2. *.pro
3. 对话框类
4. 实现按钮clicked信号对应槽函数
槽函数必须与clicked信号同型
void clicked(bool checked=false);
槽函数在哪个类实现?槽函数放入访问成员最多的类
5. 绑定信号与槽
代码:
main.cpp
#include<QApplication>
#include “mydialog.h”
int main(int args , char ** argv)
{
QApplication app(args,argv);
MyDialog dlg;
dlg.setVisible(true);
return app.exec();
}
main.pro
TEMPLATE=app
SOURCES=main.cpp mydialog.cpp
HEADERS=mydialog.h
CONFIG=release qt
QT=core gui
TARGET=main
mydialog.h
#ifndef MY_DIGLOG_H
#define MY_DIGLOG_H
#include<QDialog>
#include<QPushButton>
class MyDialog : public QDialog
{
Q_OBJECT
private:
QPushButton *btn;
public:
MyDialog(QWidget * parent=NULL);
~MyDialog();
public slots:
void showBox();
};
#endif
mydialog.cpp
#include “mydialog.h”
#include<iosteam>
#include<QMessageBox>
using std::cout;
using std::endl;
MyDialog::MyDialog(QWidget * parent)
{
resize(400,300);
btn = new QPushButton(this);
btn->resize(100,30);
btn->move(150,150);
btn->setText(“ok”);
QObject::connect(btn,SIGNAL(clicked),this,SLOT(showBox));
}
MyDialog::~MyDialog()
{
delete btn;
}
void MyDialog::showBox()
{
//cout<< “我被点击”<<endl;
QMessageBox::information(this, “Information”, “this is information”);
}
总结:用户点击按钮,按钮发生点击事件,事件发出clicked信号,用户实现槽函数,并绑定槽函数与信号函数。
QMessageBox类实现了很多静态函数实现弹出对话框
Information
about 关于对话框
…….看手册
案例2:
加法器
界面:文本框 + 文本框 =(按钮) 标签库
1.设计界面(*.ui,*.h)
2.main.cpp
3.pro
4.对话框
5.处理信号与槽
界面设计器设计界面并保存为frmjfq.ui
编译:uicfrmjfq.ui –o frmjfq.h
代码:
main.cpp
#include<QApplication>
#include “dlgjfq.h”
int main(int args , char ** argv)
{
QApplication app(args , argv);
DlgJFQdlg;
dlg.setVisible(true);
returnapp.exec();
}
main.pro
TEMPLATE=app
SOURCES=main.cpp dlgjfq.cpp
HEADERS=frmjfq.h dlgjfq.h
CONFIG=release qt
QT=core gui
TARGET=main
dlgjfq.h
#ifndef DLG_JFQ_H
#define DLG_JFQ_H
#include “frmjfq.h”
#include<QDialog>
class DlgJFQ :public QDialog
{
Q_OBJECT
private:
Ui_Frmjfq *ui;
public:
DlgJFQ(QWidget *parent=NULL);
~DlgJFQ();
publicslots:
void add(); //+按钮槽函数
};
#endif
dlgjfq.cpp
#include “dlgjfq.h”
DlgJFQ::DlgJFQ(QWidget * parent)
{
ui = newUi_Frmjfq;
ui->setupUi(this);
QObject::connect(ui->btnAdd,SIGNAL(clicked()),this,SLOT(add()));
}
DlgJFQ::~DlgJFQ()
{
delete ui;
}
void DlgJFQ::add()
{
//取字符串
QString strAdded=ui->txtAdded->text(); //txtAdded,txtAdd 为两个文本框的对象,在ui
QString strAdd = ui->txtAdd ->text();
//转换为整数
intia=strAdded.toInt();
intib=strAdd.toInt();
//计算和
int ic=ia+ib;
//把和转换为文本显示
ui->lblResult->setText(QString::number(ic));
}
QT 信号与槽 QT简单加法器的实现的更多相关文章
- QT信号和槽函数学习笔记
//connect 函数有4个参数 分别是 发送者 信号.接受者 ,槽 //connect(sender,signal,receiver,slot) /* * 信号和槽 * 信号 就是一个普通的函数 ...
- QT 信号与槽connect
QT 信号与槽connect QT 信号与槽connect connect函数调用几个限制 connect函数代码 QT中信号与槽的连接使用的connect函数是一个静态函数,在类QObject中定义 ...
- Qt 信号与槽
Qt信号与槽的理解 信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重 ...
- QT信号和槽
QT信号和槽 ============ 信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性.要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler) ...
- 关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)
最近由于项目的需求,一直在研究Qt.信号与槽机制是Qt的一大特色,该机制允许两者间传递参数,依次来实现对象间的通信.这个参数会分别存在于信号的参数列表和槽函数的参数列表中.需要注意的是,若将槽函数绑定 ...
- Qt信号和槽机制
概述 信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,他是QT的核心特性,也是QT差别于其他工具包的重要地方.信号和槽是QT自行定义 ...
- QT信号和槽在哪个线程执行问题
时隔四个月后的第一篇,换了个公司可以登录的博客,记录一些学习内容吧 这是看到别人写的比较好的一篇,排版有点乱 QThread的使用方法 起源 昨天不小心看到Qt开发人员( Bradley T.Hugh ...
- Qt信号与槽机制
一.信号和槽机制 信号和槽用于两个对象之间的通信,信号和槽机制是Qt的核心特征,也是Qt不同于其他开发框架的最突出的特征.在GUI编程中,当改变了一个部件时,总希望其他部件也能了解到该变化.更一般来说 ...
- [QT][转载] Qt信号和槽
From: http://blog.csdn.net/rl529014/article/details/51346955 GUI 程序除了要绘制控件,还要响应系统和用户事件,例如重绘.绘制完成.点击鼠 ...
随机推荐
- LINUX用户管理——/etc/passwd文件详解
输入vi /etc/passwd 可以查看此文件的内容 .本机内容如下: [root@localhost ~]# vi /etc/passwdroot:x:0:0:root:/root:/bin/ ...
- mysql memcache
http://blog.csdn.net/newjueqi/article/details/8350643
- vs2005编译QT4.5版本
1. 下载代码:qt-win-opensource-src-4.5.02. 设置环境变量 Add to PATH: ‘;%QTDIR%/bin’3. 输入cmd,启动到vs2005安装目录下,进入Mi ...
- CSS实现页面背景自动切换功能
From here:http://xiaomiya.iteye.com/blog/2047728 请看效果图: 完整代码如下: <!DOCTYPE HTML> <html> & ...
- Android UI ActionBar功能-自动隐藏 Action Bar
为了使ActionBar不影响Activity的布局内容,我们还可以设置ActionBar,将其设置为透明,并且让Activity是头部自动空出一个ActionBar的空间: 官方文档:http:// ...
- POJ3253 Fence Repair(贪心)
分割木板的顺序是自由的,所以每次选择两块最短的板,组合在一起,增加队列,原来两个板出队,直到队列中为空或者仅仅剩下一个板时结束.这里使用优先队列较为方便. #include<iostream&g ...
- C++隐式转换
#include <iostream> using namespace std; class A { int a; public: A(int n):a(n) { cout << ...
- C#生成ACCESS文件几点注意事项
1.bin文件夹下有没有Interop.ADOX.dll文件. 2.当前服务器有没有安装access 64位驱动,若没有,可安装AccessDatabaseEngine_X64.exe文件. 3.生成 ...
- webView的一些经验总结
部分内容再录于:http://www.360doc.com/content/14/0611/13/15210553_385676271.shtml 一. 加载资源的速度不慢,但是资源多了,就很慢 ...
- left join 和 left outer join 的区别
left join 和 left outer join 的区别 通俗的讲: A left join B 的连接的记录数与A表的记录数同 A right join ...