首先,定义一个基类Shape,该基类存储形状的长度,位置和(随机生成的)颜色。从那里,您可以继承这些基本属性,并进一步指定其他形状。程序至少必须支持正方形,矩形,三角形,圆形和椭圆形。每个形状都应在基于Shape的继承层次结构中定义自己的类。回想一下,继承通常跨越一个以上的层次,因此请考虑并实施适当的继承方案。定义各种形状的类应通过添加其他需要的属性,在初始化期间适当地调用父构造函数,并包括使用作为参数提供的QPainter实例绘制形状的方法来进一步指定Shape类。请注意,形状类完全封装了形状概念,包括图形绘图代码。通过为形状的draw方法提供一个已经在使用的QPainter实例,<-我提供的代码应该可以完成上面的问题,但是我不确定我做的是否正确,并且想验证一下如果我当前的代码可以做到这一点。
当用户单击窗口中的某个位置(通过调用mousePressEvent指示)时,随机创建一个新的Shape对象,使其位于点击坐标处,并将该Shape添加到要绘制的项目列表中,应该是您课程的一个属性。 Shape对象的构造函数(与其父构造函数协作)应设置其所有属性,包括坐标,颜色和大小。随意对形状尺寸施加合理的限制。每次绘制窗口时(因为某些事件触发了对paintEvent的调用),应该绘制到目前为止创建的每个形状。因为它们在列表中(请参见下文),所以您可以使用循环对其进行迭代并绘制每个形状。多态的好处在于,您可以将它们全部视为基本Shape并要求它们绘制自身,因为它们每个都实现了一个将QPainter实例(也许来自ShapeDrawer.py中的paintEvent实例)作为参数的draw方法。请注意,您必须已经通过将其对象传递给形状的draw方法之前调用它的begin方法来激活painter对象。<-我不知道如何用当前代码完成数字2,如果有人可以帮助我,我将不胜感激。第二,因为我对鼠标的点击部分和整体的两个部分感到困惑。
总的来说,我已经使用提供的代码完成了第一项工作,并且想验证它是否正确,并且不知道如何执行第二项工作并需要帮助。
我提供的代码就是我尝试过的。
import sys, random
from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtGui import QPainter, QPainterPath, QBrush, QPen
from PyQt5.QtCore import Qt
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "Main Window"
self.right= 200
self.left= 200
self.width = 500
self.height = 500
self.Window()
def Window(self):
self.setWindowTitle(self.title)
self.setGeometry(self.right, self.left, self.width, self.height)
self.show()
class shape():
def __init__(self,length,position,color):
self.length=length
self.position=position
self.color= random.choice(colors)
class circle(shape):
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.red, 4 , Qt.SolidLine))
painter.drawEllipse(20, 20, 200, 200)
class rectangle(shape):
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.yellow, 7, Qt.DotLine))
painter.drawRect(10, 20, 100, 200)
class ellipse(shape):
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 4, Qt.SolidLine))
painter.setBrush(QBrush(Qt.black, Qt.SolidPattern))
painter.drawEllipse(20, 20, 200, 100)
class triangle(shape):
def paintEvent(self, event):
painter = QPainter()
path = QPainterPath()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(QtCore.Qt.red)
path.lineTo(180, 300)
path.lineTo(200, 100)
path.lineTo(10, 50)
painter.drawPath(path)
class square(shape):
def paintEvent(self, event):
painter = QPainter()
path = QPainterPath()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(QtCore.Qt.red)
path.lineTo(20, 12)
path.lineTo(20, 28)
path.lineTo(36, 28)
path.lineTo(36,12)
path.lineTo(20,12)
painter.drawPath(path)
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
答案 0 :(得分:1)
该问题指出,形状应使用作为参数提供的QPainter
对象进行绘制。在您的实现中,您正在QPainter
中创建单独的paintEvent
实例。除了重载paintEvent
之外,您还可以在每个Shape
子类中实现一个paint方法,该方法接受一个QPainter
对象作为绘制形状的参数。然后,可以在主窗口的paintEvent
方法中创建一个QPainter
对象,遍历添加到窗口的所有形状,并为每个形状调用shape.paint(painter)
。
class Shape():
def __init__(self, length, position, color, parent=None):
self.color = color
self.position = position
self.length = length
def paint(self, painter):
pass
class Circle(Shape):
def paint(self, painter):
if not painter.isActive():
return
painter.save()
painter.setPen(QPen(self.color, 4 , Qt.SolidLine))
x, y = self.position.x(), self.position.y()
painter.drawEllipse(x, y, self.length, self.length)
painter.restore()
等,并在Window
中:
class Window(QWidget):
def __init__(self):
super().__init__()
self.resize(500, 500)
self.shapes = []
def paintEvent(self, event):
super().paintEvent(event)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
for shape in self.shapes:
shape.paint(painter)
要测试实现:
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
for _ in range(20):
pos = QtCore.QPoint(*random.choices(range(500), k=2))
length = random.randrange(100)
color = QtGui.QColor(*random.choices(range(256), k=3))
window.shapes.append(Circle(length, pos, color))
window.show()
sys.exit(App.exec())