我有一个运行在python中的websocket服务器,对于每个新连接,将创建一个新线程并处理请求。
在主线程[Gui-thread]中,我正在初始化QApplication([])。用例是,当我处理请求时,我想等待并通过QInputDialog从用户那里获得文本响应。 每当我运行它时,都会运行一个事件循环,但未显示gui。因为可以从Gui线程本身显示所有gui元素。
我尝试了使用QSignals / slots和Pypubsub的各种方法,但是无法实现所需的功能。请提出一些想法以完成用例。伪代码是很好的理解。
下面提到的代码是我尝试过的一些示例。我在以下示例中使用线程,因为,正如我提到的那样,来自连接的每个请求都是使用分配给该连接的线程执行的。并且该线程需要QInputDialog中的文本。
提前谢谢。
下面是Websockets服务器代码,用于服务调用server_extensions函数的请求,每次收到传入请求时,我都必须显示QInputDialog。
import websockets
import asyncio
from PyQt5.QtWidgets import QInputDialog, QApplication
app = QApplication([])
async def server_extentions(websocket, path):
try:
while(True):
request = await websocket.recv()
# this is where i need to show input dialog.
text, ok = QInputDialog.getText(None, "Incoming message", request)
if ok:
response = text
else:
response = "NO REPLY"
await websocket.send(response)
except websockets.ConnectionClosed as exp:
print("connection closed.")
start_server = websockets.serve(server_extentions, '127.0.0.1', 5588)
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(start_server)
loop.run_forever()
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
----编辑-----
以下是一些一般性想法,我尝试使用pypubsub。
import threading
import pubsub.pub
from PyQt5.QtWidgets import QInputDialog, QApplication
class MainThread:
def __init__(self):
self.app = QApplication([])
pubsub.pub.subscribe(self.pub_callback, "lala")
def pub_callback(self):
print("this is Main thread's pub callback.")
QInputDialog.getText(None, "main-thread", "lala call back : ")
def start_thread(self):
self.th = threading.Thread(target=self.thread_proc)
self.th.start()
def thread_proc(self):
pubsub.pub.sendMessage("lala")
m = MainThread()
m.start_thread()
-----编辑2 -------
以下是我尝试使用QSignal进行的操作。 [检查代码中的注释,如何使用Mainthread调用函数]。
import threading
from PyQt5.QtWidgets import QInputDialog, QApplication
from PyQt5.QtCore import pyqtSignal, QObject, QThread
class TextDialog(QObject):
sig = pyqtSignal(str)
def __init__(self):
QObject.__init__(self)
def get_text(self):
print("class Thread2, showing QInputDialog.")
text, ok = QInputDialog.getText(None, "Lala", "give me some text : ")
if ok:
self.sig.emit(text)
return
self.sig.emit("NO TEXT")
return
class Thread1:
def thread_proc(self):
td = TextDialog()
td.sig.connect(self.get_text_callback)
td.moveToThread(m.main_thread)
# here i dont understand how to invoke MainThread's show_dialog with main thread. [GUI Thread]
#m.show_dialog(td)
def get_text_callback(self, txt):
print("this is get_text_callback, input : " + str(txt))
class MainThread:
def __init__(self):
self.app = QApplication([])
self.main_thread = QThread.currentThread()
def main_proc(self):
th1 = Thread1()
th = threading.Thread(target=th1.thread_proc)
th.start()
def show_dialog(self, text_dialog: TextDialog):
print("got a call to MainThread's show_dialog.")
text_dialog.get_text()
m = MainThread()
m.main_proc()
exit()
答案 0 :(得分:2)
对于这种类型的应用程序,最好实现工作线程方法。这种方法的主要思想是实现QObject,将它们移动到新线程并异步调用插槽(通过QEvents,pyqtSignals,QMetaObject::invokeMethod(...)
,import threading
from functools import partial
from PyQt5 import QtCore, QtWidgets
class TextDialog(QtCore.QObject):
sig = QtCore.pyqtSignal(str)
@QtCore.pyqtSlot()
def get_text(self):
print("class Thread2, showing QInputDialog.")
text, ok = QtWidgets.QInputDialog.getText(
None, "Lala", "give me some text : "
)
if ok:
self.sig.emit(text)
return
self.sig.emit("NO TEXT")
return
class Worker1(QtCore.QObject):
@QtCore.pyqtSlot(QtCore.QObject)
def thread_proc(self, manager):
print(
"current: {}- main: {}".format(
threading.current_thread(), threading.main_thread()
)
)
manager.td.sig.connect(self.get_text_callback)
QtCore.QTimer.singleShot(0, manager.show_dialog)
@QtCore.pyqtSlot(str)
def get_text_callback(self, txt):
print(
"current: {}- main: {}".format(
threading.current_thread(), threading.main_thread()
)
)
print("this is get_text_callback, input : %s" % (txt,))
class Manager(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.td = TextDialog()
@QtCore.pyqtSlot()
def show_dialog(self):
print("got a call to MainThread's show_dialog.")
self.td.get_text()
class Application:
def __init__(self):
print(
"current: {}- main: {}".format(
threading.current_thread(), threading.main_thread()
)
)
self.app = QtWidgets.QApplication([])
# By default if after opening a window all the windows are closed
# the application will be terminated, in this case after opening
# and closing the QInputDialog the application will be closed avoiding
# that it will be noticed that get_text_callback is called,
# to avoid the above it is deactivated behavior.
self.app.setQuitOnLastWindowClosed(False)
self.manager = Manager()
def main_proc(self):
#
self.thread = QtCore.QThread()
self.thread.start()
self.worker = Worker1()
# move the worker so that it lives in the thread that handles the QThread
self.worker.moveToThread(self.thread)
# calling function asynchronously
# will cause the function to run on the worker's thread
QtCore.QTimer.singleShot(
0, partial(self.worker.thread_proc, self.manager)
)
def run(self):
return self.app.exec_()
if __name__ == "__main__":
import sys
m = Application()
m.main_proc()
ret = m.run()
sys.exit(ret)
等),以便任务在线程中执行住了QObject。
public function __construct() {
if (Auth::user()->hasRole('administrator')) {
$route = 'admin';
} else if (Auth::user()->hasRole('company')) {
$route = 'company';
} else if (Auth::user()->hasRole('schoolowner')) {
$route = 'school';
}
}
public function index()
{
return view($route.'.person.index', compact('user'))->with('status', 'No school');
}