Python的基本绘图<三>

本文通过实例演示如何使用Python的Turtle库绘制内切圆的正方形、半圆与等边三角形组合,以及正六边形和三角形的图形。重点讲解了颜色设置、填充、隐藏画笔和图形布局技巧。

学习目标:

今天继续对示例进行分析,进一步巩固Turtle库的相关语法。

学习内容

示例1 绘制圆+正方形,绘制要求:
a.绘制一个正方形并且内切一个填充的圆;
b.正方形边长为100并且轮廓线为红色;
c.内切圆轮廓线为红色并且填充为黄色;
d.绘图过程中隐藏画笔,可以清晰看见图形绘制过程。

代码演示:

import turtle as t
t.speed(8)
t.pencolor("red")
t.pensize(2)
t.seth(0)
t.forward(50)
t.left(90)
t.forward(100)
t.left(90)
t.forward(100)
t.left(90)
t.forward(100)
t.goto(0,0)

t.seth(0)
t.fillcolor("yellow")
t.begin_fill()
t.circle(50)
t.end_fill()
t.hideturtle()
t.done()

运行结果演示:
在这里插入图片描述

示例2 绘制半圆+三角形,上边是一个红色轮廓、黄色填充的边长为300的等边三角形,下边是一个绿色填充,半径为150的半圆,绘制要求:
a.画布背景为白色,等边三角形为红色轮廓,黄色填充;
b.半圆为绿色填充并且与等边三角形在底边的中点处相切;
c.能看见绘制过程并且隐藏画笔。

代码演示:

import turtle as t
t.speed(10)
t.pensize(2)
#画半圆
t.fillcolor("green")
t.begin_fill()
t.seth(0)
t.forward(150)
t.left(90)
t.circle(150, 180)
t.goto(0, 0)
t.end_fill()

t.penup()
t.goto(0, 150)
t.pendown()
t.pencolor("red")
t.pensize(2)
t.fillcolor("yellow")
t.begin_fill()
t.seth(0)
t.forward(150)
t.seth(120)
t.forward(300)
t.left(120)
t.forward(300)
t.goto(0, 150)
t.end_fill()

t.hideturtle()
t.done()

运行结果演示:
在这里插入图片描述
示例3 绘制正六边形,绘制要求:
a.背景为白色,正六边形和三角形的填充分别为红色和绿色;
b.图形中间为边长为150的正六边形,周围是六个等边三角形;
c.正六边形的上下两边要求与X轴方向平行;
d.绘图过程中隐藏画笔,并能清楚看见图形绘制过程。

代码演示:

import turtle as t
t.speed(10)

#绘制正六边形
t.fillcolor("red")
t.begin_fill()
t.seth(0)
t.penup()
t.forward(150)
t.pendown()
t.left(120)
t.forward(150)
for i in range(5):
    t.left(60)
    t.forward(150)
t.end_fill()
t.penup()
t.goto(0,0)

#绘制三角形
for i in range(6):
    t.penup()
    t.seth(i * 60)
    t.forward(150)
    t.left(60)
    t.pendown()
    t.fillcolor("green")
    t.begin_fill()
    t.forward(150)
    t.left(120)
    t.forward(150)
    t.left(120)
    t.forward(150)
    t.end_fill()
    t.penup()
    t.goto(0, 0)

t.hideturtle()
t.done()

运行结果演示:
在这里插入图片描述

