16,816
社区成员




// 主线程(UI线程) 事件循环(eventloop)
while(true)
{
msg = getmessage(timeout) // 这里就是阻塞的,直到有消息或超时
if(msg)
{
processMsg(msg); // msg 可能是 窗口创建,鼠标移动,鼠标按下 ,计时器超时等等等。。。
// 于是processMsg内部就走到你的mouseMoveEvent,mousePressEvent,timerEvent等等等等
}
//...
if(exit_flag) //程序需要退出
{
break;
}
}
至于定时器的做法,有很多方式,如果自己简单实现下的话,可以在上面写到的msg这个数据结构中加个时间戳信息,如果时间还未到,就不进行处理。
当然这还需要对getmessage这个消费者函数进行良好的设计,包括其消息队列的设计,简单点的话:
msg getmessage(int timeout)
{
//获取系统消息,依赖平台api,获得平台相关特性的消息,比如窗口创建,鼠标移动,鼠标按下 等等等等
msg = PeekMessage(....)
if(msg)
{
//...
//...
return msg;
}
//获取自定义的其他事件
msg = getFirstMsgFromCustomList();
if(msg.timestamp > now)
{
//还未超时,则重新放回后面
appendMsgToList();
//然后取下一个: msg = getFirstMsgFromList();
//当然我这只是随便举的一个最简单的实现例子
//真正好的实现,应该设计好的消息队列,比如时间轮
//...
}
//...
//...
}
设置定时器时,就只要往自己设计的CustomList中放入设置好timestamp的msg就可以了。当然定时器的精度就取决于传给getmessage的timeout的值了。
至于其他线程如何与主线程通信,也还是一样的,往主线程的CustomList放入msg就可以了。
再给你理一下:
主线程永远只在app.exec(...) 这个函数中,不会退出,exec内部就是一个无限循环,不断消费msg(或者说event,或者说signal)。每拿出来一个,就往对应的的onMsg(onEvent,slots)派送(即调用之)。
你如果还理解不了,你就随便找个你认为是在主线程中跑的代码,就比如说你重载了QWidget::mousePressEvent(QMouseEvent *event) 好了,这个函数在哪里被调用的,分析下当前的调用堆栈,代码为什么会跑去那里?
调用堆栈一直往上追溯,答案一定就是QApplication::exec() [/quote]
其实我想的是。我可能问错了。是自定义的while循环会造成界面假死,但是QApplication::exec() 的循环却不会,这是什么机制?另外,往主线程的CustomList放入msg就可以了,这个是如何实现的 ,因为对主线程加锁的话不是会造成资源竞争吗?相互争夺锁资源不是会造成界面假死吗?
// 主线程(UI线程) 事件循环(eventloop)
while(true)
{
msg = getmessage(timeout) // 这里就是阻塞的,直到有消息或超时
if(msg)
{
processMsg(msg); // msg 可能是 窗口创建,鼠标移动,鼠标按下 ,计时器超时等等等。。。
// 于是processMsg内部就走到你的mouseMoveEvent,mousePressEvent,timerEvent等等等等
}
//...
if(exit_flag) //程序需要退出
{
break;
}
}
至于定时器的做法,有很多方式,如果自己简单实现下的话,可以在上面写到的msg这个数据结构中加个时间戳信息,如果时间还未到,就不进行处理。
当然这还需要对getmessage这个消费者函数进行良好的设计,包括其消息队列的设计,简单点的话:
msg getmessage(int timeout)
{
//获取系统消息,依赖平台api,获得平台相关特性的消息,比如窗口创建,鼠标移动,鼠标按下 等等等等
msg = PeekMessage(....)
if(msg)
{
//...
//...
return msg;
}
//获取自定义的其他事件
msg = getFirstMsgFromCustomList();
if(msg.timestamp > now)
{
//还未超时,则重新放回后面
appendMsgToList();
//然后取下一个: msg = getFirstMsgFromList();
//当然我这只是随便举的一个最简单的实现例子
//真正好的实现,应该设计好的消息队列,比如时间轮
//...
}
//...
//...
}
设置定时器时,就只要往自己设计的CustomList中放入设置好timestamp的msg就可以了。当然定时器的精度就取决于传给getmessage的timeout的值了。
至于其他线程如何与主线程通信,也还是一样的,往主线程的CustomList放入msg就可以了。
再给你理一下:
主线程永远只在app.exec(...) 这个函数中,不会退出,exec内部就是一个无限循环,不断消费msg(或者说event,或者说signal)。每拿出来一个,就往对应的的onMsg(onEvent,slots)派送(即调用之)。
你如果还理解不了,你就随便找个你认为是在主线程中跑的代码,就比如说你重载了QWidget::mousePressEvent(QMouseEvent *event) 好了,这个函数在哪里被调用的,分析下当前的调用堆栈,代码为什么会跑去那里?
调用堆栈一直往上追溯,答案一定就是QApplication::exec()