开发者社区> 问答> 正文

在Dash回调中显示PyQt5元素

在我的Python Dash应用程序中,我想显示一些PyQt5窗口弹出窗口。这些是从回调内部激活的。

不幸的是,当显示弹出窗口时,我在控制台中收到此警告:

警告:未在main()线程中创建QApplication。

我的问题:如果从Python Dash回调内部调用它,如何在main()线程中创建QApplication?

在下面,您可以找到代表mwe的代码。如果运行此代码段,则会看到警告。显然,当从回调内激活QApplication时,它不在主线程上运行(我猜是app.run_server()已在主线程上运行)。我如何修改它,以便QApplication位于主线程中?

该示例类似于PyQt5 GUI中的Use Dash(plot.ly),但不相同(我希望Dash中的pyqt5,而不是pyqt5中的Dash)。

import os, dash
from PyQt5.QtWidgets import QApplication,QMainWindow
from PyQt5.QtCore import QCoreApplication
import dash_html_components as html
from dash.dependencies import Input, Output

class MainWindow(QMainWindow):
    #some Qpop up
    pass

app = dash.Dash()

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    #button which, if pressed, created a QApplication in a non-main thread
    html.Button("show pop up", id="button"),
    html.H2(children='', id='result')
    ])

#The callback which creates the pop up I want to show.
#This is activated when the button "show pop up" is pressed, and causes the warning to appear
@app.callback(
Output(component_id='result', component_property='children'),
[Input(component_id='button', component_property='n_clicks')]
)   
def popUp(n_clicks):
    if not n_clicks:
        raise dash.exceptions.PreventUpdate
    app = QCoreApplication.instance()
    if app is None:
        app = QApplication([os.getcwd()])
    mainWin = MainWindow()
    mainWin.show()
    app.exec_()
    return "You saw a pop-up"

if __name__ == '__main__':
    app.run_server(debug=False)

问题来源:stackoverflow

展开
收起
is大龙 2020-03-24 20:31:10 832 0
1 条回答
写回答
取消 提交回答
  • 逻辑是在辅助线程中运行Dash并通过如下所示的信号将通知发送到GUI(此答案基于我的其他答案):

    import functools
    import os
    import threading
    
    from PyQt5 import QtCore, QtWidgets
    
    import dash
    import dash_html_components as html
    from dash.dependencies import Input, Output
    
    
    class MainWindow(QtWidgets.QMainWindow):
        closed = QtCore.pyqtSignal()
    
        def closeEvent(self, event):
            self.closed.emit()
            super().closeEvent(event)
    
    
    class Manager(QtCore.QObject):
        def __init__(self, parent=None):
            super().__init__(parent)
            self._view = None
    
        @property
        def view(self):
            return self._view
    
        def init_gui(self):
            self._view = MainWindow()
    
        @QtCore.pyqtSlot()
        def show_popup(self):
            if self.view is not None:
                self.view.show()
    
    
    qt_manager = Manager()
    
    app = dash.Dash()
    
    app.layout = html.Div(
        children=[
            html.H1(children="Hello Dash"),
            html.Button("show pop up", id="button"),
            html.H2(children="", id="result"),
        ]
    )
    
    
    @app.callback(
        Output(component_id="result", component_property="children"),
        [Input(component_id="button", component_property="n_clicks")],
    )
    def popUp(n_clicks):
        if not n_clicks:
            raise dash.exceptions.PreventUpdate
    
        loop = QtCore.QEventLoop()
        qt_manager.view.closed.connect(loop.quit)
        QtCore.QMetaObject.invokeMethod(
            qt_manager, "show_popup", QtCore.Qt.QueuedConnection
        )
        loop.exec_()
    
        return "You saw a pop-up"
    
    
    def main():
        qt_app = QtWidgets.QApplication.instance()
        if qt_app is None:
            qt_app = QtWidgets.QApplication([os.getcwd()])
        qt_app.setQuitOnLastWindowClosed(False)
        qt_manager.init_gui()
        threading.Thread(
            target=app.run_server, kwargs=dict(debug=False), daemon=True,
        ).start()
    
        return qt_app.exec_()
    
    
    if __name__ == "__main__":
        main()
    

    回答来源:stackoverflow

    2020-03-24 20:31:17
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载