pythonpyqt5qlistwidget

How to use results from list widget in another class?


I am new to object oriented programming and need assistance getting the value from a listwidget in one class to another class. I have one listwidget called selectedVariables in the MainWindow class. I want the SecondWindow class to be able to get the variables from selectedVariables so the user can select them in the second window to group the data by a certain variable. Ideally, when they click the three dots, a new window pops up with a list of the widgets, but for now I just need to understand how to get the selectedVariable list items and send it to the SecondWindow Class. The code below runs without errors, but has no reference to the selectedVariables list.

I did try layout.addWidget(MainWindow.selectedVariables, 3, 0, 1, 1) and it gave me the error :

Traceback (most recent call last):

File "S:\1WORKING\FINANCIAL ANALYST\Shawn Schreier\Python\Minimum Example.py", line 99, in mw = MainWindow()

File "S:\1WORKING\FINANCIAL ANALYST\Shawn Schreier\Python\Minimum Example.py", line 49, in init self.mw = SecondWindow()

File "S:\1WORKING\FINANCIAL ANALYST\Shawn Schreier\Python\Minimum Example.py", line 30, in init layout.addWidget(MainWindow.selectedVariables, 3, 0, 1, 1)

AttributeError: type object 'MainWindow' has no attribute '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())

Solution

  • If you want to copy items, then you should use the clone() function of QListWidgetItem.

    Note that you should do the same also in add_variable: while your case is very simple, cloning an item ensures that all its properties (including custom data, like text or background color) are copied, not only its text.

    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()
    

    Note that when app.exec() returns, it means that the application has been quit, calling app.quit() after that is pointless. Also: 1. rows and columns of a grid layout are always based on 0-indexes (just like almost anything in computing), so you should add items from 0, not 1; 2. the row/column span always defaults to 1, so there is no point in specifying it unless you specifically want a span greater than 1.