Pyside2 QGuiApplication,Gui 在按钮上冻结

Pyside2 QGuiApplication, Gui freeze on button Clicked

我正在使用 QML、Pyside2 和 QGuiApplication 编写桌面应用程序 问题是当我点击任何按钮时 Gui 冻结,代码执行和 Gui returns 到正常状态。 我搜索并发现问题是我的应用程序的单线程。 所以我试着让它成为多线程 我试过了:

QGuiApplication.processEvents()

和:

app = QGuiApplication()
app.processEvents()

在 pyQT5 中,我知道这就是答案并解决了问题:

QApplication.processEvents()

如文档所述link函数:

processEvents()

应该可以但不能用!

这是我的 Qml 调用函数:

RoundButton{
     icon.source :"icons/baseline_play_arrow_black_48dp"
     onClicked: DataVisClass.road_analysis()
}

这是 DataVisClass.py :

from PySide2.QtCore import QObject, Slot
from PySide2.QtGui import QGuiApplication

class DataVis(QObject):
    def __init__(self,app):
        super().__init__()
        self.app = app
        self.roadAnalyser = RoadAnalyser()

    @Slot()
    def road_analysis(self):
        self.roadAnalyser.centrality(True, True, 'Piedmont, California, USA', "drive_service", "betweenness_centrality", self.app)

和RoadAnalyser.py:

class RoadAnalyser:
    def centrality(self, logs, use_cache, place, net_type, alg_type, app):
        app.processEvents()
        QGuiApplication.processEvents()
        ox.config(log_console=logs, use_cache=use_cache)
        # place = 'Piedmont, California, USA'
        G = ox.graph_from_address(place, network_type=net_type)
        # G = ox.graph_from_address(place, network_type='drive_service')

        gdf = ox.gdf_from_place(place)
        area = ox.projection.project_gdf(gdf).unary_union.area

        # calculate basic and extended network stats, merge them together, and display
        stats = ox.basic_stats(G, area=area)
        extended_stats = ox.extended_stats(G, ecc=True, bc=True, cc=True)
        for key, value in extended_stats.items():
            stats[key] = value
            QGuiApplication.processEvents()
        pd.Series(stats)

        G_projected = ox.project_graph(G)
        max_node, max_bc = max(extended_stats[alg_type].items(), key=lambda x: x[1])
        # max_node, max_bc = max(extended_stats['betweenness_centrality'].items(), key=lambda x: x[1])
        print("Best node is : ",max_bc,max_node)

        # nc = get_node_colors_by_stat(G_projected, data=extended_stats['betweenness_centrality'])
        nc = get_node_colors_by_stat(G_projected, data=extended_stats[alg_type])
        # for each in nc :
        #     print(each)
        fig, ax = ox.plot_graph(G, fig_height=6, node_color=nc, node_size=20, node_zorder=2,
                                edge_linewidth=2, edge_color='#333333', bgcolor='k')
        # for each in extended_stats['betweenness_centrality'].items():
        #     print(each)

谢谢

耗时的任务不应该 运行 在主线程中,因为它们会阻塞事件循环,其结果之一就是冻结。解决方法是 运行 在另一个线程中:

  • 删除与“app”或 QXApplication 相关的所有内容,因为它是不必要的

    class RoadAnalyser:
        def centrality(self, logs, use_cache, place, net_type, alg_type):
            ox.config(log_console=logs, use_cache=use_cache)
            # place = 'Piedmont, California, USA'
            G = ox.graph_from_address(place, network_type=net_type)
            # G = ox.graph_from_address(place, network_type='drive_service')
    
            gdf = ox.gdf_from_place(place)
            area = ox.projection.project_gdf(gdf).unary_union.area
    
            # calculate basic and extended network stats, merge them together, and display
            stats = ox.basic_stats(G, area=area)
            extended_stats = ox.extended_stats(G, ecc=True, bc=True, cc=True)
            for key, value in extended_stats.items():
                stats[key] = value
            pd.Series(stats)
    
            G_projected = ox.project_graph(G)
            max_node, max_bc = max(extended_stats[alg_type].items(), key=lambda x: x[1])
            # max_node, max_bc = max(extended_stats['betweenness_centrality'].items(), key=lambda x: x[1])
            print("Best node is : ", max_bc, max_node)
    
            # nc = get_node_colors_by_stat(G_projected, data=extended_stats['betweenness_centrality'])
            nc = get_node_colors_by_stat(G_projected, data=extended_stats[alg_type])
            # for each in nc :
            #     print(each)
            fig, ax = ox.plot_graph(
                G,
                fig_height=6,
                node_color=nc,
                node_size=20,
                node_zorder=2,
                edge_linewidth=2,
                edge_color="#333333",
                bgcolor="k",
            )
    
  • 使用threading.Thread

    import threading
    
    
    class DataVis(QObject):
        def __init__(self, app):
            super().__init__()
            self.app = app
            self.roadAnalyser = RoadAnalyser()
    
        @Slot()
        def road_analysis(self):
    
            threading.Thread(
                target=self.roadAnalyser.centrality,
                args=(
                    True,
                    True,
                    "Piedmont, California, USA",
                    "drive_service",
                    "betweenness_centrality",
                ),
            ).start()
    

更新

如果你想从线程发送信息,那么必须使用信号

class DataVis(QObject):
    fooSignal = Signal(str)

    # ...

    @Slot()
    def road_analysis(self):

        threading.Thread(
            target=self.roadAnalyser.centrality,
            args=(
                True,
                True,
                "Piedmont, California, USA",
                "drive_service",
                "betweenness_centrality",
                self.fooSignal
            ),
        ).start()
class RoadAnalyser:
    def centrality(self, logs, use_cache, place, net_type, alg_type, signal):
        # ...
        signal.emit("foo")
Connections{
    target: DataVisClass
    function onFooSignal(msg){
         console.log(msg)
    }
}