mechapman
mechapman

Reputation: 25

clearing layout on QWidget in pyqt

I am trying to create a gui using PYQT that displays a couple of pictures and buttons. Every time the user clicks next, I want new pictures to appear. However, when I try to do this, I get an error saying:

Attempting to set QLayout "" on Example "", which already has a layout

how can I delete the layout from the QWidget?

Here is my code:

#!/usr/bin/env.python

import sys
from PyQt4 import QtGui, QtCore


class Example(QtGui.QWidget):

  def __init__(self):
    super(Example, self).__init__()

    self.pageNumber = 1
    self.CTlist = ('ct.png', 'ct2.png', 'ct3.png')
    self.initUI(self.pageNumber)

  def initUI(self,page):    
    lbl1 = QtGui.QLabel(self)
    button1 = QtGui.QRadioButton('Picture 1')

    lbl2 = QtGui.QLabel(self)
    button2 = QtGui.QRadioButton('Picture 2')

    button3 = QtGui.QPushButton('Next')
    button3.clicked.connect(self.next)

    pixmap = QtGui.QPixmap(self.CTlist[page])
    lbl1.setPixmap(pixmap)
    lbl2.setPixmap(pixmap)

    vbox1 = QtGui.QVBoxLayout()
    vbox1.addWidget(lbl1)
    vbox1.addWidget(button1)

    vbox2 = QtGui.QVBoxLayout()
    vbox2.addWidget(lbl2)
    vbox2.addWidget(button2)

    vbox3 = QtGui.QVBoxLayout()
    vbox3.addWidget(button3)

    hbox = QtGui.QHBoxLayout()
    hbox.addLayout(vbox1)
    hbox.addLayout(vbox2)
    hbox.addLayout(vbox3)

    self.setLayout(hbox)

    self.move(300,200)
    self.setWindowTitle('Choose which picture you like more')
    self.show()    

  def next(self):
      self.pageNumber += 1
      self.initUI(self.pageNumber)


def main():
  app = QtGui.QApplication(sys.argv)
  ex = Example()
  sys.exit(app.exec_())

if __name__== '__main__':
  main()

Upvotes: 1

Views: 1712

Answers (2)

NorthCat
NorthCat

Reputation: 9937

According the docs:

Sets the layout manager for this widget to layout.

If there already is a layout manager installed on this widget, QWidget won't let you install another. You must first delete the existing layout manager (returned by layout()) before you can call setLayout() with the new layout.

If layout is the layout manger on a different widget, setLayout() will reparent the layout and make it the layout manager for this widget.

So, you can simply reparent the layout to a temporary widget (link):

def initUI(self,page):

    if self.layout():
        QtGui.QWidget().setLayout(self.layout())

    lbl1 = QtGui.QLabel(self)
    button1 = QtGui.QRadioButton('Picture 1')

    lbl2 = QtGui.QLabel(self)
    button2 = QtGui.QRadioButton('Picture 2')

    button3 = QtGui.QPushButton('Next')
    button3.clicked.connect(self.next)

    pixmap = QtGui.QPixmap(self.CTlist[page])
    lbl1.setPixmap(pixmap)
    lbl2.setPixmap(pixmap)

    vbox1 = QtGui.QVBoxLayout()
    vbox1.addWidget(lbl1)
    vbox1.addWidget(button1)

    vbox2 = QtGui.QVBoxLayout()
    vbox2.addWidget(lbl2)
    vbox2.addWidget(button2)

    vbox3 = QtGui.QVBoxLayout()
    vbox3.addWidget(button3)

    hbox = QtGui.QHBoxLayout()
    hbox.addLayout(vbox1)
    hbox.addLayout(vbox2)
    hbox.addLayout(vbox3)

    self.setLayout(hbox)

    self.move(300,200)
    self.setWindowTitle('Choose which picture you like more')
    self.show()

Upvotes: 0

user3419537
user3419537

Reputation: 5000

The problem here is that you are reinitialising your entire UI every time next() is called, which is creating a new layout every time and trying to assign that to your widget with self.setLayout(hbox).

What you really want to do is just change the pixmap being displayed inside your labels. If you change your initUI function to make the labels members of your Example class, then the next function can look something like this

def next(self):
  self.pageNumber += 1
  pixmap = QtGui.QPixmap(self.CTlist[self.pageNumber])
  self.lbl1.setPixmap(pixmap)
  self.lbl2.setPixmap(pixmap)

Upvotes: 1

Related Questions