python pyqt QPainter 小部件不显示在布局中
python pyqt QPainter widgets don't show up in layout
我是 python3 pyqt GUI 开发的新手。我正在尝试制作一个简单的 GUI,它在包含许多 QHBoxLayout 的 QVBoxLayout 的复合布局结构中很好地具有各种小部件 spaced。在构建布局时,我使用 addStretch() 方法 space 出小部件,但绘制的圆圈不会显示在 GUI 显示中。但是,如果我注释掉所有 addStretch() 函数调用,则 GUI 会显示所有需要的小部件(但是间距不好看)。圆圈去哪儿了?
请帮忙!
不显示圆形小部件的代码。
#!/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_())
显示圆形小部件的代码(所有 addStretch() 调用都已注释掉)
#!/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_())
当您使用 addStrech()
时,布局将使用 sizeHint()
作为尺寸,因为未设置尺寸所以它不可见,解决方案是设置 属性。另一个建议是不要将 QPainter
设为 class 的成员,因为它不可避免地会消耗内存,只需将其设为局部变量即可。另一个建议是你在 setColor()
方法中调用 update()
并且它不会节省你的代码行并且你有一个更清晰的代码。
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)
我是 python3 pyqt GUI 开发的新手。我正在尝试制作一个简单的 GUI,它在包含许多 QHBoxLayout 的 QVBoxLayout 的复合布局结构中很好地具有各种小部件 spaced。在构建布局时,我使用 addStretch() 方法 space 出小部件,但绘制的圆圈不会显示在 GUI 显示中。但是,如果我注释掉所有 addStretch() 函数调用,则 GUI 会显示所有需要的小部件(但是间距不好看)。圆圈去哪儿了?
请帮忙!
不显示圆形小部件的代码。
#!/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_())
显示圆形小部件的代码(所有 addStretch() 调用都已注释掉)
#!/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_())
当您使用 addStrech()
时,布局将使用 sizeHint()
作为尺寸,因为未设置尺寸所以它不可见,解决方案是设置 属性。另一个建议是不要将 QPainter
设为 class 的成员,因为它不可避免地会消耗内存,只需将其设为局部变量即可。另一个建议是你在 setColor()
方法中调用 update()
并且它不会节省你的代码行并且你有一个更清晰的代码。
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)