问题描述
我正在为开放源码的客户端/服务器4X策略游戏构建Qt客户端。这是Google夏季代码项目。不过,我陷入僵局。基本上,客户端通过C ++协议层与服务器进行接口,便于客户端/服务器通信。该协议文档可从获得。现在我的问题是协议要求您创建虚拟EventLoop类的子类()。有一个SimpleEventLoop用于同一链接上的控制台客户端的示例。我很难弄清楚如何设计自己的事件循环子类来处理协议的事件同时挂钩到Qt应用程序。我的研究使我相信是我要使用的Qt类,但文档似乎很苗条,我不知道我会怎么做这样做。
有没有人有其他外部事件循环与Qt应用程序链接的经验?我还在Qt页面上找到了这个,但它不是很有帮助 - 或至少我没有真正理解它。
谢谢!
我最近没有做太多的Qt开发,但如果我记得正确,可以调用在你自己的事件循环中(而不是通过)
编辑:我曾经用过一个缓慢的星期天上午的机会来测试/学习一些关于(Python绑定对于Qt),并将下面的概念验证码拼凑在一起。使用基于 QApplication :: processEvents()
的自定义事件循环将呼叫替换为 QApplication :: exec()
em>似乎可以正常工作。
我也快速查看了和。从 SimpleEventLoop :: runEventLoop()的主循环中的某个地方添加
。要将其添加到主循环中,我可能会将 QApplication :: processEvents()
tv
间隔替换为与
tv.tv_sec = 0;
tv.tv_usec = 10000; //每0.01秒运行一次processEvents()
app-> processEvents();
并更改到 void SimpleEventLoop :: runEventLoop(QApplication * app)
。将您常用的Qt东西添加到您的客户端实施中应该不错(您更换 tpclient-cpptext main.cpp
)
看起来像一个黑客,但是。我可能会从这样开始,开始。我认为你的想法包括和Qt各自概念中的计时器,以便将它们与到是更好的长期解决方案。那么你的 runEventLoop()
只需调用 QApplication :: exec()
即可。但是我以前从未使用过 QAbstractEventDispatcher
,所以我的意见是什么。
import sys
import time
从PyQt4导入QtGui
从PyQt4导入QtCore
#全局变量用作一个快速而肮脏的方式通知我的
#主事件循环,MainWindow已经退出
APP_RUNNING = False
class SampleMainWindow(QtGui.QMainWindow):
def __init __(self,parent =无)
QtGui.QMainWindow .__ init __(self)
全局APP_RUNNING
APP_RUNNING = True
#主窗口
self.setGeometry(300,
self.setWindowTitle('Test')
self.statusBar()。showMessage('Ready')
#退出操作(假设退出图标
#http://upload.wikimedia.org/wikipedia/commons/b/bc/Exit.png
#保存为Exit.png与该文件相同的文件夹)
出口A ction = QtGui.QAction(QtGui.QIcon('Exit.png')
,'Exit'
,self)
exitAction.setShortcut('Ctrl + Q')
exitAction .setStatusTip('exit application')
self.connect(exitAction
,QtCore.SIGNAL('triggered()')
,QtCore.SLOT('close()'))
#主菜单
menubar = self.menuBar()
fileMenu = menubar.addMenu('& File')
fileMenu.addAction(exitAction)
#toolbar
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)
#文本编辑器
textEdit = QtGui.QTextEdit()
self.setCentralWidget(textEdit)
#tool tip
textEdit.setToolTip('输入一些文本')
QtGui.QToolTip.setFont (QtGui.QFont('English',12))
def closeEvent(self,event):
reply = QtGui.QMessageBox.question(self
,'Message'
,你确定吗?
,QtGui.QMessageBox.Yes
,QtGui.QMessageBox.No)
如果回复== QtGui.QMessageBox.Yes:
event.accept()
全局APP_RUNNING
APP_RUNNING =假
else:
event.ignore()
#主程序
app = QtGui.QApplication(sys.argv)
testWindow = SampleMainWindow()
testWindow.show()
#运行自定义事件循环而不是app.exec_()
而APP_RUNNING:
app.processEvents()
#sleep以防止我的伟大事件循环吃100%cpu
time.sleep(0.01)
I'm building a Qt client for the open-source client/server 4X strategy game Thousand Parsec. This a Google Summer of Code project. I'm however stuck at a dead end. Basically, the client interfaces with the server via a C++ protocol layer that facilitates client/server communication. The protocol's documentation is available here.
Now my problem is that the protocol requires you to create a subclass of the virtual EventLoop class (link) in your client. There is an example SimpleEventLoop used for console clients on the same link. I'm having difficulty figuring out how I can design my own event loop subclass that handles the protocol's events while hooking into the Qt application at the same time. My research has lead me to believe QAbstractEventDispatcher is the Qt class I want to use but the documentation seems pretty slim and I'm not exactly sure how I would go about doing this.
Does anyone else have experience linking external event loops with a Qt application? I've also found this example on the Qt page but it wasn't very helpful - or at least I didn't really understand it.
Thanks!
I haven't done too much Qt development recently, but if I remember correctly, you can call QApplication::processEvents()
within your own event loop (instead of starting the Qt main loop through QApplication::exec()
)
Edit: I have used the opportunity of a slow Sunday morning to test-drive / learn something about PyQt (Python bindings for Qt) and cobbled together a proof-of-concept code below. Replacing the call to QApplication::exec()
with a custom event loop based on QApplication::processEvents()
seems to work.
I have also quickly looked at simpleeventloop.cpp
and tpclient-cpptext main.cpp
. From the looks of it, it shoud be fine to just add QApplication::processEvents()
somewhere in the main loop of SimpleEventLoop::runEventLoop()
. To add it to the main loop, I would probably replace the tv
interval for the select()
function in lines 106
through 117
with
tv.tv_sec = 0;
tv.tv_usec = 10000; // run processEvents() every 0.01 seconds
app->processEvents();
and change the signature in line 89
to void SimpleEventLoop::runEventLoop(QApplication *app)
. It should than be fine to add your usual Qt stuff to your implementation of the client (your replacement of tpclient-cpptext main.cpp
)
Looks like a hack, though. I would probably start with something like this to get started. I think that your idea of wrapping TPSocket
and the timer within Qt's respective concepts in order to forward them with the QAbstractEventDispatcher
to the QEventLoop
is the better long-term solution. It should then be sufficient that your runEventLoop()
simply calls QApplication::exec()
. But I have never used QAbstractEventDispatcher
before, so take my comments for what they are.
import sys
import time
from PyQt4 import QtGui
from PyQt4 import QtCore
# Global variable used as a quick and dirty way to notify my
# main event loop that the MainWindow has been exited
APP_RUNNING = False
class SampleMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self)
global APP_RUNNING
APP_RUNNING = True
# main window
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Test')
self.statusBar().showMessage('Ready')
# exit action (assumes that the exit icon from
# http://upload.wikimedia.org/wikipedia/commons/b/bc/Exit.png
# is saved as Exit.png in the same folder as this file)
exitAction = QtGui.QAction(QtGui.QIcon('Exit.png')
,'Exit'
,self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
self.connect(exitAction
,QtCore.SIGNAL('triggered()')
,QtCore.SLOT('close()'))
# main menu
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
# toolbar
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)
# text editor
textEdit = QtGui.QTextEdit()
self.setCentralWidget(textEdit)
#tool tip
textEdit.setToolTip('Enter some text')
QtGui.QToolTip.setFont(QtGui.QFont('English', 12))
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self
,'Message'
,"Are you sure?"
,QtGui.QMessageBox.Yes
,QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
global APP_RUNNING
APP_RUNNING = False
else:
event.ignore()
# main program
app = QtGui.QApplication(sys.argv)
testWindow = SampleMainWindow()
testWindow.show()
# run custom event loop instead of app.exec_()
while APP_RUNNING:
app.processEvents()
# sleep to prevent that my "great" event loop eats 100% cpu
time.sleep(0.01)
这篇关于组合Qt的外部事件循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!