Search code examples
pythonpython-3.xpyqtpyqt4

The PyQt button does not show up


So....I am using the PyQt lib for python to make a Graphics class which abstracts away most of the features of the QtGui class.I"ll be using it later for my other projects.This seems to be working fine,except that the button and the other widgets do not show up,although the window gets created.

import sys
from PyQt4 import QtGui

class Graphics:
    def __init__(self):

        self.app=QtGui.QApplication(sys.argv)
        self.widgets={}
        self.labels={}
        self.buttons={}


    def getApp(self):

        return self.app


    def newWidget(self,name:str):

        self.widgets[name]=QtGui.QWidget()
        return self.widgets[name]       


    def addButton(self,name:str,text:str):

        self.buttons[name]=QtGui.QPushButton(text)
        return self.buttons[name]


    def addLabel(self,name:str,text:str):

        self.labels[name]=QtGui.QLabel()
        self.labels[name].setText(text)
        return self.labels[name]


    def start(self):
        for widget in self.widgets:
            self.widgets[widget].show()
        sys.exit(self.app.exec_())

^ That's the code.Down below shows how i implement the class

from graphics import Graphics

gui=Graphics()
w1=gui.newWidget("hmm")
bt1=gui.addButton("hey","hello")
print(bt1)
gui.start()

It'd be great if you could provide insight as to why this is happening.Thank You


Solution

  • In Qt there is a basic rule: the QWidget children are drawn with respect to the parent QWidget, and if it does not have a parent this will be a window, which is called top-level.

    Another concept is QPushButton, QLabel, QSpinBox, etc. are QWidgets since they inherit from this class.

    So, since QPushButton does not have a parent, it should show itself as a window, and for that you should use show():

    def start(self):
        [w.show() for name, w in self.widgets.items()]
        [button.show() for name, button in self.buttons.items()]
        [label.show() for name, label in self.labels.items()]
    
        sys.exit(self.app.exec_())
    

    enter image description here


    If your intention is that some QLabel or QPushButton be part of some QWidget then we must indicate that widget as parent, for example in my next solution I propose to add the name of the widget, and if the widget does not exist it should be created:

    import sys
    from PyQt4 import QtGui
    
    class Graphics:
        def __init__(self):
            self.app=QtGui.QApplication(sys.argv)
            self.widgets={}
            self.labels={}
            self.buttons={}
    
        def getApp(self):
            return self.app
    
        def newWidget(self, name:str):
            w = QtGui.QWidget()
            self.widgets[name] = w
            return w     
    
        def addButton(self, widget_name:str, name:str, text:str):
            if widget_name in self.widgets:
                w = self.widgets[widget_name]
            else:
                w = self.newWidget(widget_name)
            button = QtGui.QPushButton(text, parent=w)
            self.buttons[name] = button
            return button
    
        def addLabel(self, widget_name:str, name:str, text:str):
            if widget_name in self.widgets:
                w = self.widgets[widget_name]
            else:
                w = self.newWidget(widget_name)
            label = QtGui.QLabel(text, parent=w)
            self.labels[name] = label
            return label
    
        def start(self):
            [w.show() for name, w in self.widgets.items()]
    
            sys.exit(self.app.exec_())
    

    enter image description here


    If you want to add a parent after the button is created then you can use setParent():

    graphics.py

    import sys
    from PyQt4 import QtGui
    
    class Graphics:
        def __init__(self):
            self.app=QtGui.QApplication(sys.argv)
            self.widgets={}
            self.labels={}
            self.buttons={}
    
        def getApp(self):
            return self.app
    
        def newWidget(self, name:str):
            w = QtGui.QWidget()
            self.widgets[name] = w
            return w     
    
        def addButton(self, name:str, text:str):
            button = QtGui.QPushButton(text)
            self.buttons[name] = button
            return button
    
        def addLabel(self, name:str, text:str):
            label = QtGui.QLabel(text)
            self.labels[name] = label
            return label
    
        def start(self):
            for _, w in in self.widgets.items():
                w.show()
            sys.exit(self.app.exec_())
    

    main.py

    gui=Graphics()
    w1 = gui.newWidget("hmm")
    bt1 = gui.addButton("hey","hello")
    bt1.setParent(w1) # <-- set w1 as parent of bt1
    gui.start()