简体   繁体   中英

PyQt5 - how to enable a new (third) button that fail to show after running clicked pushButton?

Here is a simple program to create 2 pushbuttons and a third pushbutton when either of the first two buttons is clicked. But it doesn't work. When I click one of the first two buttons I get the message in the console indicating it has been clicked but no 3rd button appears. Why?? Thanks!

 from PyQt5 import QtCore, QtGui, QtWidgets
 class Ui_Form(object):
     def setupUi(self, Form):
         Form.setObjectName("Form")
         Form.resize(400, 300)
     def setup_pushButton(self, word, x, y, width, height):
         self.pushButton = QtWidgets.QPushButton(Form)
         self.pushButton.setGeometry(QtCore.QRect(x, y, width, height))
         self.pushButton.setText(word)
         self.pushButton.clicked.connect(self.but_clicked)
     def create_pushButtons(self):
         self.setup_pushButton('apple', 100, 110, 75, 23)
         self.setup_pushButton('car', 20, 110, 75, 23)
     def but_clicked(self):
         print('clicked')
         self.setup_pushButton('house', 250, 110, 75, 23)
 if __name__ == "__main__":
     import sys
     app = QtWidgets.QApplication(sys.argv)
     Form = QtWidgets.QWidget()
     ui = Ui_Form()
     ui.setupUi(Form)
     ui.create_pushButtons()
     Form.show()
     sys.exit(app.exec_())

Below code with inline commenting will help you figure out what went wrong and why I put things where they are. Most important... your button names may change every now and then therefor I've made the code variable for you by using setattr and getattr . Less work to do afterwards and more pythonic with an eye on OOP ;-)

Note: Normally initialization of buttons occur in the setupUI by convention. In your case we treat the buttons as additions to the main setupUI not taken into account earlier because its an additional feature in a fictional product asked by your beloved product launching customer.

Enjoy!

Tributton example:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(QtWidgets.QWidget, object):

    def __init__(self, parent=None):

        print '> This is start of main app'

        super(Ui_Form, self).__init__(parent)

        self.setupUI(self)

        self.buttonlist = [('apple', 100, 110, 75, 23),
                       ('car', 20, 110, 75, 23),
                       ('house', 250, 110, 75, 23)]

        self.create_pushButtons()

        print '> Everything is painted... lets show it on screen.'

    def setupUI(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Twobutton Example", "Twobutton Example"))

    def create_pushButtons(self):

        for item in self.buttonlist:

            # set attribute with variable name (e.g. "car" may change into "cars")
            setattr(self, 'pushButton_%s' % (item[0]), QtWidgets.QPushButton(self))

            # painting the variale named button.
            #                                          x,       y,   width,  height
            getattr(self, 'pushButton_%s' % (item[0])).setGeometry(QtCore.QRect(item[1], item[2], item[3], item[4]))
            getattr(self, 'pushButton_%s' % (item[0])).setText(item[0])

            # create the connection aswell for the variable named button in a single "go".
            if item[0] in [self.buttonlist[0][0], self.buttonlist[1][0]]:
                getattr(self, 'pushButton_%s' % (item[0])).clicked.connect(self.buton_clicked)

            if item[0] == self.buttonlist[2][0]:

                getattr(self, 'pushButton_%s' % (item[0])).clicked.connect(self.house_but_clicked)
                getattr(self, 'pushButton_%s' % (item[0])).hide()

    def buton_clicked(self):

        #"Murder she wrote".. : who done it... was it car or apple... where did the order came from?
        sender = self.sender()
        text = sender.text()

        print('The button %s was clicked' % text)
        # print 'clicked' to python standard out. In an editor like komodo edit you see imidiatly what you do.
        sys.stdout.flush()

        # car button:
        # if button house is hidden... lets show it (again).
        if text in [self.buttonlist[1][0], ]:
            getattr(self, 'pushButton_%s' % (self.buttonlist[2][0])).show()

        # apple button:
        # if button house is show... lets hide it again.
        if text in [self.buttonlist[0][0], ]:
            getattr(self, 'pushButton_%s' % (self.buttonlist[2][0])).hide()

    def house_but_clicked(self):
        sender = self.sender()

        print('The button %s was clicked and its going to be connected to something else' % sender.text())
        sys.stdout.flush()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_Form()
    ui.show()
    sys.stdout.flush()
    sys.exit(app.exec_())

EDIT : to show inccorect use of variable objectname after comment OP on december 10th.

OP script :

snippet...

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    t = ui
    ui.create_pushButtons()

    Form.show()
#    print dir(__builtins__)
#    l = dir(Ui_Form.setup_pushButton)
#    from pprint import pprint
#    pprint(l)
#    t = Ui_Form()
    variables = [i for i in dir(t) if not inspect.ismethod(i)]
    print variables
    sys.exit(app.exec_())

Output print variables:

[' class ', ' delattr ', ' dict ', ' doc ', ' format ', ' getattribute ', ' hash ', ' init ', ' module ', ' new ', ' reduce ', ' reduce_ex ', ' repr ', ' setattr ', ' sizeof ', ' str ', ' subclasshook ', ' weakref ', 'but_clicked', 'create_pushButtons', 'pushButton1', 'setupUi', 'setup_pushButton']

Tributton example script :

snippet...

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_Form()
    t = ui
    ui.show()
    sys.stdout.flush()
    variables = [i for i in dir(t) if not inspect.ismethod(i)]
    print variables
    sys.exit(app.exec_())

Output print variables:

This is start of main app Everything is painted... lets show it on screen. ['DrawChildren', 'DrawWindowBackground', 'IgnoreMask', 'PaintDeviceMetric', ... 'pos', 'previousInFocusChain', 'property', 'pushButton_apple', 'pushButton_car', 'pushButton_house', 'pyqtConfigure', 'raise_', 'receivers', 'rect', 'releaseKeyboard', ... 'windowOpacity', 'windowRole', 'windowState', 'windowTitle', 'windowTitleChanged', 'windowType', 'x', 'y']

As you can see there are three separate atributes with their own objectName space, namely ... 'pushButton_apple' , 'pushButton_car' and 'pushButton_house' .

Actually, my code did produce the new button it just wasn't showing. By adding --self.pushButton.show() -- it now works fine. Here's the complete revised code that works.

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
     def setupUi(self, Form):
          Form.setObjectName("Form")
          Form.resize(400, 300)
     def setup_pushButton(self, word, x, y, width, height):
          self.pushButton = QtWidgets.QPushButton(Form)
         self.pushButton.setGeometry(QtCore.QRect(x, y, width, height))
         self.pushButton.setText(word)
     self.pushButton.clicked.connect(self.but_clicked)
 def create_pushButtons(self):
     self.setup_pushButton('apple', 100, 110, 75, 23)
     self.setup_pushButton('car', 20, 110, 75, 23)
 def but_clicked(self):
     print('clicked')
     self.setup_pushButton('house', 250, 110, 75, 23)
     self.pushButton.show()
 if __name__ == "__main__":
      import sys
      app = QtWidgets.QApplication(sys.argv)
      Form = QtWidgets.QWidget()
      ui = Ui_Form()
      ui.setupUi(Form)
      ui.create_pushButtons()
      Form.show()
      sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM