QAxWidget实例中的QEventLoop失败



我正在使用Windows OCX api开发基于终端的PyQt应用程序。我在QAxWidget实例中实现(调用exec) QEventLoop时遇到了麻烦。

如果我在主QApplication主循环中调用exec(),一切正常。但是,在主循环中实例化的QAxWidget的实例中调用exec(),它不会像预期的那样工作。

当exec()在代码中调用(_on_event_connect)时,错误消息显示如下

"QEventLoop:exec: instance 0x18479d8 has already called exec()"

在调用exit()的时刻,QEventLoop似乎没有运行。在此之后,应用程序将被挂起。

下面是我的代码的简化示例,它尝试调用QAxWidget方法"dynamicCall"一旦登录过程完成。它由pyQt信号/槽机制组成,从API服务器获取事件。请理解,你不能执行这段代码,因为它需要特定的api安装和注册的用户id。但我希望你能看到问题所在。

main.py

import sys
from PyQt5.QtWidgets import QApplication
from api import OpenApi
class Main():
def __init__(self):
self.api = OpenApi()
self.api.comm_connect()
# self.api.req_basic_stock_info("035420") -> if I call here, works well
if __name__ == "__main__":
app = QApplication(sys.argv)
main = Main()
sys.exit(app.exec_())

api.py

import sys
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5.QtCore import *
class OpenApi(QAxWidget):
def __init__(self):
super().__init__()
self.setControl("KHOPENAPI.KHOpenAPICtrl.1")
self.OnEventConnect.connect(self._on_event_connect)
self.OnReceiveTrData.connect(self._on_receive_tr_data)
self._qloop = QEventLoop()
def loop(self):
if not self._qloop.isRunning():
logger.info(f"-->exec")
self._qloop.exec()
else:
logger.info("exec skipped")
def unloop(self):
if self._qloop.isRunning():
logger.info("-->exit")
self._qloop.exit()
else:
logger.info(f"exit skipped")
def comm_connect(self):
self.dynamicCall("CommConnect()")
self.loop()
def comm_rq_data(self, rqname, trcode, next, screen_no):
self.dynamicCall("CommRqData(QString, QString, int, QString)", rqname, trcode, next, screen_no)
self.loop()
def _on_event_connect(self, err_code):
if err_code == 0:
logger.info("logged in")
else:
logger.info("log-in failed")
self.unloop()
# If I call this function here, QEventLoop fails

self.req_basic_stock_info("000660")    
def _on_receive_tr_data(self, screen_no, rqname, trcode, record_name, next,
unused1, unused2, unused3, unused4):
logger.info(f"OnReceivTrData: {rqname}")
self.unloop()
def req_basic_stock_info(self, code):
# I want to call this function inside instance on certain condition.
self.set_input_value("item", code)
scrno = "2000"
self.comm_rq_data("ITEM_INFO_REQ", "opt10080", "0", scrno)

输出如下:

12:42:53,54 test INFO -->exec
12:42:58,961 test INFO logged in
12:42:58,962 test INFO -->exit
12:42:58,977 test INFO -->exec
QEventLoop::exec: instance 0x35c34a0 has already called exec()
12:42:59,33 test INFO OnReceivTrData:ITEM_INFO_REQ
12:42:59,35 test INFO exit skipped

正如eyllanesc告诉我的,我更改了与assign/deassign QEventLoop相关的函数,如下所示。

def loop(self):
self._qloop = QEventLoop()
self._qloop.exec()
def unloop(self):
try:
self._qloop.exit()
except AttributeError as e:
logger.error(e)

更新恐怕这个问题还没有解决。当req_basic_stock_info函数在_on_event_connect事件上被调用时,它是成功的,但是我在另一个事件函数上调用它,它再次挂起,没有任何错误消息。调用机制没有区别。

调用exit()函数并不意味着QEventLoop可以被重用,因此会发出错误消息。在这种情况下,最好使用新的QEventLoop:

def unloop(self):
if self._qloop.isRunning():
logger.info("-->exit")
self._qloop.exit()
self._qloop = QEventLoop()
else:
logger.info(f"exit skipped")

相关内容

  • 没有找到相关文章

最新更新