如何避免GtkDrawingArea在draw事件触发时被清除?
解决Gtk3 DrawingArea保留历史绘制图形的问题
没问题,这完全可以实现!你的核心问题是当前代码只存储了最后一次点击的坐标,而且每次draw事件触发时,Cairo上下文会被默认重置(相当于清空画布),所以之前绘制的圆形就消失了。我们只需要调整数据存储和绘制逻辑,就能保留所有历史图形。
修改后的完整代码
#!/usr/bin/env python3 import gi gi.require_version('Gtk','3.0') from gi.repository import Gtk, Gdk import cairo import math class MouseButtons: LEFT_BUTTON = 1 RIGHT_BUTTON = 3 class Example(Gtk.Window): def __init__(self): super(Example, self).__init__() self.init_ui() def init_ui(self): self.darea = Gtk.DrawingArea() self.darea.connect("draw", self.on_draw) self.darea.set_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.add(self.darea) self.set_title("Fill & stroke") self.resize(230, 150) self.set_position(Gtk.WindowPosition.CENTER) self.connect("delete-event", Gtk.main_quit) self.darea.connect("button-press-event", self.on_button_press) # 改动1:存储所有点击的坐标,而不是单个坐标 self.coords = [] self.show_all() def on_draw(self, wid, cr): # 可选:先绘制白色背景,避免残留痕迹 cr.set_source_rgb(1, 1, 1) cr.paint() # 改动2:遍历所有存储的坐标,逐个绘制圆形 cr.set_source_rgb(0.6, 0.6, 0.6) for (x, y) in self.coords: cr.arc(x, y, 40, 0, 2*math.pi) cr.fill() def on_button_press(self, w, e): if e.type == Gdk.EventType.BUTTON_PRESS \ and e.button == MouseButtons.LEFT_BUTTON: # 改动3:将新坐标添加到列表,而不是替换旧坐标 self.coords.append([e.x, e.y]) self.darea.queue_draw() def main(): app = Example() Gtk.main() if __name__ == "__main__": main()
关键改动说明
- 存储所有点击位置:把
self.coords从单个坐标的列表,改成存储多个坐标的列表,每次点击就将新坐标追加进去。 - 批量绘制历史图形:在
on_draw方法中,遍历所有存储的坐标,逐个绘制圆形。这样每次queue_draw()触发重绘时,都会把所有历史圆形重新画一遍,自然就保留了之前的图形。 - 可选背景绘制:添加了白色背景的绘制,确保画布每次重绘都是干净的,避免出现奇怪的残留痕迹(如果不需要可以去掉这部分)。
现在你每次点击DrawingArea,都会新增一个圆形,而且之前的所有圆形都会被保留下来~
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

