pyqt5 update() function not working for QGroupBox

169 views Asked by At

Ok so I think the best way for me to show what I'm trying to accomplish is visually, so I created a reproducible example of what I'm trying to do and strangely enough... it worked perfectly fine. Here it is

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

big_ar = ["1","2","3"]


class MyMainWindow(QWidget):

    def __init__(self):
        super(MyMainWindow,self).__init__()
        self.setGeometry(300,300,300,300)

        self.initUI()


    def initUI(self):
        self.lay = QVBoxLayout()

        self.window_opener = WindowOpenerButton("open window",self)
        self.group_box = UpdatingGroupBox(self)

        self.lay.addWidget(self.window_opener)
        self.lay.addWidget(self.group_box)

        self.setLayout(self.lay)
        


    def cust_update(self):

        self.group_box.addButton()
        self.group_box.update()
        



class WindowOpenerButton(QPushButton):

    def __init__(self,txt,par):
        super(WindowOpenerButton,self).__init__(txt,par)

        self.clicked.connect(self.openWin)


    def openWin(self):
        
        self.smallWindow = MySmallWindow(psp=self.parentWidget())
        
        self.smallWindow.show()




class MySmallWindow(QWidget):

    def __init__(self,psp=None,parent=None):
        
        super(MySmallWindow,self).__init__(parent)
        self.setGeometry(100,100,100,100)
        
        self.pseudo_parent = psp
        
        self.populate()


    

    def populate(self):
        self.layout = QVBoxLayout()

        self.line_edit = QLineEdit(self)
        
        self.done = DoneButton("done",self,self.line_edit)
        

        self.layout.addWidget(self.line_edit)
        self.layout.addWidget(self.done)

        self.setLayout(self.layout)
        

    def closeEvent(self,event):

        if self.pseudo_parent != None:
            self.pseudo_parent.cust_update()

            
class UpdatingGroupBox(QGroupBox):

    def __init__(self,par):

        super(UpdatingGroupBox,self).__init__(par)

        self.layout = QVBoxLayout()

        self.addPreexisting()
        self.setLayout(self.layout)

    def addPreexisting(self):
        global big_ar

        for i in range(len(big_ar)):
            self.layout.addWidget(QPushButton(big_ar[i],self))

    def addButton(self):
        global big_ar
        
        self.layout.addWidget(QPushButton(big_ar[ len(big_ar) - 1],self))
            

class DoneButton(QPushButton):

    def __init__(self,txt,par,src):

        super(DoneButton,self).__init__(txt,par)

        self.txt_source = src
        

        self.clicked.connect(self.addToArr)

    def addToArr(self):

        global big_ar

        big_ar.append(self.txt_source.text())
        self.parentWidget().close()
        print(big_ar)


def main():
    app = QApplication(sys.argv)
    app.setStyle("Fusion")


    x = MyMainWindow()

    x.show()


    app.exec()


if __name__ == "__main__":
    main()


Now this example outlines what I'm trying to do quite accurately and simply where it gets the string from the line edit on the smaller window and makes it into a pushbutton in the larger window's qgroupbox which is then updated immediately afterwards. The only difference between this example and my code is that instead of using a global array to add onto the qgroupbox, I use an instance variable, take a look.

    def cust_update(self):
        mem_f = open(self.file,"r")
        
        raw_file_ml = mem_f.read().split("{")[1]

        file_ml = raw_file_ml.split(";")


        self.list.append(Member(file_ml[len(file_ml) - 2]))


        mem_f.close()

   
        self.mb_gb.addButton()
        
        self.mb_gb.update()

This is the cust_update method for my actual program (you can disregard the first couple lines) and mb_gb is a MemberList which is this:

class MemberList(comps.MyButtonList): #list of memButtons derived from members.txt
    

    def __init__(self,ttl,labl_ls,par,**kwargs): 
        super(MemberList,self).__init__(ttl,labl_ls,par,**kwargs)

        
        self.layout = QVBoxLayout()

        self.addPrexisting()

        self.setLayout(self.layout)

        
    def addPrexisting(self):
        for i in range(len(self.list)):
            self.layout.addWidget(QPushButton(self.list[i].fullName()))
        
    def addButton(self):
        nb = QPushButton(self.list[len(self.list) - 1])
        
        self.layout.addWidget(nb)

the self.list represents a list of members which, as you can see in the cust_update method, is updated. The MemberList then takes the last element of the list and makes it into a button which is then added to its layout.

It's very similar to the first example's ugb but for some reason when the cust_event is called, even though it adds the button to the layout, it isn't being drawn (discovered through print debugging) and I have already tried using repaint()

EDIT:

I now see the confusion with what a Member and MyButtonList is, the reason I didn't explain them in the first place is because I didn't find it necessary as those parts of the code are working (my bad!). Here's the member class :

class Member:

    def __init__(self,info_str):
        info_ar = info_str.split(",")
        self.first_name = info_ar[0]
        self.last_name = info_ar[1]
        self.idnum = info_ar[2]
        self.grade_when_joined = info_ar[3]
        self.gender = info_ar[4]
        self.position = info_ar[5]
        self.date_joined = info_ar[6][0:len(info_ar[6])]

        
        
    def fullName(self):
        
        return self.first_name.capitalize() + " " + self.last_name.capitalize()

    def __str__(self):
        return (self.fullName() + ": " + self.id() + " " + self.gender + " " + self.getPosition()  + " " + str(self.date_joined))
    

    def id(self):
        lln = self.last_name.lower()
        return lln + str(self.idnum)

    def dateJoined(self):
        y = int(self.date_joined[0:4])
        m = int(self.date_joined[5:7])
        d = int(self.date_joined[8:10])

        return dt.date(y,m,d)


    def sex(self):

        s = "Other"

        if self.gender == 'm':
            s  = "Male"
        elif self.gender == 'f':
            s = "Female"

        return s


    def getPosition(self):

        pos = "Member"

        if self.position == "o":
            pos = "Officer"
        elif self.position == "v":
            pos = "Vice President"
        elif self.position == "p":
            pos = "President"


        return pos


    def idInt(self):
        return int(self.idnum)

Prior to the closeEvent, a line is added to a txt file based on user input which follows the format

First_Name,Last_Name,ID#,Grade,Gender,Position,Date_When_Joined

when the close event happens, the cust_update method reads the file, splits it into individual members by ";" and takes the last one (the member that was just added) and makes it into a qpushbutton with its first name.

The MyButtonList class is nearly identical to the MemberList class, the only difference is in what goes on the buttons so it looks like this:

class MyButtonList(MyGroupBox):

    def __init__(self,ttl,lab_ls,par,**kwargs):
        super(MyButtonList,self).__init__(title=ttl,pare=par,**kwargs)
        self.setUpdatesEnabled(True)

        self.label_ls = lab_ls

        self.list = self.parentWidget().list

        self.layout = QVBoxLayout()

        self.addPrexisting()

        self.setLayout(self.layout)


    def addPrexisting(self):
        for i in range(len(self.list)):
            self.layout.addWidget(QPushButton(str(i),self))
        

    def addButton(self):
        self.layout.addWidget(QPushButton("added",self))

Please let me know if there's anything I missed or I didn't communicate properly, sorry I didn't put everything here in the first place!

0

There are 0 answers