Solomon Baker
Solomon Baker

Reputation: 13

Pyqt5 Don't know where to pass instance variable from button

So I have 2 group boxes, left one has 2 buttons, fruits and vegetables. Right group box is empty and should add to it items after pressing a button. I wrote button class so it stores items, what I can't seem to understand is how do I pass item list, or rather where should I pass it. So I want to press a button(ex. fruits) and items from that button should show up in second(right)group box.

Example:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QPushButton,QGroupBox, QDialog, QHBoxLayout


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

        self.win = QDialog()
        self.win.setGeometry(200, 200, 800, 600)
        self.setFixedSize(800, 600)

        layout = QHBoxLayout()

        # Creating categories buttons and groupbox
        self.gboxCategories = self.createCategories()
        layout.addWidget(self.gboxCategories)

        # Creating items and groupbox
        self.gboxItems = self.createItems()
        layout.addWidget(self.gboxItems)

        self.setLayout(layout)
        self.show()

    def createCategories(self):
        categories = ['FRUITS', 'VEGETABLES']
        gbox = QGroupBox('CATEGORIES')
        gboxLayout = QVBoxLayout()

        for i in categories:
            btn = categoryButton(i)
            gboxLayout.addWidget(btn)

        gbox.setLayout(gboxLayout)

        return gbox

    # This should be done after clicking on a category button
    def createItems(self):
        items = []

        gbox = QGroupBox('ITEMS')
        gboxLayout = QVBoxLayout()

        for i in items:
            lbl = QLabel(i)
            gboxLayout.addWidget(lbl)

        gbox.setLayout(gboxLayout)
        return gbox


class categoryButton(QPushButton):
    def __init__(self, name):
        super().__init__()

        self.name = name
        self.items = []

        self.setText(self.name)

    def mousePressEvent(self, e):
        if e.buttons() == Qt.LeftButton:
            # Adding items to button list to be passed upon creation of labels
            if self.name == 'FRUITS':
                self.items = ['APPLES', 'PEAR', 'PLUM']

            elif self.name == 'VEGETABLES':
                self.items = ['CARROT', 'POTATO']

            print(f"""Button {self.name} : items = {self.items}""")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWin = mainWindow()
    app.exec_()

Upvotes: 1

Views: 42

Answers (1)

Vasco Ludovico
Vasco Ludovico

Reputation: 141

One of the solutions is to add a callback manager method to mainWindow and make mousePressEvent trigger it. You can centralize there all callback reactions. Additionally, before adding new widgets to the layout on the right you need to delete the existing ones.


import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QPushButton,QGroupBox, QDialog, QHBoxLayout


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

        self.win = QDialog()
        self.win.setGeometry(200, 200, 800, 600)
        self.setFixedSize(800, 600)

        self.layout = QHBoxLayout()

        # Creating left and right layouts
        self.leftlayout,self.leftbox=self.createvlayout('CATEGORIES')
        self.rightlayout,self.rightbox=self.createvlayout('ITEMS')

        self.layout.addWidget(self.leftbox)
        self.layout.addWidget(self.rightbox)

        # Populate CATEGORIES
        self.populatevlayout(['FRUITS', 'VEGETABLES'],self.leftlayout,callback=self.mousecallbacks)
        self.populatevlayout([],self.rightlayout,callback=self.mousecallbacks)

        self.setLayout(self.layout)
        self.show()

    def createvlayout(self,name):
        gbox = QGroupBox(name)
        gboxLayout = QVBoxLayout()
        gbox.setLayout(gboxLayout)
        return gboxLayout,gbox

    def populatevlayout(self,items,layout,callback=None):
        while True:
            item=layout.takeAt(0)
            if item:
                if item.widget():
                    item.widget().deleteLater()
            else:
                break
        for i in items:
            btn = categoryButton(i,callback)
            layout.addWidget(btn)
          

    def mousecallbacks(self,name):
            # Adding items to button list to be passed upon creation of labels
            if name == 'FRUITS':
                self.populatevlayout(['APPLES', 'PEAR', 'PLUM'],self.rightlayout,callback=self.mousecallbacks)
            elif name == 'VEGETABLES':
                self.populatevlayout(['CARROT', 'POTATO'],self.rightlayout,callback=self.mousecallbacks)



class categoryButton(QPushButton):
    def __init__(self, name,callback):
        super().__init__()

        self.name = name
        self.callback=callback
        self.setText(self.name)

    def mousePressEvent(self, e):
        if e.buttons() == Qt.LeftButton:
            if self.callback is not None:
                self.callback(self.name)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWin = mainWindow()
    app.exec_()

Upvotes: 1

Related Questions