开罗和 Gdk.Window 与 Gtk.DrawingArea 使用 python gobject-introspection 和 gtk3
Cairo and Gdk.Window with Gtk.DrawingArea using python gobject-introspection and gtk3
我正在尝试遵循参考文档中的 Gtk+ v3 教程。特别是第一个绘图示例使用 cairo
将绘图处理到 Gtk.DrawingArea
.
https://developer.gnome.org/gtk3/stable/ch01s03.html
作为参考,我正在使用这些资源:
https://python-gtk-3-tutorial.readthedocs.org/en/latest/
http://lazka.github.io/pgi-docs/
请看一下我将 ch01s03
程序(部分)翻译成 python。我遇到的主要问题是 configure_event_cb()
程序应该创建一个 cairo.Surface
对象连接到 Gdk.Window
。我不知道如何找到这个 Gdk.Window
甚至不知道在哪里查看参考文档。
from gi.repository import Gtk, Gdk, cairo
surface = None
def clear_surface():
global surface
surface = cairo.Surface()
surface.set_source_rgb(1,1,1)
surface.paint()
def configure_event_cb(wid,evt):
global surface
if surface is not None:
surface.destroy()
surface = None
'''
Here, I am trying to implement the following C code:
surface = gdk_window_create_similar_surface(
gtk_widget_get_window(widget),
CAIRO_CONTENT_COLOR,
gtk_widget_get_allocated_width(widget),
gtk_widget_get_allocated_height(widget) );
'''
clear_surface()
return True
def close_window(wid):
global surface
if surface is not None:
surface.destroy()
Gtk.main_quit()
if __name__ == '__main__':
win = Gtk.Window(Gtk.WindowType.TOPLEVEL)
win.set_title('Drawing Area')
win.connect('destroy',close_window)
win.set_border_width(8)
frame = Gtk.Frame()
frame.set_shadow_type(Gtk.ShadowType.IN)
win.add(frame)
da = Gtk.DrawingArea()
da.set_size_request(100,100)
frame.add(da)
da.connect('configure-event',configure_event_cb)
win.show_all()
Gtk.main()
我了解到 DrawingArea 现在使用 draw 事件而不是 configure-event 这是一个简单的代码:
from gi.repository import Gtk
def draw_cb(widget, cr):
cr.set_source_rgba(0,0,0,0.5)
cr.rectangle(50,75,100,100)
cr.fill()
return False
win = Gtk.Window()
win.set_title("test")
win.set_default_size(800,600)
win.connect('delete-event', Gtk.main_quit)
da=Gtk.DrawingArea()
da.connect('draw', draw_cb)
win.add(da)
win.show_all()
Gtk.main()
但是如果你真的想在公开事件的回调中创建一个 cairo 上下文,只需使用它来获取 gtk.gdk.window:
myGdkWindow = mywin.get_window()
cr = myGdkWindow.cairo_create()
在@cedlemo 的(已接受)答案的帮助下,我能够在 python
中重新创建 ch01s03
Gtk+
示例。但是,我不得不导入 cairo
actual 因为 gi.repository.cairo.Context()
构造函数不存在。起初这并不明显,但也许是有道理的。这是完整的工作版本。请参阅 original C
version with comments.
from gi.repository import Gtk, Gdk
import cairo
surface = None
def clear_surface():
global surface
cr = cairo.Context(surface)
cr.set_source_rgb(1,1,1)
cr.paint()
del cr
def configure_event_cb(wid,evt):
global surface
if surface is not None:
del surface
surface = None
win = wid.get_window()
width = wid.get_allocated_width()
height = wid.get_allocated_height()
surface = win.create_similar_surface(
cairo.CONTENT_COLOR,
width,
height)
clear_surface()
return True
def draw_cb(wid,cr):
global surface
cr.set_source_surface(surface,0,0)
cr.paint()
return False
def draw_brush(wid,x,y):
global surface
cr = cairo.Context(surface)
cr.set_source_rgb(0,0,0)
cr.rectangle(x-3,y-3,6,6)
cr.fill()
del cr
wid.queue_draw_area(x-3,y-3,6,6)
def button_press_event_cb(wid,evt):
global surface
if surface is None:
return False
if evt.button == Gdk.BUTTON_PRIMARY:
draw_brush(wid,evt.x,evt.y)
elif evt.button == Gdk.BUTTON_SECONDARY:
clear_surface()
wid.queue_draw()
return True
def motion_notify_event_cb(wid,evt):
global surface
if surface is None:
return False
if evt.state & Gdk.EventMask.BUTTON_PRESS_MASK:
draw_brush(wid,evt.x,evt.y)
return True
def close_window(wid):
global surface
if surface is not None:
del surface
surface = None
Gtk.main_quit()
if __name__ == '__main__':
win = Gtk.Window()
win.set_title('Drawing Area')
win.connect('destroy',close_window)
win.set_border_width(8)
frame = Gtk.Frame()
frame.set_shadow_type(Gtk.ShadowType.IN)
win.add(frame)
da = Gtk.DrawingArea()
da.set_size_request(100,100)
frame.add(da)
da.connect('draw',draw_cb)
da.connect('configure-event',configure_event_cb)
da.connect('motion-notify-event',motion_notify_event_cb)
da.connect('button-press-event',button_press_event_cb)
da.set_events(da.get_events() | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK)
win.show_all()
Gtk.main()
我正在尝试遵循参考文档中的 Gtk+ v3 教程。特别是第一个绘图示例使用 cairo
将绘图处理到 Gtk.DrawingArea
.
https://developer.gnome.org/gtk3/stable/ch01s03.html
作为参考,我正在使用这些资源:
https://python-gtk-3-tutorial.readthedocs.org/en/latest/
http://lazka.github.io/pgi-docs/
请看一下我将 ch01s03
程序(部分)翻译成 python。我遇到的主要问题是 configure_event_cb()
程序应该创建一个 cairo.Surface
对象连接到 Gdk.Window
。我不知道如何找到这个 Gdk.Window
甚至不知道在哪里查看参考文档。
from gi.repository import Gtk, Gdk, cairo
surface = None
def clear_surface():
global surface
surface = cairo.Surface()
surface.set_source_rgb(1,1,1)
surface.paint()
def configure_event_cb(wid,evt):
global surface
if surface is not None:
surface.destroy()
surface = None
'''
Here, I am trying to implement the following C code:
surface = gdk_window_create_similar_surface(
gtk_widget_get_window(widget),
CAIRO_CONTENT_COLOR,
gtk_widget_get_allocated_width(widget),
gtk_widget_get_allocated_height(widget) );
'''
clear_surface()
return True
def close_window(wid):
global surface
if surface is not None:
surface.destroy()
Gtk.main_quit()
if __name__ == '__main__':
win = Gtk.Window(Gtk.WindowType.TOPLEVEL)
win.set_title('Drawing Area')
win.connect('destroy',close_window)
win.set_border_width(8)
frame = Gtk.Frame()
frame.set_shadow_type(Gtk.ShadowType.IN)
win.add(frame)
da = Gtk.DrawingArea()
da.set_size_request(100,100)
frame.add(da)
da.connect('configure-event',configure_event_cb)
win.show_all()
Gtk.main()
我了解到 DrawingArea 现在使用 draw 事件而不是 configure-event 这是一个简单的代码:
from gi.repository import Gtk
def draw_cb(widget, cr):
cr.set_source_rgba(0,0,0,0.5)
cr.rectangle(50,75,100,100)
cr.fill()
return False
win = Gtk.Window()
win.set_title("test")
win.set_default_size(800,600)
win.connect('delete-event', Gtk.main_quit)
da=Gtk.DrawingArea()
da.connect('draw', draw_cb)
win.add(da)
win.show_all()
Gtk.main()
但是如果你真的想在公开事件的回调中创建一个 cairo 上下文,只需使用它来获取 gtk.gdk.window:
myGdkWindow = mywin.get_window()
cr = myGdkWindow.cairo_create()
在@cedlemo 的(已接受)答案的帮助下,我能够在 python
中重新创建 ch01s03
Gtk+
示例。但是,我不得不导入 cairo
actual 因为 gi.repository.cairo.Context()
构造函数不存在。起初这并不明显,但也许是有道理的。这是完整的工作版本。请参阅 original C
version with comments.
from gi.repository import Gtk, Gdk
import cairo
surface = None
def clear_surface():
global surface
cr = cairo.Context(surface)
cr.set_source_rgb(1,1,1)
cr.paint()
del cr
def configure_event_cb(wid,evt):
global surface
if surface is not None:
del surface
surface = None
win = wid.get_window()
width = wid.get_allocated_width()
height = wid.get_allocated_height()
surface = win.create_similar_surface(
cairo.CONTENT_COLOR,
width,
height)
clear_surface()
return True
def draw_cb(wid,cr):
global surface
cr.set_source_surface(surface,0,0)
cr.paint()
return False
def draw_brush(wid,x,y):
global surface
cr = cairo.Context(surface)
cr.set_source_rgb(0,0,0)
cr.rectangle(x-3,y-3,6,6)
cr.fill()
del cr
wid.queue_draw_area(x-3,y-3,6,6)
def button_press_event_cb(wid,evt):
global surface
if surface is None:
return False
if evt.button == Gdk.BUTTON_PRIMARY:
draw_brush(wid,evt.x,evt.y)
elif evt.button == Gdk.BUTTON_SECONDARY:
clear_surface()
wid.queue_draw()
return True
def motion_notify_event_cb(wid,evt):
global surface
if surface is None:
return False
if evt.state & Gdk.EventMask.BUTTON_PRESS_MASK:
draw_brush(wid,evt.x,evt.y)
return True
def close_window(wid):
global surface
if surface is not None:
del surface
surface = None
Gtk.main_quit()
if __name__ == '__main__':
win = Gtk.Window()
win.set_title('Drawing Area')
win.connect('destroy',close_window)
win.set_border_width(8)
frame = Gtk.Frame()
frame.set_shadow_type(Gtk.ShadowType.IN)
win.add(frame)
da = Gtk.DrawingArea()
da.set_size_request(100,100)
frame.add(da)
da.connect('draw',draw_cb)
da.connect('configure-event',configure_event_cb)
da.connect('motion-notify-event',motion_notify_event_cb)
da.connect('button-press-event',button_press_event_cb)
da.set_events(da.get_events() | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK)
win.show_all()
Gtk.main()