問題描述
我正在為開源客戶端/服務器 4X 策略游戲 Thousand Parsec 構建 Qt 客戶端.這是一個 Google Summer of Code 項目.然而,我陷入了死胡同.基本上,客戶端通過促進客戶端/服務器通信的 C++ 協議層與服務器接口.該協議的文檔可在此處獲得.
現在我的問題是協議要求您創建虛擬 EventLoop 類的子類 (link) 在您的客戶端中.有一個示例 SimpleEventLoop 用于同一鏈接上的控制臺客戶端.我很難弄清楚如何設計我自己的事件循環子類來處理協議的事件,同時連接到 Qt 應用程序.我的研究讓我相信 QAbstractEventDispatcher 是我想使用的 Qt 類但文檔似乎很薄,我不確定我將如何做這件事.
有沒有其他人有將外部事件循環與 Qt 應用程序聯系起來的經驗?我還在 Qt 頁面上找到了這個 example 但是這不是很有幫助 - 或者至少我沒有真正理解它.
謝謝!
我最近沒有做太多的 Qt 開發,但是如果我沒記錯的話,可以調用 QApplication::processEvents()
在您自己的事件循環中(而不是通過 QApplication::exec()
)
我利用周日上午緩慢的機會試駕/了解了一些關于PyQt(Qt 的 Python 綁定)并在下面拼湊了一個概念驗證代碼.使用基于 QApplication::processEvents()
的自定義事件循環替換對 QApplication::exec()
的調用似乎可行.>
我也快速查看了simpleeventloop.cpp
和 tpclient-cpptext main.cpp
/a>.從它的外觀來看,只需在 SimpleEventLoop::runEventLoop()
的主循環中的某處添加 QApplication::processEvents()
應該沒問題.要將其添加到主循環中,我可能會替換 select() 函數的 tv
間隔/gitweb/gitweb.cgi?p=libtpproto-cpp.git;a=blob;f=tpproto/simpleeventloop.cpp;hb=ebfc08b322c552d73d34a368cca0623782f8d3f8#l106" rel="nofollines">code>r1117
與
tv.tv_sec = 0;tv.tv_usec = 10000;//每 0.01 秒運行一次 processEvents()app->processEvents();
并更改 行 89
到 void SimpleEventLoop::runEventLoop(QApplication *app)
.將您常用的 Qt 內容添加到您的客戶端實現中應該沒問題(您替換 tpclient-cpptext main.cpp
)
不過看起來像黑客.我可能會從這樣的事情開始.我認為你的想法包裝 TPSocket
和 Qt 各自概念中的計時器,以便使用 QAbstractEventDispatcher
到 QEventLoop
是更好的長期解決方案.然后,您的 runEventLoop()
只需調用 QApplication::exec()
就足夠了.但我以前從未使用過 QAbstractEventDispatcher
,所以請采納我的意見.
導入系統導入時間從 PyQt4 導入 QtGui從 PyQt4 導入 QtCore# 全局變量用作通知我的快速而骯臟的方式# MainWindow 已經退出的主事件循環APP_RUNNING = 假類 SampleMainWindow(QtGui.QMainWindow):def __init__(self, parent=None):QtGui.QMainWindow.__init__(self)全球APP_RUNNINGAPP_RUNNING = 真# 主窗口self.setGeometry(300, 300, 250, 150)self.setWindowTitle('測試')self.statusBar().showMessage('Ready')# 退出動作(假設退出圖標來自# http://upload.wikimedia.org/wikipedia/commons/b/bc/Exit.png# 保存為 Exit.png 與此文件在同一文件夾中)exitAction = QtGui.QAction(QtGui.QIcon('Exit.png'),'出口',自己)exitAction.setShortcut('Ctrl+Q')exitAction.setStatusTip('退出應用程序')self.connect(exitAction),QtCore.SIGNAL('觸發()'),QtCore.SLOT('close()'))# 主菜單菜單欄 = self.menuBar()fileMenu = menubar.addMenu('&File')fileMenu.addAction(exitAction)# 工具欄self.toolbar = self.addToolBar('退出')self.toolbar.addAction(exitAction)# 文本編輯器textEdit = QtGui.QTextEdit()self.setCentralWidget(textEdit)#工具提示textEdit.setToolTip('輸入一些文字')QtGui.QToolTip.setFont(QtGui.QFont('English', 12))def closeEvent(self, event):回復 = QtGui.QMessageBox.question(self,'信息',你確定嗎?",QtGui.QMessageBox.Yes,QtGui.QMessageBox.No)如果回復 == QtGui.QMessageBox.Yes:事件.接受()全球APP_RUNNINGAPP_RUNNING = 假別的:事件.忽略()# 主程序app = QtGui.QApplication(sys.argv)testWindow = SampleMainWindow()testWindow.show()# 運行自定義事件循環而不是 app.exec_()當 APP_RUNNING 時:app.processEvents()# sleep 以防止我的偉大的"事件循環消耗 100% cpu時間.睡眠(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 結合的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!