如何在另一个 class 中使用列表小部件的结果?

How to use results from list widget in another class?

我是面向对象编程的新手,需要帮助从一个 class 中的列表小部件获取值到另一个 class。我在主窗口 class 中有一个名为 selectedVariables 的列表小部件。我希望 SecondWindow class 能够从 selectedVariables 获取变量,这样用户就可以在第二个 window 中 select 它们按某个变量对数据进行分组。理想情况下,当他们单击三个点时,会弹出一个新的 window,其中包含一个小部件列表,但现在我只需要了解如何获取 selectedVariable 列表项并将其发送到第二窗口 Class。下面的代码运行没有错误,但没有引用 selectedVariables 列表。

我确实尝试了 layout.addWidget(MainWindow.selectedVariables, 3, 0, 1, 1) 但它给了我错误:

回溯(最近调用最后):

文件“S:WORKING\FINANCIALANALYST\ShawnSchreier\Python\MinimumExample.py”,第 99 行,在 mw = MainWindow()

文件“S:WORKING\FINANCIAL ANALYST\Shawn Schreier\Python\Minimum Example.py”,第 49 行,在 init 中 self.mw = SecondWindow()

文件“S:WORKING\FINANCIAL ANALYST\Shawn Schreier\Python\Minimum Example.py”,第 30 行,在 init 中 layout.addWidget(MainWindow.selectedVariables, 3, 0, 1, 1)

AttributeError: 类型对象 'MainWindow' 没有属性 'selectedVariables'

from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QListWidget, QLineEdit, QTextEdit, QGridLayout, QHBoxLayout, QVBoxLayout, QSizePolicy, QFileDialog, QTabWidget, QCheckBox
import PyQt5.QtGui as qtg
from PyQt5.QtCore import Qt, QSettings
import inspect
from PyQt5 import QtCore

class SecondWindow(QWidget):
    def __init__(self):
        super().__init__()
        
        layout = QGridLayout()
        by = QLabel("By")
        byVariables = QLineEdit()
        byVariableList = QListWidget()
        layout.addWidget(by, 1,0,1,1)
        layout.addWidget(byVariables, 2, 0, 1, 1)
        byButton = QPushButton("...")
        layout.addWidget(byButton, 2, 1, 1, 1)
        
        self.setLayout(layout)

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        # Add a title
        self.setWindowTitle("GUI Querying Program")

        self.layout = QHBoxLayout()
        self.setLayout(self.layout)
        self.initUI()
        self.setButtonConnections()
        
        self.mw = SecondWindow()
        

    def initUI(self):
        subLayouts = {}

        subLayouts['LeftColumn'] = QGridLayout()
    
        self.layout.addLayout(subLayouts['LeftColumn'],1)
        
        # Buttons
        self.buttons = {}
        self.buttons['addVariable'] = QPushButton('>')
        self.buttons['removeVariable'] = QPushButton('<')
        self.buttons['Toolkit'] = QPushButton('Toolkit')
        
        
        self.variables = QListWidget()
        self.selectedVariables = QListWidget()
        
        subLayouts['LeftColumn'].addWidget(self.variables, 7,0,4,1)
        subLayouts['LeftColumn'].addWidget(self.selectedVariables, 7,1,4,1)
        subLayouts['LeftColumn'].addWidget(self.buttons['addVariable'], 10,0,1,1)
        subLayouts['LeftColumn'].addWidget(self.buttons['removeVariable'], 10,1,1,1)
        subLayouts['LeftColumn'].addWidget(self.buttons['Toolkit'], 11,1,1,1)
        
        names = ['apple', 'banana', 'Cherry']
        self.variables.insertItems(0, names)
        
    def setButtonConnections(self):
        self.buttons['addVariable'].clicked.connect(self.add_variable)
        self.buttons['removeVariable'].clicked.connect(self.remove_variable)
        self.buttons['Toolkit'].clicked.connect(self.show_new_window)   
        
    def add_variable(self):
        selected_elements=[item.text() for item in self.variables.selectedItems()]
        variableItem = self.selectedVariables.insertItems(self.variables.count(),selected_elements)
        #self.variablesSearch.clear()
        
    def remove_variable(self):
        oldVariable = self.selectedVariables.currentRow()
        self.selectedVariables.takeItem(oldVariable)
    
    def show_new_window(self):
        self.mw.show()


if __name__ == "__main__":
    import sys
    app = QApplication([])
    mw = MainWindow()
    mw.show()
    # Run the app
    app.exec()
    app.quit()
    #sys.exit(app.exec())

您可以尝试将 SecondWindow class 设为子 class。这意味着,让它继承您的 MainWindow 方法。像这样

Class SecondWindow(MainWindow):

据我了解,根据您的代码,selectedVariables 实例可以根据使用的方法互换。所以在构造函数中将其定义为实例变量会更明智

Class MainWindow(Qwidget):
   def__init__(self):
      self.selectedVariables = QListWidget()
       

这样,您将更容易独立地继承对它发生的操作。此外,您不需要每次都调用该方法,这是必须的。

如果你想复制项,那么你应该使用QListWidgetItem的clone()函数。

请注意,您也应该在 add_variable 中执行相同的操作:虽然您的情况非常简单,但 克隆 一个项目可确保 所有 它的属性(包括自定义数据,如文本或背景颜色)被复制,而不仅仅是它的文本。

class SecondWindow(QWidget):
    def __init__(self):
        super().__init__()
        
        layout = QGridLayout(self)

        by = QLabel("By")
        byVariables = QLineEdit()
        self.byVariableList = QListWidget()
        byButton = QPushButton("...")
        layout.addWidget(by, 0, 0)
        layout.addWidget(byVariables, 1, 0)
        layout.addWidget(byButton, 2, 1)
        layout.addWidget(self.byVariableList, 3, 0, 1, 2)

    def setItems(self, items):
        self.byVariableList.clear()
        for item in items:
            self.byVariableList.addItem(item)


class MainWindow(QWidget):
    # ...
    def add_variable(self):
        for item in self.variables.selectedItems():
            self.selectedVariables.addItem(item.clone())

    def show_new_window(self):
        items = []
        for i in range(self.selectedVariables.count()):
            items.append(self.selectedVariables.item(i).clone())
        self.mw.setItems(items)
        self.mw.show()

注意当app.exec()returns时,表示应用已经退出,之后再调用app.quit()就没有意义了。另外: 1. 网格布局的行和列总是基于 0 索引(就像计算中几乎 anything 一样),所以你应该从 0 添加项目,而不是 1; 2. row/column 跨度始终默认为 1,因此没有必要指定它,除非您特别希望跨度大于 1。