• 3401阅读
  • 16回复

新人求教一个关于信号和槽的问题 [复制链接]

上一主题 下一主题
离线gy19920615
 

只看楼主 倒序阅读 楼主  发表于: 2017-12-25
      我想问的主题是 如何用信号和槽把变量显示界面上。
     我写的线程函数里面对读取的数据进行了处理,并显示到界面上,之前用指针调用UI 控件的方法会崩溃(主线程才能调用UI 界面),现在用信号和槽的方法处理,可是新人实在太笨拙,不知道信号和槽怎么处理这种情况,我是这么写的:
      头文件在类MainWindow 里声明了信号 signal:voidvalueChanged(double);
      声明了槽 private slots:  void setValueol(double);
      在线程函数里声明了变量c,存储电压值,连接信号和槽:
              c=(float)(256*data[1]+data[0]-512)*1.5/1000;          
              connect(c,SIGNAL(valueChanged(doubele))),this,SLOT(setValueVol(double))); (疑问:c可以作为object1吗? Object2可以写this 吗?信号是如何触发槽的~)

      槽函数:void MainWindow::setValueVol (double c)
                     {
                      QString tempStr;
                      ui->TextBrowser ->setText(temp.setNum(c));
                      }

以上,代码肯定是不能编译通过的,但是我不太懂信号和槽,看了很多资料没有讲解我这种情况的,多半的信号是按钮类型的,请问变量发生改变可以作为信号吗,怎么处理
离线zxwmail

只看该作者 1楼 发表于: 2017-12-25
直接赋值不行么?不是更简单
ui->TextBrowser ->setText(temp.setNum(c));
离线gy19920615

只看该作者 2楼 发表于: 2017-12-25
这个线程函数是静态函数,不能赋值的
离线yanwuyue

只看该作者 3楼 发表于: 2017-12-26
object是类class,c是double,肯定不能这么创建,
setText就是槽函数
思路1:直接使用使用信号发射QMetaObject::invokeMethod
QMetaObject::invokeMethod(通过MainWindow指针 获取TextBrowser指针,"setText",Q_ARG(QString ,tempStr));
思路2:通过MainWindow中转信号,
MainWindow中创建信号valueChanged,如
connect(this,SIGNAL(valueChanged(doubele))),ui->TextBrowser ,SLOT(setValueVol(double)));

使用时emit (MainWindow指针)->valueChanged(tempStr);
离线gy19920615

只看该作者 4楼 发表于: 2017-12-29
回 yanwuyue 的帖子
yanwuyue:object是类class,c是double,肯定不能这么创建,
setText就是槽函数
思路1:直接使用使用信号发射QMetaObject::invokeMethod
QMetaObject::invokeMethod(通过MainWindow指针 获取TextBrowser指针,"setText",Q_ARG(QString ,tempStr));
思路2:通过MainWindow中转信号,
..... .. (2017-12-26 20:27) 

emit (MainWindow *)UserData->valueChanged(c1);编译不通过,UserData是LPVOID类型的
离线yanwuyue

只看该作者 5楼 发表于: 2017-12-29
UserData是什么你问我,代码都没一段,编译错误信息也没有,我哪知道你写的什么鬼,你在搞笑吗

离线alexltr

只看该作者 6楼 发表于: 2017-12-31
1. 信号和槽的基本概念没有搞清楚,建议看看文档里【Signals & Slots】这一章节,
    慢慢理解,基本的用法应该是不难的。

2. 不知道你的实际代码是怎样的,但从你贴出的几行代码看,就有多处拼写错误。
    干这个活还是要严谨一点,要不然出现一些莫名其妙的错误会耗费你很多时间。
     即使发帖提问也应该一样,要不然别人看不懂你的代码, 怎么帮你?





我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
离线gy19920615

只看该作者 7楼 发表于: 2018-01-02
回 alexltr 的帖子
alexltr:1. 信号和槽的基本概念没有搞清楚,建议看看文档里【Signals & Slots】这一章节,
    慢慢理解,基本的用法应该是不难的。
2. 不知道你的实际代码是怎样的,但从你贴出的几行代码看,就有多处拼写错误。
    干这个活还是要严谨一 .. (2017-12-31 09:20) 

离线ab13402364

只看该作者 8楼 发表于: 2018-01-04
说一种我常用的方法吧,主要分四步:
一、在线程类中定义一个信号(如 dataShow(),可传参数,也可为空);
二、在定义线程对象的父类中定义一个相应的槽函数,槽函数实现界面显示相关操作;
三、在定义线程对象的父类中connect刚刚定义的信号和槽函数(注:信号和槽函数不在一个线程);
四、在线程类中的线程函数中发送刚刚定义的信号。(如 emit dataShow(),定义的时候有参数还得填写相应的参数)
离线勤为径也

只看该作者 9楼 发表于: 2018-01-04
回 alexltr 的帖子
alexltr:1. 信号和槽的基本概念没有搞清楚,建议看看文档里【Signals & Slots】这一章节,
    慢慢理解,基本的用法应该是不难的。
2. 不知道你的实际代码是怎样的,但从你贴出的几行代码看,就有多处拼写错误。
    干这个活还是要严谨一 .. (2017-12-31 09:20) 

版主,帮忙看看我的问题:《线程内使用emit(),内存泄漏十分严重,哪里出了问题?有源代码(http://www.qtcn.org/bbs/read-htm-tid-65443.html)》
离线gy19920615

只看该作者 10楼 发表于: 2018-01-04
回 ab13402364 的帖子
ab13402364:说一种我常用的方法吧,主要分四步:
一、在线程类中定义一个信号(如 dataShow(),可传参数,也可为空);
二、在定义线程对象的父类中定义一个相应的槽函数,槽函数实现界面显示相关操作;
三、在定义线程对象的父类中connect刚刚定义的信号和槽函数(注:信号和槽函数不在一个线程) .. (2018-01-04 09:40) 

谢谢回复,用了你教我的方法,
1.在MainWIdow类定义了信号datashow(double)和槽setvalue(double);
2.在窗口初始化函数里创建textBrowser类型的对象NUMERIC_C1。连接信号和槽,connecet(NUMERIC_C1,SIGNAI(datashow(double)),this,SLOT(setvalue(double)));

在静态函数里发送信号
static DWORD __stdcall PDOtest(DWORD EvenID,LPVOID pBuf ,DWORD buflen, LPVOID userdata)
{
  ....;
  c1=(float)(....);
  emit datashow(c1); //发送c1;
}
编译出错, ‘datashow’ was ot declared in this scope;
就是说对信号的定义不对吧,在静态函数里调用的话要在哪定义呢?
离线yanwuyue

只看该作者 11楼 发表于: 2018-01-04
回 gy19920615 的帖子
gy19920615:谢谢回复,用了你教我的方法,
1.在MainWIdow类定义了信号datashow(double)和槽setvalue(double);
2.在窗口初始化函数里创建textBrowser类型的对象NUMERIC_C1。连接信号和槽,connecet(NUMERIC_C1,SIGNAI(datashow(double)),this,SLOT(setvalue(double)));
....... (2018-01-04 11:15) 

错误1:
datashow是MainWIdow的信号,你静态函数里面肯定没有啦
emit datashow(c1); 就是 emit this->datashow(c1);
静态函数this不存在,肯定无法编译
你必须 emit (MainWIdow指针)->datashow(c1);

错误2:QtextBrowser根本没有datashow的信号,所以
connecet(NUMERIC_C1,SIGNAI(datashow(double)),this,SLOT(setvalue(double)));
也是编译不过去

SIGNAI就是发送,SLOT就是接收,你完全都是在乱写



离线ab13402364

只看该作者 12楼 发表于: 2018-01-04
一个简单的例程,你看看是否有用吧:
.h文件


.cpp文件


参数根据自己需求修改
离线gy19920615

只看该作者 13楼 发表于: 2018-01-04
回 yanwuyue 的帖子
yanwuyue:错误1:
datashow是MainWIdow的信号,你静态函数里面肯定没有啦
emit datashow(c1); 就是 emit this->datashow(c1);
静态函数this不存在,肯定无法编译
....... (2018-01-04 12:11) 

第一个错误我明白了,那请问我应该发送什么信号给textbrowser?
离线gy19920615

只看该作者 14楼 发表于: 2018-01-06
回 ab13402364 的帖子
ab13402364:一个简单的例程,你看看是否有用吧:
.h文件
[图片]
.cpp文件
....... (2018-01-04 15:05) 

很有用,谢谢,但是我不知道textbrowser应该接收的信号怎么写,在哪里可以查到各种控件和信号的说明吗
离线ab13402364

只看该作者 15楼 发表于: 2018-01-08
回 gy19920615 的帖子
gy19920615:很有用,谢谢,但是我不知道textbrowser应该接收的信号怎么写,在哪里可以查到各种控件和信号的说明吗 (2018-01-06 13:18) 

就在槽函数里面实现你需要实现的功能就行了啊,就是需要显示的数据显示在textbrowser控件中就行了,qtcreator开发工具里面的左侧有个帮助文档,点击进去搜索这个控件的类名就会有相应的说明
离线gy19920615

只看该作者 16楼 发表于: 2018-01-25
老哥,我仿照你教我的方式做了,编译能过,在主界面点开始通信,然后就崩溃了。已经证明能读到CAN发过来的数据,您看看我的程序:
.h文件,声明了信号和槽
signals:
    DataShow(double c);
private slots:
   void setValueVol(double);

.c文件,将信号和槽连接了起来:
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),ui(new UI::MainWindow)
{
ui->setupUi(this);
.....
connect(this,SIGNAL(DataShow(double)),this,SLOT(setValueVol(double)));
....
}

串口初始化函数里面有一个设置事件回调函数:
    ZCOMA_SetEventCallback(hdChannel, PDoTest, NULL, 0,0);
该函数来厂家提供的函数库文件,作用是一定时间周期调用一次回调函数。
重点来了,回调函数是一个静态函数,在里面读取CAN发送的数据,并显示到主界面上:
static DWORD __stdcall PDoTest(DWORD EventID, LPVOID pBuf, DWORD BufLen, LPVOID UserData)
{
...
ManWindow * pUse = (MainWindow *)UserData;
c=(float)(data[1]+data[2])/1000;
emit pUse->DataShow(c);      
}
槽函数如下:
MainWindow::setValueVol(double)
{
QString temStr;
ui->NUMERIC_C->setText(tempStr.setNum(c));
}
      已经验证过了如果把emit pUse->DataShow(c) 这句话放在别的函数里面就能成功的在界面上显示c的数值,放到 static DWORD __stdcall PDoTest(DWORD EventID, LPVOID pBuf, DWORD BufLen, LPVOID UserData)这个函数里面就崩溃,请问到底是什么原因呢?

快速回复
限100 字节
 
上一个 下一个