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,可视化,信号与槽)