在python运行时从GUI向线程传递数据

在python运行时从GUI向线程传递数据,python,multithreading,pyqt,pyqt5,python-3.6,Python,Multithreading,Pyqt,Pyqt5,Python 3.6,我正在尝试构建一个小型python应用程序,其中一个简单的Web服务器在后台运行,您可以使用GUI发送不同的消息 我使用的是PyQt5和Python3.6,我已经成功地将数据从工作线程传递到GUI,但我不知道如何以另一种方式实现 以下是我的代码框架: 主窗口: class Ui_MainWindow(object): def __init__(self): super().__init__() self.input = True # 1

我正在尝试构建一个小型python应用程序,其中一个简单的Web服务器在后台运行,您可以使用GUI发送不同的消息

我使用的是PyQt5和Python3.6,我已经成功地将数据从工作线程传递到GUI,但我不知道如何以另一种方式实现

以下是我的代码框架:

主窗口:

class Ui_MainWindow(object):
    def __init__(self):
        super().__init__()

        self.input = True
        # 1 - create Worker and Thread inside the Form
        self.obj = WebServer.WebServer(self.input)  # no parent!
        self.thread = QtCore.QThread()  # no parent!
        # 2 - Connect Worker`s Signals to Form method slots to post data.
        self.obj.dataReady.connect(self.onDataReady)
        # 3 - Move the Worker object to the Thread object
        self.obj.moveToThread(self.thread)
        # 4 - Connect Worker Signals to the Thread slots
        self.obj.finished.connect(self.thread.quit)
        # 5 - Connect Thread started signal to Worker operational slot method
        self.thread.started.connect(self.obj.startServer)
        # 6 - Start the thread
        self.thread.start()
        # 7 - Start the form
        self.setupUi()

    def setupUi(self): 
        # Set up the GUI
        #...

        self.MainWindow.show()

    def onDataReady(self, data):
        # Data received from working thread
        # Do stuff...

    def on_click_set2(self):
        self.input = not self.input
        print(self.input)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())
class WebServer(QObject):
    finished = pyqtSignal()
    dataReady = pyqtSignal(dict)

    def __init__(self, input):
        super().__init__()
        self.input = input

    @pyqtSlot()
    def startServer(self): # A slot takes no params
        # self.loop = asyncio.get_event_loop()
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        coro = asyncio.start_server(self.handle_update, '192.168.2.1', 8888, loop=self.loop)
        self.server = self.loop.run_until_complete(coro)

        # Serve requests until Ctrl+C is pressed
        print('Serving on {}'.format(self.server.sockets[0].getsockname()))
        try:
            self.loop.run_forever()
        except KeyboardInterrupt:
            pass

        self.finished.emit()

    async def handle_update(self, reader, writer):
        data = await reader.read(100)
        message = data.decode()
        addr = writer.get_extra_info('peername')
        print(f'Received: {message} from {addr}')

        if self.input:
            print("Input is True")
        else:
            print("Input is False")

        reply = self.input

        print(f'Send: {reply}')
        writer.write(str(reply).encode())
        await writer.drain()

        print("Close the client socket")
        writer.close()
        self.dataReady.emit(reply)
WebServer:

class Ui_MainWindow(object):
    def __init__(self):
        super().__init__()

        self.input = True
        # 1 - create Worker and Thread inside the Form
        self.obj = WebServer.WebServer(self.input)  # no parent!
        self.thread = QtCore.QThread()  # no parent!
        # 2 - Connect Worker`s Signals to Form method slots to post data.
        self.obj.dataReady.connect(self.onDataReady)
        # 3 - Move the Worker object to the Thread object
        self.obj.moveToThread(self.thread)
        # 4 - Connect Worker Signals to the Thread slots
        self.obj.finished.connect(self.thread.quit)
        # 5 - Connect Thread started signal to Worker operational slot method
        self.thread.started.connect(self.obj.startServer)
        # 6 - Start the thread
        self.thread.start()
        # 7 - Start the form
        self.setupUi()

    def setupUi(self): 
        # Set up the GUI
        #...

        self.MainWindow.show()

    def onDataReady(self, data):
        # Data received from working thread
        # Do stuff...

    def on_click_set2(self):
        self.input = not self.input
        print(self.input)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_MainWindow()
    sys.exit(app.exec_())
