如何将小部件推广到具有不同选择的不同类?

Posted

技术标签:

【中文标题】如何将小部件推广到具有不同选择的不同类?【英文标题】:how to promote widget to different classes with different selection? 【发布时间】:2021-02-15 01:11:38 【问题描述】:

我正在使用 pyqt5 在小部件上绘制股票趋势。有时小部件只有一个情节,有时我想有 3 个子情节。我为同一个小部件设计了两个类,如下所示。首先,我将小部件提升到下面的第一类,只有一个情节。稍后当我选择不同的按钮来绘制不同的图时,我想将图更改为具有 3 个子图,这意味着我需要更改小部件的类。是否可以为具有不同选择的相同小部件更改类?或者有没有其他方法?

class gui_stock_oneplot(QWidget):
    def __init__(self,parent=None):
        QWidget.__init__(self,parent)
        self.canvas=FigureCanvas(Figure())
        
        vertical_layout=QVBoxLayout()
        vertical_layout.addWidget(self.canvas)
        
        self.canvas.axis1=self.canvas.figure.add_subplot(111)
        self.canvas.axis2=self.canvas.axis1.twinx()
        self.canvas.axis3=self.canvas.axis1.twinx()
        self.canvas.figure.set_facecolor("white")  #lightblue
        self.setLayout(vertical_layout)

想要将小部件类更改为:

class gui_stock_3plot(QWidget):
    def __init__(self,parent=None):
        QWidget.__init__(self,parent)
        self.canvas=FigureCanvas(Figure())
        
        vertical_layout=QVBoxLayout()
        vertical_layout.addWidget(self.canvas)
        
        self.canvas.axis1=self.canvas.figure.add_subplot(311)
        self.canvas.axis2=self.canvas.figure.add_subplot(312)
        self.canvas.axis3=self.canvas.figure.add_subplot(313)
        self.canvas.figure.set_facecolor("white")  #lightblue
        self.setLayout(vertical_layout)

【问题讨论】:

你的问题不清楚,自己解释清楚。请提供minimal reproducible example 对不起eyllanesc。是的,我的问题不清楚。我不知道怎么问?我是 Pyqt5 的新手。基本上,我设计了一个小部件来绘制区域。我想让同一个小部件灵活地绘制一个子图和 3 个子图。怎么做?我的想法是改变小部件类。谢谢 如果您提供 MRE,也许您可​​以提供帮助,否则我会走我的路 “promote”是指通过 Designer 中的提升小部件使用自定义类吗?如果是这样,不,你不能:一旦 ui 被实例化,小部件实例被创建,你不能“改变类”实例(这与 PyQt 无关,它是类和实例背后的基本概念任何语言)。如果您创建一个表格,您可以自定义它(子类表格),使其具有 3、4 或更多条腿、宽度和高度,但是一旦创建它,​​您就无法将其变成直升机。 【参考方案1】:

如果通过“提升” OP 意味着在 .ui 中使用自定义小部件,那么答案是否定的,你不能。

显然,OP 有一个 XY 问题,因为他想知道一个可能的解决方案:如何在 2 个类之间切换一个被提升的小部件,而不是背景问题:如何更改自定义小部件中的绘图?

对于根本问题,至少有两种可能的解决方案:

    你可以先在同一个小部件中实现所有逻辑,方法是清理图形,然后重新绘制:

    class Widget(QWidget):
        def __init__(self):
            super().__init__()
            layout = QVBoxLayout(self)
    
            self.canvas = FigureCanvas(Figure())
            layout.addWidget(self.canvas)
    
        def one_plot(self):
            self.canvas.figure.clear()
    
            self.canvas.axis1 = self.canvas.figure.add_subplot(111)
            self.canvas.axis2 = self.canvas.axis1.twinx()
            self.canvas.axis3 = self.canvas.axis1.twinx()
            self.canvas.figure.set_facecolor("white")  # lightblue
    
            self.canvas.draw()
    
        def three_plot(self):
            self.canvas.figure.clear()
    
            self.canvas.axis1 = self.canvas.figure.add_subplot(311)
            self.canvas.axis2 = self.canvas.figure.add_subplot(312)
            self.canvas.axis3 = self.canvas.figure.add_subplot(313)
            self.canvas.figure.set_facecolor("white")  # lightblue
    
            self.canvas.draw()
    

    然后只需使用每个函数的 clicked 信号来更改绘图:

    self.one_button.clicked.connect(self.foo_widget.one_plot)
    self.three_button.clicked.connect(self.foo_widget.three_plot)
    

    另一个解决方案不是推广而是使用 QStackedWidget。逻辑是将每个小部件添加到 QStackedWidget 并通过按钮更改索引。

    self.one_widget = gui_stock_oneplot()
    one_index = self.stacked_widget.addWidget(self.one_widget)
    self.one_button.clicked.connect(
        lambda *args, index=one_index: self.stacked_widget.setCurrentIndex(index)
    )
    
    self.three_widget = gui_stock_3plot()
    three_index = self.stacked_widget.addWidget(self.three_widget)
    self.three_button.clicked.connect(
        lambda *args, index=three_index: self.stacked_widget.setCurrentIndex(index)
    )
    

【讨论】:

哇,eyllanesc,这令人印象深刻!你让我一整个晚上感觉很好。第一个解决方案对我来说更容易理解。第二种方法我以前从未这样做过,但它非常聪明。这真是太棒了!非常感谢 eyllanesc,非常感谢您的帮助。 我想的另一个解决方案是不要在要提升的类中定义任何子图。相反,我可以在主程序中添加子图吗?例如 self.widgetPlot.canvas.axis1=self.widgetPlot.canvas.figure.add_subplot(311) self.widgetPlot.canvas.axis2=self.widgetPlot.canvas.figure.add_subplot(312)

以上是关于如何将小部件推广到具有不同选择的不同类?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 如何将小部件扩展为具有更多内容的更大小部件?

将小部件插入 QGridLayout 的问题

将小部件添加到地图会破坏 GWT 中的其他小部件

如何将小部件尺寸传递给 __init__

Android Widget:在将小部件添加到屏幕之前显示配置活动

如何有条件地将小部件添加到列表中?