Reputation: 13
I am new to python3 pyqt GUI development. I am trying to make a simple GUI which has various widgets spaced nicely in a compound layout structure of a QVBoxLayout which contains many QHBoxLayouts. When building the layouts, I use the addStretch() method to space out the widgets but the circles which are painted do not show up in the GUI display. However if I comment out all of the addStretch() function calls then the GUI displays all the desired widgets (however the spacing is not good looking). Where are the circles going?
Please help!
Code where circle widgets do not show up.
#!/usr/bin/python3
import sys
from PyQt4 import QtCore, QtGui
class DrawCircle(QtGui.QWidget):
def __init__(self, color, parent=None):
QtGui.QWidget.__init__(self, parent)
self.color = color
def setColor(self,color):
self.color = color
def paintEvent(self,event):
self.paint = QtGui.QPainter()
self.paint.begin(self)
self.paint.setRenderHint(QtGui.QPainter.Antialiasing)
radx = 30
rady = radx
if self.color == 'red':
self.paint.setPen(QtCore.Qt.red)
self.paint.setBrush(QtCore.Qt.red)
elif self.color == 'green':
self.paint.setPen(QtCore.Qt.green)
self.paint.setBrush(QtCore.Qt.green)
k = int(radx * 1.5)
center = QtCore.QPoint(k,k)
self.paint.drawEllipse(center,radx,rady)
self.paint.end()
class Window(QtGui.QMainWindow, QtGui.QGraphicsView):
def __init__(self):
super(Window,self).__init__()
# GUI Setup
self.myWid = QtGui.QWidget()
# Establish a Vertical Box Layout
# The layout will be a vertical box layout comprised of horizontal
# box layouts
self.vbox_fullDisplay = QtGui.QVBoxLayout()
# Add a Zero-width spacer-item before the area where the
# text label will appear
self.vbox_fullDisplay.addStretch(1)
###############################
# Build horizontal box layout #
###############################
self.hbox_top = QtGui.QHBoxLayout()
# The text should be centered on the screen so zero-width
# spacer items will be added to the left and right of the label
self.hbox_top.addStretch(1)
self.top_text_label = QtGui.QLabel(self)
self.top_text_label.setFont(QtGui.QFont("Times",32,QtGui.QFont.Bold))
self.top_text_label.setText("Top of window")
self.top_text_label.adjustSize()
self.hbox_top.addWidget(self.top_text_label)
self.hbox_top.addStretch(1)
# Add the horizontal box layout to the vertical box layout
self.vbox_fullDisplay.addLayout(self.hbox_top)
# Add space between the text and the row of circles
self.vbox_fullDisplay.addStretch(1)
############################
# Build the row of buttons #
############################
self.hbox_buttons = QtGui.QHBoxLayout()
# The text should be centered on the screen so zero-width
# spacer items will be added to the left and right of the label
self.hbox_buttons.addStretch(1)
# These buttons will be used to toggle the color of the circles
btn1 = QtGui.QPushButton('Circle 1')
btn1.clicked.connect(self.circle1Meth)
btn2 = QtGui.QPushButton('Circle 2')
btn2.clicked.connect(self.circle2Meth)
self.hbox_buttons.addWidget(btn1)
self.hbox_buttons.addStretch(1)
self.hbox_buttons.addWidget(btn2)
self.hbox_buttons.addStretch(1)
# Add the horizontal box layout to the vertical box layout
self.vbox_fullDisplay.addLayout(self.hbox_buttons)
# Add space between the text and the row of circles
self.vbox_fullDisplay.addStretch(1)
############################
# Build the row of circles #
############################
self.hbox_circles = QtGui.QHBoxLayout()
self.hbox_circles.addStretch(1)
self.__circleColors = ['red','green']
self.__circle1Color = 0;
self.circle1 = DrawCircle(self.__circleColors[self.__circle1Color])
print("const draw circ2")
self.__circle2Color = 1
self.circle2 = DrawCircle(self.__circleColors[self.__circle2Color])
self.hbox_circles.addWidget(self.circle1)
self.hbox_circles.addStretch(1)
self.hbox_circles.addWidget(self.circle2)
self.hbox_circles.addStretch(1)
# Add the row of circles to the vertical box layout
self.vbox_fullDisplay.addLayout(self.hbox_circles)
# Add space between the circles and the slot machine pictures
self.vbox_fullDisplay.addStretch(1)
self.bottomLabel = QtGui.QLabel(self)
self.bottomLabel.setText("Bottom Of GUI")
self.bottomLabel.adjustSize()
self.vbox_fullDisplay.addWidget(self.bottomLabel)
self.myWid.setLayout(self.vbox_fullDisplay)
self.setCentralWidget(self.myWid)
self.setGeometry(100,200,600,500)
self.setWindowTitle('Does this work')
def circle1Meth(self):
print("Circ1 change")
if self.__circle1Color == 1:
self.__circle1Color = 0
else:
self.__circle1Color = 1
# Set the color for circle 1
self.circle1.setColor(self.__circleColors[self.__circle1Color])
# force a repaint by updating the widget Using the repaint() method
# could cause infinite recursion
self.update()
def circle2Meth(self):
print("Circ2 change")
if self.__circle2Color == 1:
self.__circle2Color = 0
else:
self.__circle2Color = 1
# Set the color for circle 1
self.circle2.setColor(self.__circleColors[self.__circle2Color])
# force a repaint by updating the widget Using the repaint() method
# could cause infinite recursion
self.update()
###
# Run GUI
###
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
Code where circle widgets show up (all addStretch() calls commented out)
#!/usr/bin/python3
import sys
from PyQt4 import QtCore, QtGui
class DrawCircle(QtGui.QWidget):
def __init__(self, color, parent=None):
QtGui.QWidget.__init__(self, parent)
self.color = color
def setColor(self,color):
self.color = color
def paintEvent(self,event):
self.paint = QtGui.QPainter()
self.paint.begin(self)
self.paint.setRenderHint(QtGui.QPainter.Antialiasing)
radx = 30
rady = radx
if self.color == 'red':
self.paint.setPen(QtCore.Qt.red)
self.paint.setBrush(QtCore.Qt.red)
elif self.color == 'green':
self.paint.setPen(QtCore.Qt.green)
self.paint.setBrush(QtCore.Qt.green)
k = int(radx * 1.5)
center = QtCore.QPoint(k,k)
self.paint.drawEllipse(center,radx,rady)
self.paint.end()
class Window(QtGui.QMainWindow, QtGui.QGraphicsView):
def __init__(self):
super(Window,self).__init__()
# GUI Setup
self.myWid = QtGui.QWidget()
# Establish a Vertical Box Layout
# The layout will be a vertical box layout comprised of horizontal
# box layouts
self.vbox_fullDisplay = QtGui.QVBoxLayout()
# Add a Zero-width spacer-item before the area where the
# text label will appear
#self.vbox_fullDisplay.addStretch(1)
###############################
# Build horizontal box layout #
###############################
self.hbox_top = QtGui.QHBoxLayout()
# The text should be centered on the screen so zero-width
# spacer items will be added to the left and right of the label
#self.hbox_top.addStretch(1)
self.top_text_label = QtGui.QLabel(self)
self.top_text_label.setFont(QtGui.QFont("Times",32,QtGui.QFont.Bold))
self.top_text_label.setText("Top of window")
self.top_text_label.adjustSize()
self.hbox_top.addWidget(self.top_text_label)
#self.hbox_top.addStretch(1)
# Add the horizontal box layout to the vertical box layout
self.vbox_fullDisplay.addLayout(self.hbox_top)
# Add space between the text and the row of circles
#self.vbox_fullDisplay.addStretch(1)
############################
# Build the row of buttons #
############################
self.hbox_buttons = QtGui.QHBoxLayout()
# The text should be centered on the screen so zero-width
# spacer items will be added to the left and right of the label
#self.hbox_buttons.addStretch(1)
# These buttons will be used to toggle the color of the circles
btn1 = QtGui.QPushButton('Circle 1')
btn1.clicked.connect(self.circle1Meth)
btn2 = QtGui.QPushButton('Circle 2')
btn2.clicked.connect(self.circle2Meth)
self.hbox_buttons.addWidget(btn1)
#self.hbox_buttons.addStretch(1)
self.hbox_buttons.addWidget(btn2)
#self.hbox_buttons.addStretch(1)
# Add the horizontal box layout to the vertical box layout
self.vbox_fullDisplay.addLayout(self.hbox_buttons)
# Add space between the text and the row of circles
#self.vbox_fullDisplay.addStretch(1)
############################
# Build the row of circles #
############################
self.hbox_circles = QtGui.QHBoxLayout()
#self.hbox_circles.addStretch(1)
self.__circleColors = ['red','green']
self.__circle1Color = 0;
self.circle1 = DrawCircle(self.__circleColors[self.__circle1Color])
print("const draw circ2")
self.__circle2Color = 1
self.circle2 = DrawCircle(self.__circleColors[self.__circle2Color])
self.hbox_circles.addWidget(self.circle1)
#self.hbox_circles.addStretch(1)
self.hbox_circles.addWidget(self.circle2)
#self.hbox_circles.addStretch(1)
# Add the row of circles to the vertical box layout
self.vbox_fullDisplay.addLayout(self.hbox_circles)
# Add space between the circles and the slot machine pictures
#self.vbox_fullDisplay.addStretch(1)
self.bottomLabel = QtGui.QLabel(self)
self.bottomLabel.setText("Bottom Of GUI")
self.bottomLabel.adjustSize()
self.vbox_fullDisplay.addWidget(self.bottomLabel)
self.myWid.setLayout(self.vbox_fullDisplay)
self.setCentralWidget(self.myWid)
self.setGeometry(100,200,600,500)
self.setWindowTitle('Does this work')
def circle1Meth(self):
print("Circ1 change")
if self.__circle1Color == 1:
self.__circle1Color = 0
else:
self.__circle1Color = 1
# Set the color for circle 1
self.circle1.setColor(self.__circleColors[self.__circle1Color])
# force a repaint by updating the widget Using the repaint() method
# could cause infinite recursion
self.update()
def circle2Meth(self):
print("Circ2 change")
if self.__circle2Color == 1:
self.__circle2Color = 0
else:
self.__circle2Color = 1
# Set the color for circle 1
self.circle2.setColor(self.__circleColors[self.__circle2Color])
# force a repaint by updating the widget Using the repaint() method
# could cause infinite recursion
self.update()
###
# Run GUI
###
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
Upvotes: 1
Views: 1887
Reputation: 243945
When you use addStrech()
the layouts will use sizeHint()
as the size, since the size is not set so it is not visible, the solution is to set that property. Another suggestion is that you do not make the QPainter
a member of the class since it consumes memory in an unavoidable way, just make it a local variable. Another recommendation is that you call update()
inside setColor()
method and it does not save you code lines and you have a cleaner code.
class DrawCircle(QtGui.QWidget):
def __init__(self, color, parent=None):
QtGui.QWidget.__init__(self, parent)
self.color = color
def setColor(self,color):
self.color = color
self.update()
def paintEvent(self,event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
radx = 5
rady = radx
if self.color in ('red', 'green'):
col = QtGui.QColor(self.color)
painter.setPen(col)
painter.setBrush(col)
k = int(radx * 1.5)
center = QtCore.QPoint(k,k)
painter.drawEllipse(center,radx,rady)
def sizeHint(self):
return QtCore.QSize(15, 15)
Upvotes: 1