class WebServer(QObject):
    finished = pyqtSignal()
    dataReady = pyqtSignal(dict)

    def __init__(self, input):
        super().__init__()
        self.input = input

    @pyqtSlot()
    def startServer(self): # A slot takes no params
        # self.loop = asyncio.get_event_loop()
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        coro = asyncio.start_server(self.handle_update, '192.168.2.1', 8888, loop=self.loop)
        self.server = self.loop.run_until_complete(coro)

        # Serve requests until Ctrl+C is pressed
        print('Serving on {}'.format(self.server.sockets[0].getsockname()))
        try:
            self.loop.run_forever()
        except KeyboardInterrupt:
            pass

        self.finished.emit()

    async def handle_update(self, reader, writer):
        data = await reader.read(100)
        message = data.decode()
        addr = writer.get_extra_info('peername')
        print(f'Received: {message} from {addr}')

        if self.input:
            print("Input is True")
        else:
            print("Input is False")

        reply = self.input

        print(f'Send: {reply}')
        writer.write(str(reply).encode())
        await writer.drain()

        print("Close the client socket")
        writer.close()
        self.dataReady.emit(reply)
例如,我想把输入传递给线程,如果我喜欢上面的(显然)输入总是保持初始值,当我点击GUI上的按钮时,线程中的输入不会改变

我该怎么做呢?只要我按下按钮,输入的值就会更新(所以在运行时从GUI向线程传递一个值)?我假设这类似于从线程传递到GUI,因此从GUI发出一个信号,并在踏板上连接到它,但我不知道如何从工作线程找到对GUI的引用

有什么建议吗?当然,欢迎您提供有关应用程序/后台服务器解决方案的代码或方法的任何其他输入!提前谢谢你的帮助

更新:

也许我不清楚我的问题是什么,所以这里是:


当GUI线程和辅助线程并行运行时,如何将值从GUI线程发送到辅助线程?(如果上面的代码对您来说有任何意义,请将其用作示例,否则请使用一般示例)

Web服务器不必位于另一个线程中,只需要在另一个线程中执行eventloop。在这种情况下,Web服务器通过队列与服务器线程交换数据。虽然QObject不是线程安全的,但信号是线程安全的,从QObject所在线程以外的线程发出信号没有问题

导入异步IO
导入线程
导入队列
从functools导入部分
从PyQt5导入QtCore、QtGui、QtWidgets
类Web服务器(QtCore.QObject):
dataReady=QtCore.pyqtSignal(对象)
def startServer(自):
self.m_loop=asyncio.new_event_loop()
self.m_queue=queue.queue()
asyncio.set\u事件\u循环(self.m\u循环)
coro=asyncio.start\u服务器(
self.handle\u更新,“127.0.0.1”,10000,循环=self.m\u循环
)
self.server=self.m_循环。运行_直到_完成(coro)
打印(“服务于{}”。格式(self.server.sockets[0].getsockname())
threading.Thread(target=self.m_loop.run_forever,daemon=True).start()
@QtCore.pyqtSlot(对象)
def setData(自身,数据):
如果hasattr(self,“m_队列”):
self.m_queue.put(数据)
def停止(自):
如果hasattr(self,“m_循环”):
self.m_loop.stop()
异步def句柄_更新(self、reader、writer):
reply=“”
数据=等待读卡器读取(100)
message=data.decode()
addr=writer.get\u额外信息(“peername”)
打印(f“从{addr}收到:{message}”)
如果不是self.m_queue.empty():
data=self.m_queue.get(block=False)
答复=数据
打印(f“发送:{reply}”)
writer.write(str(reply.encode())
等待writer.drain()
打印(“关闭客户端套接字”)
writer.close()
self.dataReady.emit(回复)
类小部件(qtwidts.QWidget):
dataChanged=QtCore.pyqtSignal(对象)
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
self.m_lineedit=qtwidts.QLineEdit()
button=QtWidgets.QPushButton(“发送”,单击=self.onClicked)
lay=qtwidts.QVBoxLayout(self)
lay.addWidget(self.m_lineedit)
lay.addWidget(按钮)
self.m_web=WebServer()
self.m_web.startServer()
self.dataChanged.connect(self.m_web.setData)
@QtCore.pyqtSlot()
def onClicked(自):
text=self.m_lineedit.text()
self.dataChanged.emit(文本)
@QtCore.pyqtSlot(对象)
def onDataReady(自身,数据):
打印(数据)
def关闭事件(自身、事件):
self.m_web.stop()
super().closeEvent(事件)
如果名称=“\uuuuu main\uuuuuuuu”:
导入系统
app=qtwidts.QApplication(sys.argv)
w=Widget()
w、 show()
sys.exit(app.exec_())

它显示所有GUI代码,但无法分析问题出在何处代码的问题是
input
变量的值在创建时传递给线程,但在运行时不会更新。但我更新了我的帖子,强调了我的问题。