У меня есть сервер веб-сокетов, работающий на python, и для каждого нового соединения будет создаваться новый поток, и запросы будут обслуживаться.
В основном потоке [Gui-thread] я инициализирую QApplication ([]). случай использования, когда я обрабатываю запрос, я хотел подождать и получить текстовый ответ от пользователя через QInputDialog.
когда я запускаю его, запускается цикл обработки событий, но он не показывает графический интерфейс. потому что все элементы графического интерфейса могут отображаться из самого Gui-потока.
Я пробовал разные подходы, используя QSignals / slots и Pypubsub, но не смог добиться того, что требуется. пожалуйста, предложите некоторую идею, чтобы закончить вариант использования. псевдокод приветствуется.
Ниже приведен код, который я попробовал. Я использую поток в приведенных ниже примерах, потому что, как я уже упоминал, каждый запрос от соединения выполняется с потоком, назначенным для соединения. и текст из QInputDialog требуется потоком.
Заранее спасибо.
ниже приведен код сервера websockets, который обслуживает запрос, вызывающий функцию server_extentions, я должен показывать 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()