Hi! Hope you're enjoying this blog. I have a new home at www.goldsborough.me. Be sure to also check by there for new posts <3

Wednesday, September 18, 2013

Dynamically adding objects in PyQt

Hi all, today I thought I'd show you how to dynamically add objects. It may already be clear to you, but it wasn't to me in the beginning, so this is for those struggling with the idea.

We will start out with a simple window, a button, a global variable and a grid layout (important!).

import sys
from PyQt4 import QtGui, QtCore


count = 1

class Main(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.initUI()

    def initUI(self):

        centralwidget = QtGui.QWidget()

        self.add = QtGui.QPushButton("Add")
        

        self.grid = QtGui.QGridLayout()
        
        self.grid.addWidget(self.add,0,0)

        centralwidget.setLayout(self.grid)

        self.setCentralWidget(centralwidget)


    #---------Window settings --------------------------------
        
        self.setGeometry(300,300,280,170)
        self.setWindowTitle("")
        self.setWindowIcon(QtGui.QIcon(""))
        self.setStyleSheet("background-color:")
        self.show()

def main():
    app = QtGui.QApplication(sys.argv)
    main = Main()
    main.show()

    sys.exit(app.exec_())

if __name__ == "__main__":
    main()


Next, we will write the function connecting to the add button. This function will create a new button and add it to the grid. So, first:


self.add.clicked.connect(self.Add)

Then, two functions:

    def Add(self):
        global count

        b = QtGui.QPushButton(str(count),self)
        b.clicked.connect(self.Button)

        self.grid.addWidget(b,count,0)

        count += 1

    def Button(self):
        pass


Don't worry about the Button function for now, I just created it in order to prevent an error. So what exactly happens in the Add function? First, we import(?) the global variable count, which we will need for a couple of things. Then, we create a button and name it anything we want, this is not important, what is important though, is that we set the text to the string encoded integer count, so that each time we add a button and increase the count number, we have a different text.  Of course, this could be anything you want, if, for example, you have a user input something, you could just set it to the variable holding the input. Anyway, connect that button to a function and add it to the grid layout. Here, the variable count is very important, since we need a different position for each button added. Lastly, add 1 to count.

Now the Button function:

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

        print(sender.text())

If you don't know already, to determine the sender of the signal for this slot, you can call the sender() function. This of course just gives us the hexadecimal position and identity of the widget. Since it is a button, we can access it's text to distinguish between them. So call sender.text(), and you'll see which button is being pressed.

This is it for this tutorial, in another tutorial, I'll might cover how to delete them dynamically using a context menu :)

6 comments :

  1. Thanks, I´ve been struggling for more than 6 hours until I found this post. Thanks a lot. One little issue: I don´t want to use text in the buttons, I´m using Icons. So, I´ll see what to do next. At least, I can decide now for text or icon. I´ll see if I can hide the text, etc.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. I figured it out... I was writing everything out of order

      import sys
      from PyQt4 import QtGui, QtCore

      count = 1


      class Main(QtGui.QMainWindow):
      def __init__(self):
      QtGui.QMainWindow.__init__(self)
      self.initUI()

      def initUI(self):
      centralwidget = QtGui.QWidget()

      self.add = QtGui.QPushButton("Add")
      self.add.clicked.connect(self.Add)

      self.grid = QtGui.QGridLayout()

      self.grid.addWidget(self.add, 0, 0)

      centralwidget.setLayout(self.grid)

      self.setCentralWidget(centralwidget)

      # ---------Window settings --------------------------------

      self.setGeometry(300, 300, 280, 170)
      self.setWindowTitle("")
      self.setWindowIcon(QtGui.QIcon(""))
      self.setStyleSheet("background-color:")
      self.show()

      def Add(self):
      global count

      b = QtGui.QPushButton(str(count), self)
      b.clicked.connect(self.Button)

      self.grid.addWidget(b, count, 0)

      count += 1

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

      print(sender.text())


      def main():
      app = QtGui.QApplication(sys.argv)
      main = Main()
      main.show()

      sys.exit(app.exec_())


      if __name__ == "__main__":
      main()

      Delete
  3. This code is a big help for me ! Thx

    ReplyDelete
  4. is there any ways to create grid layouts with different number of rows dynamically depending on the integer input from the user?

    ReplyDelete
  5. use the QGridLayout.addWidget(QWidget, int row, int column, Qt.Alignment alignment = 0)
    and it will automatically add it self

    ReplyDelete