问题是关于将现有的基于pthread的基于C,pthread的应用程序与QT GUI进行接口。这似乎是一个简单的任务,但是,当我搜索(在互联网上和通过试验&错误),我没有找到一个可接受的解决方案。将数据和事件从pthread发送到QT QApplication使用QLabel和QImage
现在,该应用程序大量使用了预先存在的C库,我无法修改其代码。
基本上,预先存在的库实现了一个循环,它以周期性的方式调用一些函数(使用一些数据)。只有那些我能够定义的函数(函数指针)。
在一个完整的应用中,预先存在的库环以下述方式调用这些函数(又名“初始化”,“过程”和“UNINIT”):
init(f);
process(f);
process(f);
...
process(f);
...
process(f);
uninit(f);
的“f”为一个结构,允许保持调用呼叫的相关数据,“init”和“uninint”函数用于设置和销毁由f分配的数据。
现在,process()函数进行了一些计算,最后的结果是一个矩阵,我想在QT GUI中以图像的形式显示它(就像它获得的那样)。
但是,QT GUI有自己的阻塞事件循环,又名myApp.exec()。因此,为了达到这个目的,我在我的“init”函数中创建了一个新线程(pthread),它将首先用相关数据填充“f”字段,然后输入myApp.exec()循环。 myApp是一个简单的QApplication,包含一个QLabel,显示一个QPixmap,由QImage构建,我可以用计算的数据填充它的“bits()”数据(这里使用一些不相关的映射)。然后,“process”函数进行连续的计算,更新QImage的“bits”数据(“bits”指针通过f结构已知),然后强制GUI自行更新。
这里有一些代码段:
init(f){
...
pthread_create(&(f->qt_tid),NULL,&qtimgdisplay_main_thread,f);
...
}
process(f){
...
do_computation();
do_ update(f->bits);
f->myLabel->repaint();
...
}
static void *qtimgdisplay_main_thread(void *arg){
FStructure *f = (FStructure *)arg;
char arg0[] = "programName";
char arg1[] = "arg";
char arg2[] = "another arg";
char* argv[] = { &arg0[0], &arg1[0], &arg2[0], NULL };
int argc = (int)(sizeof(argv)/sizeof(argv[0])) - 1;
f->myApp = new QApplication(argc, &argv[0]);
//we create a image
QImage image(f->winwidth,f->winheight,QImage::Format_RGB32);
f->bits=image.bits(); //pointer to the underlying data image
f->myLabel=new QLabel();
f->myLabel->setPixmap(QPixmap::fromImage(image));
f->myLabel->show();
f->myApp->exec();
return NULL;
}
虽然有些工作(execpts一些随机段错误),与溶液中的问题是,它(正确地)显示:
的QPixmap:不是可以安全地在GUI线程之外使用像素映射
这是完全正确的,因为QWidgets不可重入。因此,我尝试以异步的方式(我仍然不得不想象如何从我的进程()发出一个信号到QLabel myLabel)发送一个Repaint流程“:
f->myLabel->repaint();
有:
f->myApp->postEvent(f->myLabel,new QPaintEvent(f->myLabel->rect()));
灾难性结果是QT GUI不更新自身;更多的,控制台显示:
了QPainter ::开始:小工具画只能作为开始的的paintEvent
结果最后,我想用一些“聪明”(即我发现这里更换同上面的行: http://www.qtforum.org/article/18253/qpaintevent-problem-in-qt4.html),即:
QPaintEvent *pe = new QPaintEvent(f->myLabel->rect());
f->myLabel->setAttribute(Qt::WA_WState_InPaintEvent, true);
f->myApp->sendEvent(s->myLabel,f->myLabel->rect());
f->myLabel->setAttribute(Qt::WA_WState_InPaintEvent, false);
的梦幻般的结果是,它甚至没有编译:
错误:呼叫没有匹配函数 '的QApplication ::的SendEvent(QLabel * &,查阅QRect)'
我迷路了。请有人帮忙吗?
这些是我考虑一些可能的解决方案:
1)使qtimgdisplay_main_thread一个线程的QThread,而不是并行线程的线程,虽然我不知道这将是任何帮助;
2)试图从我的“进程”发出一些信号到f-> myApp或f-> myLabel,但我不知道如何做到这一点,因为“process”运行在非QThread(和有没有办法访问父线程)
3)创建和销毁一个新的QApplication,与所有关联的QLabel和QImage内的“过程”,但这只是在正常情况下做的压倒性和白痴。
感谢您阅读所有这些内容。如果可能,请尝试通过代码(而不是其他文档)提供给我一个提示。
编辑:看来,如果我使用:的
f->myLabel->update();
代替:
f->myLabel->repaint();
在我的 “过程”。
任何人都可以证实这是正确的解决方案吗?