信号与槽

背景:

面向过程

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

函数调用:

直接调用

回调调用(低耦合)

面向对象

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

对象调用

直接调用

接口调用

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. POJ 3740 DLX

    题意:给你一个01矩阵,然后求是否存在选择一些行,使得每一列的1的个数都为1. 思路:貌似朴素的DFS也可以,加点剪枝就可以过.这里贴个DLX的模版. 推荐博客:http://www.cppblog. ...

  2. C# 分析搜索引擎url 得到搜索关键字

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. 编程内功修炼之数据结构—BTree(二)实现BTree插入、查询、删除操作

    1 package edu.algorithms.btree; import java.util.ArrayList; import java.util.List; /** * BTree类 * * ...

  4. 一张图告诉你如何优化web 性能

  5. uva 10004 Bicoloring(dfs二分染色,和hdu 4751代码差不多)

    Description In the ``Four Color Map Theorem" was proven with the assistance of a computer. This ...

  6. javascritp第十课:面向对象

    js中的函数就是对象,对象就是函数,当js中需要使用面向对象,使用js闭包模拟面向对象,当函数作为对象使用时,每个单词首字母都大写 var obj=new object();  //js中默认就是ob ...

  7. javascript第六课类型转换

    1.parseint(参数): 转换为整数,即使参数中的字符串包含字母数字混合,此方法也会自动一个一个判断和转换   parseInt(参数,进制);将参数通过几进制的方式转为数字 2.parsefl ...

  8. (转)iOS 开发,工程中混合使用 ARC 和非ARC

    [前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...

  9. BZOJ 1024 SCOI 2009 生日快乐 深搜

    题目大意:有一块蛋糕,长为X,宽为Y.如今有n个人来分这块蛋糕,还要保证每一个人分的蛋糕的面积相等.求一种分法,使得全部的蛋糕的长边与短边的比值的最大值最小. 思路:刚拿到这个题并没有什么思路.可是定 ...

  10. winform CheckedListBox实现全选/全不选

    /全选         private void button3_Click(object sender, EventArgs e)         {             for (int i ...