<think>好的,我现在需要帮助用户解决如何在Qt中使用Qt Designer设计MainWindow的UI,并将自定义的Canvas类集成进去,实现笔、橡皮擦和保存功能。首先,我得回忆一下Qt的基本工作流程,特别是Qt Designer和自定义部件的集成方法。 用户提到了使用Qt自带的UI设计工具,也就是Qt Designer。我知道Qt Designer生成的是.ui文件,这个文件会被uic工具转换成Python代码(假设用户用的是PyQt或者PySide)。用户需要将自定义的Canvas类添加到这个UI中。通常,Qt Designer允许添加自定义的widget,但可能需要提升为某个已有的基类,比如QWidget,然后在代码中将这个提升的widget替换为自定义的Canvas类。 接下来,用户需要实现笔、橡皮擦和保存功能。Canvas类应该继承自QWidget或QGraphicsView之类的绘图区域。在Canvas类中,可能需要处理鼠标事件,记录绘制的路径,并根据当前工具(笔或橡皮擦)来改变绘制的方式。橡皮擦可能通过绘制背景色来实现,或者使用组合模式来擦除已有的绘图。保存功能可能需要将Canvas的内容保存为图片文件,比如PNG或JPEG。 现在,我需要详细分步骤来解答。首先是如何在Qt Designer中添加一个用于绘图的区域。用户需要在UI文件中放置一个QWidget作为Canvas的占位符,然后将其提升为自定义的Canvas类。这涉及到在Qt Designer中右键点击该QWidget,选择“提升为”,然后输入类名和头文件。不过,用户需要注意,生成的代码可能需要手动导入Canvas类,或者在代码中进行设置。 然后,如何将UI文件与自定义类结合。用户需要使用uic模块将.ui文件转换为Python代码,然后在主窗口类中初始化UI,并设置Canvas实例。可能需要重写某些方法,或者将UI中的控件(如按钮)与Canvas的功能连接起来,比如按钮点击事件触发笔或橡皮擦模式的切换,以及保存操作。 关于Canvas类的实现,需要处理鼠标按下、移动和释放事件,记录路径的点,并在paintEvent中进行绘制。可能需要两个路径,一个用于永久保存的绘图,另一个用于临时预览。橡皮擦功能可以通过改变笔的颜色为背景色,或者使用合成模式QPainter.CompositionMode_Clear。保存功能可以使用QWidget.grab()来捕获Canvas的内容,然后保存为图片。 可能的陷阱包括:提升的widget在代码中是否正确初始化,事件处理是否正确连接,绘图性能是否足够,以及保存图片时的路径和权限问题。此外,需要注意在布局中正确设置Canvas的大小和位置,确保UI布局在不同分辨率下表现一致。 最后,用户可能需要示例代码来展示如何实现这些步骤,包括UI文件的处理、提升widget的方法、Canvas类的绘图逻辑,以及信号槽的连接。应该提醒用户检查Qt版本和PyQt/PySide的兼容性,确保所有模块正确导入,并处理可能的异常。</think>### 使用Qt Designer集成自定义Canvas类实现绘图功能 #### 一、创建基础UI布局(Qt Designer操作) 1. 新建`MainWindow`窗体 2. 添加工具栏或按钮组: - 笔按钮 - 橡皮擦按钮 - 保存按钮 3. 添加`QWidget`容器作为绘图区域: - 右键选择"提升为..." - 输入自定义类名`Canvas` - 设置头文件为`canvas.py`(Python文件路径)[^2] ```xml <!-- mainwindow.ui 片段 --> <widget class="Canvas" name="centralwidget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> </widget> ``` #### 二、自定义Canvas类实现 ```python # canvas.py from PyQt5.QtWidgets import QWidget from PyQt5.QtGui import QPainter, QPen, QColor, QImage from PyQt5.QtCore import Qt, QPoint class Canvas(QWidget): def __init__(self): super().__init__() self.image = QImage(self.size(), QImage.Format_RGB32) self.image.fill(Qt.white) self.drawing = False self.brush_size = 5 self.brush_color = Qt.black self.last_point = QPoint() def paintEvent(self, event): painter = QPainter(self) painter.drawImage(self.rect(), self.image, self.image.rect()) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = True self.last_point = event.pos() def mouseMoveEvent(self, event): if self.drawing: painter = QPainter(self.image) painter.setPen(QPen(self.brush_color, self.brush_size, Qt.SolidLine, Qt.RoundCap)) painter.drawLine(self.last_point, event.pos()) self.last_point = event.pos() self.update() def mouseReleaseEvent(self, event): self.drawing = False def set_eraser(self): self.brush_color = Qt.white # 或使用QPainter.CompositionMode_Clear def set_brush(self): self.brush_color = Qt.black def save_image(self, filename): self.image.save(filename) ``` #### 、主窗口逻辑集成 ```python # main.py import sys from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog from PyQt5.uic import loadUiType ui, _ = loadUiType('mainwindow.ui') class MainWindow(QMainWindow, ui): def __init__(self): super().__init__() self.setupUi(self) self.canvas = self.findChild(Canvas, "centralwidget") # 获取提升后的Canvas实例 # 连接信号槽 self.actionBrush.triggered.connect(self.canvas.set_brush) self.actionEraser.triggered.connect(self.canvas.set_eraser) self.actionSave.triggered.connect(self.save_file) def save_file(self): filename, _ = QFileDialog.getSaveFileName( self, "保存图片", "", "PNG图片(*.png);;JPEG图片(*.jpg)") if filename: self.canvas.save_image(filename) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` #### 四、关键实现细节 1. **提升控件原理**:通过`QWidget`的元对象系统实现动态类型替换,需确保: - 自定义类继承自对应基类 - 提升时指定正确的头文件路径[^3] 2. **绘图优化**: ```python # 使用双缓冲技术防止闪烁 def __init__(self): # ... self.setAttribute(Qt.WA_StaticContents) ``` 3. **橡皮擦实现原理**: ```python def set_eraser(self): painter = QPainter(self.image) painter.setCompositionMode(QPainter.CompositionMode_Clear) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值