信号与槽

背景:

面向过程

模块之间低耦合设计(高内聚)。

函数调用:

直接调用

回调调用(低耦合)

面向对象

模块之间低耦合设计(高内聚)

对象调用

直接调用

接口调用

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简单加法器的实现的更多相关文章

  1. QT信号和槽函数学习笔记

    //connect 函数有4个参数 分别是 发送者 信号.接受者 ,槽 //connect(sender,signal,receiver,slot) /* * 信号和槽 * 信号 就是一个普通的函数 ...

  2. QT 信号与槽connect

    QT 信号与槽connect QT 信号与槽connect connect函数调用几个限制 connect函数代码 QT中信号与槽的连接使用的connect函数是一个静态函数,在类QObject中定义 ...

  3. Qt 信号与槽

    Qt信号与槽的理解 信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重 ...

  4. QT信号和槽

    QT信号和槽 ============ 信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性.要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler) ...

  5. 关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)

    最近由于项目的需求,一直在研究Qt.信号与槽机制是Qt的一大特色,该机制允许两者间传递参数,依次来实现对象间的通信.这个参数会分别存在于信号的参数列表和槽函数的参数列表中.需要注意的是,若将槽函数绑定 ...

  6. Qt信号和槽机制

    概述 信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,他是QT的核心特性,也是QT差别于其他工具包的重要地方.信号和槽是QT自行定义 ...

  7. QT信号和槽在哪个线程执行问题

    时隔四个月后的第一篇,换了个公司可以登录的博客,记录一些学习内容吧 这是看到别人写的比较好的一篇,排版有点乱 QThread的使用方法 起源 昨天不小心看到Qt开发人员( Bradley T.Hugh ...

  8. Qt信号与槽机制

    一.信号和槽机制 信号和槽用于两个对象之间的通信,信号和槽机制是Qt的核心特征,也是Qt不同于其他开发框架的最突出的特征.在GUI编程中,当改变了一个部件时,总希望其他部件也能了解到该变化.更一般来说 ...

  9. [QT][转载] Qt信号和槽

    From: http://blog.csdn.net/rl529014/article/details/51346955 GUI 程序除了要绘制控件,还要响应系统和用户事件,例如重绘.绘制完成.点击鼠 ...

随机推荐

  1. ORACLE RAC中的oc4j和gsd资源以及RAC相关的进程

    1.RAC相比单实例数据库多出的进程: LMS - Gobal Cache Service Process 全局缓存服务进程 LMD - Global Enqueue Service Daemon 全 ...

  2. Codeforces 306B

    #include <cstdio> #include <algorithm> #include <cstring> #include <cstdlib> ...

  3. JProfiler解决Java服务器的性能跟踪

    转自:http://www.blogjava.net/anymobile/articles/28248.html

  4. Android手机自带内部存储路径的获取 (转)

    转自:http://my.oschina.net/liucundong/blog/288183 我有一台中兴的Android手机,型号是 ZTE U930HD,手机没有插入外置SD卡(也就是Micro ...

  5. 练习3.20 a 将中缀表达式转换为后缀表达式

    //将中缀表达式转换为后缀表达式 int main() { ; ]={,,,,,,,}; char tmp; PtrToStack s; s = CreateStack( MaxSize ); ) { ...

  6. ios 后台模式

    1.在后台可以继续播放音频 To play sound in the background, make sure to add the following to the Info.plist file ...

  7. Productivity Improvements for the Entity Framework(实体框架设计)【转】

    Background We’ve been hearing a lot of good feedback on the recently released update to the Entity F ...

  8. C#核编之一个简单的C#程序

    构建一个简单的C#应用程序需要注意一下几点: 1.C#要求所有的程序逻辑都包含在一个类型定义中       --->这里的类型指的是(类,接口,结构,枚举,委托中的一个或多个) 2.与其他语言不 ...

  9. My SQL和LINQ 实现ROW_NUMBER() OVER以及Fatal error encountered during command execution

    Oracle 和SQL server都有ROW_NUMBER() OVER这个功能函数,主要用于分组排序,而MySQL 却没有 SELECT * FROM (SELECT ROW_NUMBER() O ...

  10. & 和 && 区别

    java中&和&&的区别,&和&&虽然都是逻辑运算符,都是判断两边为真,则语句成立,但是在运行的时候,还是有差别的,下面举例来说明. java中& ...