PyGobject(三十六)布局容器之OffscreenWindow
2016-07-29 15:53
519 查看
GtkOffscreenWindow
继承关系
Methods
Virtual Methods
Properties
Signals
例一控件倒影
GdkWindow
继承关系
Methods
Virtual Methods
Properties
Signals
例二控件旋转
例三控件倒影2
我们的想法是把一个小部件和手动设置它的状态,将其添加到Gtk.OffscreenWindow,然后检索快照作为cairo.Surface或GdkPixbuf.Pixbuf。
Gtk.OffscreenWindow从Gtk.Window派生只是作为一个实现细节。应用程序不应该使用任何Gtk.Window的特定API来操作这个对象。它应被视为没有父窗口的Gtk.Bin小部件。
当包含屏幕外的小部件重绘,Gtk.OffscreenWindow会发送Gtk.Widget::damage-event信号。
代码:
代码解析:
创建两个一样的HBox,一个添加到Gtk.OffscreenWindow
一个添加到Gtk.Window。
在Gtk.Window的do_draw方法中,获取Gtk.OffscreenWindow的快照
然后用它画出两个快照,一个正常布局,一个倒立
代码
代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728
继承关系
Methods
Virtual Methods
Properties
Signals
例一控件倒影
GdkWindow
继承关系
Methods
Virtual Methods
Properties
Signals
例二控件旋转
例三控件倒影2
Gtk.OffscreenWindow
Gtk.OffscreenWindow严格意在用于获得不属于正常插件层次结构的一部分部件的快照。由于Gtk.OffscreenWindow是一个顶级小部件则无法获得与它充满窗口的快照,因为你不能装在另一个顶层一个顶级部件。我们的想法是把一个小部件和手动设置它的状态,将其添加到Gtk.OffscreenWindow,然后检索快照作为cairo.Surface或GdkPixbuf.Pixbuf。
Gtk.OffscreenWindow从Gtk.Window派生只是作为一个实现细节。应用程序不应该使用任何Gtk.Window的特定API来操作这个对象。它应被视为没有父窗口的Gtk.Bin小部件。
当包含屏幕外的小部件重绘,Gtk.OffscreenWindow会发送Gtk.Widget::damage-event信号。
继承关系
Gtk.OffscreenWindow是Gtk.Window的直接子类Methods
方法修饰词 | 方法名及参数 |
---|---|
static | new () |
get_pixbuf () | |
get_surface () |
Virtual Methods
Properties
Name | Type | Flags | Short Description |
---|
Signals
Name | Short Description |
---|
例一.控件倒影
代码:
#!/usr/bin/env python3 # Created by xiaosanyu at 16/7/17 # section 042 # # author: xiaosanyu # website: yuxiaosan.tk \ # http://blog.csdn.net/a87b01c14 # created: 16/7/17 TITLE = "GtkOffscreenWindow" DESCRIPTION = """ Gtk.OffscreenWindow is strictly intended to be used for obtaining snapshots of widgets that are not part of a normal widget hierarchy. Since Gtk.OffscreenWindow is a toplevel widget you cannot obtain snapshots of a full window with it since you cannot pack a toplevel widget in another toplevel. this demo has a bug "self.offwindow.realize()" This line of code will generate a bug when it run in gtk-demo.py please run this demo in the console """ import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gdk, GLib, GObject import cairo class OffscreenWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="GtkOffscreenWindow Effects") self.connect("delete-event", Gtk.main_quit) self.set_size_request(300, 100) self.creat_widget("1") self.creat_offwindow() def creat_widget(self, name): hbox = Gtk.HBox(spacing=6) # 不理解,为什么要在这里使用add,如果这句话往后移,会报错 if name == "1": self.add(hbox) backbutton = Gtk.Button() backbutton.add(Gtk.Image.new_from_icon_name("go-previous", 4)) entry = Gtk.Entry() applybutton = Gtk.Button.new_with_label("Apply") applybutton.connect("clicked", self.on_click, name) hbox.pack_start(backbutton, False, False, 0) hbox.pack_start(entry, True, True, 0) hbox.pack_start(applybutton, False, False, 0) return hbox @staticmethod def on_click(widget, name): print("onclick", name) def creat_offwindow(self): self.offwindow = Gtk.OffscreenWindow.new() self.offwindow.add(self.creat_widget("2")) self.offwindow.realize() def do_draw(self, cr): window = self.get_window() if Gtk.cairo_should_draw_window(cr, window): if self.offwindow: Gtk.render_background(self.get_style_context(), cr, 0, 0, self.get_allocated_width(), self.get_allocated_height()) self.offwindow.show_all() surface = self.offwindow.get_surface() height = self.offwindow.get_size().height cr.set_source_surface(surface, 0, 0) cr.paint() matrix = cairo.Matrix(1.0, 0.0, 0.3, 1.0, 0.0, 0.0) matrix.scale(1.0, -1.0) matrix.translate(-10, - 3 * height - 10) cr.transform(matrix) cr.set_source_surface(surface, 0, height) # create linear gradient as mask-pattern to fade out the source mask = cairo.LinearGradient(0.0, height, 0.0, 2 * height) mask.add_color_stop_rgba(0.0, 0.0, 0.0, 0.0, 0.0) mask.add_color_stop_rgba(0.25, 0.0, 0.0, 0.0, 0.01) mask.add_color_stop_rgba(0.5, 0.0, 0.0, 0.0, 0.25) mask.add_color_stop_rgba(0.75, 0.0, 0.0, 0.0, 0.5) mask.add_color_stop_rgba(1.0, 0.0, 0.0, 0.0, 1.0) cr.mask(mask) def main(): win = OffscreenWindow() win.show_all() Gtk.main() if __name__ == "__main__": main()
代码解析:
创建两个一样的HBox,一个添加到Gtk.OffscreenWindow
一个添加到Gtk.Window。
在Gtk.Window的do_draw方法中,获取Gtk.OffscreenWindow的快照
surface = self.offwindow.get_surface()
然后用它画出两个快照,一个正常布局,一个倒立
Gdk.Window
继承关系
Gtk.Window是GObject.Object的直接子类Methods
方法修饰词 | 方法名及参数 |
---|---|
static at_pointer () | |
static | constrain_size (geometry, flags, width, height) |
static | new (parent, attributes, attributes_mask) |
static | process_all_updates () |
static | set_debug_updates (setting) |
beep () | |
begin_move_drag (button, root_x, root_y, timestamp) | |
begin_move_drag_for_device (device, button, root_x, root_y, timestamp) | |
begin_paint_rect (rectangle) | |
begin_paint_region (region) | |
begin_resize_drag (edge, button, root_x, root_y, timestamp) | |
begin_resize_drag_for_device (edge, device, button, root_x, root_y, timestamp) | |
cairo_create () | |
configure_finished () | |
coords_from_parent (parent_x, parent_y) | |
coords_to_parent (x, y) | |
create_gl_context () | |
create_similar_image_surface (format, width, height, scale) | |
create_similar_surface (content, width, height) | |
deiconify () | |
destroy () | |
destroy_notify () | |
enable_synchronized_configure () | |
end_paint () | |
ensure_native () | |
flush () | |
focus (timestamp) | |
freeze_toplevel_updates_libgtk_only () | |
freeze_updates () | |
fullscreen () | |
fullscreen_on_monitor (monitor) | |
geometry_changed () | |
get_accept_focus () | |
get_background_pattern () | |
get_children () | |
get_children_with_user_data (user_data) | |
get_clip_region () | |
get_composited () | |
get_cursor () | |
get_decorations () | |
get_device_cursor (device) | |
get_device_events (device) | |
get_device_position (device) | |
get_device_position_double (device) | |
get_display () | |
get_drag_protocol () | |
get_effective_parent () | |
get_effective_toplevel () | |
get_event_compression () | |
get_events () | |
get_focus_on_map () | |
get_frame_clock () | |
get_frame_extents () | |
get_fullscreen_mode () | |
get_geometry () | |
get_group () | |
get_height () | |
get_modal_hint () | |
get_origin () | |
get_parent () | |
get_pass_through () | |
get_pointer () | |
get_position () | |
get_root_coords (x, y) | |
get_root_origin () | |
get_scale_factor () | |
get_screen () | |
get_source_events (source) | |
get_state () | |
get_support_multidevice () | |
get_toplevel () | |
get_type_hint () | |
get_update_area () | |
get_user_data () | |
get_visible_region () | |
get_visual () | |
get_width () | |
get_window_type () | |
has_native () | |
hide () | |
iconify () | |
input_shape_combine_region (shape_region, offset_x, offset_y) | |
invalidate_maybe_recurse (region, child_func, *user_data) | |
invalidate_rect (rect, invalidate_children) | |
invalidate_region (region, invalidate_children) | |
is_destroyed () | |
is_input_only () | |
is_shaped () | |
is_viewable () | |
is_visible () | |
lower () | |
mark_paint_from_clip (cr) | |
maximize () | |
merge_child_input_shapes () | |
merge_child_shapes () | |
move (x, y) | |
move_region (region, dx, dy) | |
move_resize (x, y, width, height) | |
peek_children () | |
process_updates (update_children) | |
raise_ () | |
register_dnd () | |
reparent (new_parent, x, y) | |
resize (width, height) | |
restack (sibling, above) | |
scroll (dx, dy) | |
set_accept_focus (accept_focus) | |
set_background (color) | |
set_background_pattern (pattern) | |
set_background_rgba (rgba) | |
set_child_input_shapes () | |
set_child_shapes () | |
set_composited (composited) | |
set_cursor (cursor) | |
set_decorations (decorations) | |
set_device_cursor (device, cursor) | |
set_device_events (device, event_mask) | |
set_event_compression (event_compression) | |
set_events (event_mask) | |
set_focus_on_map (focus_on_map) | |
set_fullscreen_mode (mode) | |
set_functions (functions) | |
set_geometry_hints (geometry, geom_mask) | |
set_group (leader) | |
set_icon_list (pixbufs) | |
set_icon_name (name) | |
set_keep_above (setting) | |
set_keep_below (setting) | |
set_modal_hint (modal) | |
set_opacity (opacity) | |
set_opaque_region (region) | |
set_override_redirect (override_redirect) | |
set_pass_through (pass_through) | |
set_role (role) | |
set_shadow_width (left, right, top, bottom) | |
set_skip_pager_hint (skips_pager) | |
set_skip_taskbar_hint (skips_taskbar) | |
set_source_events (source, event_mask) | |
set_startup_id (startup_id) | |
set_static_gravities (use_static) | |
set_support_multidevice (support_multidevice) | |
set_title (title) | |
set_transient_for (parent) | |
set_type_hint (hint) | |
set_urgency_hint (urgent) | |
set_user_data (user_data) | |
shape_combine_region (shape_region, offset_x, offset_y) | |
show () | |
show_unraised () | |
show_window_menu (event) | |
stick () | |
thaw_toplevel_updates_libgtk_only () | |
thaw_updates () | |
unfullscreen () | |
unmaximize () | |
unstick () | |
withdraw () |
Virtual Methods
do_create_surface (width, height) |
do_from_embedder (embedder_x, embedder_y, offscreen_x, offscreen_y) |
do_to_embedder (offscreen_x, offscreen_y, embedder_x, embedder_y) |
Properties
Name | Type | Flags | Short Description |
---|---|---|---|
cursor Gdk.Cursor r/w Cursor |
Signals
Name | Short Description |
---|---|
create-surface | The ::create-surface signal is emitted when an offscreen window needs its surface (re)created, which happens either when the window is first drawn to, or when the window is being resized. |
from-embedder | The ::from-embedder signal is emitted to translate coordinates in the embedder of an offscreen window to the offscreen window. |
pick-embedded-child | The ::pick-embedded-child signal is emitted to find an embedded child at the given position. |
to-embedder | The ::to-embedder signal is emitted to translate coordinates in an offscreen window to its embedder. |
例二.控件旋转
代码
#!/usr/bin/env python3 # Created by xiaosanyu at 16/7/17 # section 043 # # author: xiaosanyu # website: yuxiaosan.tk \ # http://blog.csdn.net/a87b01c14 # created: 16/7/17 TITLE = "Rotated Button" DESCRIPTION = """ Offscreen windows can be used to transform parts of a widget hierarchy. Note that the rotated button is fully functional. """ import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gdk, GLib, GObject from math import * class RotatedBin(Gtk.Bin): def __init__(self, *args, **kwargs): Gtk.Bin.__init__(self, *args, **kwargs) self.set_has_window(True) self.angle = 0.0 self.child = None self.offscreen_window = None @classmethod def new(cls, *args, **kwargs): return GObject.new(cls, *args, **kwargs) def to_child(self, widget_x, widget_y): s = sin(self.angle) c = cos(self.angle) child_area = self.child.get_allocation() w = c * child_area.width + s * child_area.height h = s * child_area.width + c * child_area.height x = widget_x y = widget_y x -= (w - child_area.width) / 2 y -= (h - child_area.height) / 2 x -= child_area.width / 2 y -= child_area.height / 2 xr = x * c + y * s yr = y * c - x * s x = xr y = yr x += child_area.width / 2 y += child_area.height / 2 return x, y def to_parent(self, offscreen_x, offscreen_y): s = sin(self.angle) c = cos(self.angle) child_area = self.child.get_allocation() w = c * child_area.width + s * child_area.height h = s * child_area.width + c * child_area.height x = offscreen_x y = offscreen_y x -= child_area.width / 2 y -= child_area.height / 2 xr = x * c - y * s yr = x * s + y * c x = xr y = yr x += child_area.width / 2 y += child_area.height / 2 x -= (w - child_area.width) / 2 y -= (h - child_area.height) / 2 return x, y def pick_offscreen_child(self, offscreen_window, widget_x, widget_y): if self.child and self.child.get_visible(): x, y = self.to_child(widget_x, widget_y) child_area = self.child.get_allocation() if 0 <= x < child_area.width and 0 <= y < child_area.height: return self.offscreen_window def offscreen_window_to_parent(self, window, parent_x, parent_y, offscreen_x, offscreen_y): parent_x, parent_y = self.to_parent(offscreen_x, offscreen_y) return parent_x, parent_y def offscreen_window_from_parent(self, window, parent_x, parent_y, offscreen_x, offscreen_y): offscreen_x, offscreen_y = self.to_child(parent_x, parent_y) return offscreen_x, offscreen_y def do_realize(self): attributes = Gdk.WindowAttr() child_requisition = Gtk.Requisition() self.set_realized(True) allocation = self.get_allocation() border_width = self.get_border_width() attributes.x = allocation.x + border_width attributes.y = allocation.y + border_width attributes.width = allocation.width - 2 * border_width attributes.height = allocation.height - 2 * border_width attributes.window_type = Gdk.WindowType.CHILD attributes.event_mask = self.get_events() \ | Gdk.EventMask.EXPOSURE_MASK \ | Gdk.EventMask.POINTER_MOTION_MASK \ | Gdk.EventMask.BUTTON_PRESS_MASK \ | Gdk.EventMask.BUTTON_RELEASE_MASK \ | Gdk.EventMask.SCROLL_MASK \ | Gdk.EventMask.ENTER_NOTIFY_MASK \ | Gdk.EventMask.LEAVE_NOTIFY_MASK attributes.visual = self.get_visual() attributes.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT attributes_mask = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.VISUAL window = Gdk.Window.new(self.get_parent_window(), attributes, attributes_mask) self.set_window(window) window.set_user_data(self) window.connect("pick-embedded-child", self.pick_offscreen_child) attributes.window_type = Gdk.WindowType.OFFSCREEN child_requisition.width = child_requisition.height = 0 if self.child and self.child.get_visible(): child_allocation = self.child.get_allocation() attributes.width = child_allocation.width attributes.height = child_allocation.height self.offscreen_window = Gdk.Window.new(self.get_screen().get_root_window(), attributes, attributes_mask) self.offscreen_window.set_user_data(self) if self.child: self.child.set_parent_window(self.offscreen_window) Gdk.offscreen_window_set_embedder(self.offscreen_window, window) self.offscreen_window.connect("to-embedder", self.offscreen_window_to_parent) self.offscreen_window.connect("from-embedder", self.offscreen_window_from_parent) self.offscreen_window.show() def do_unrealize(self): self.offscreen_window.set_user_data(None) self.offscreen_window.destroy() self.offscreen_window = None self.child.unrealize() def do_child_type(self): if self.child: return GObject.TYPE_NONE return Gtk.Widget def do_add(self, widget): if not self.child: if self.offscreen_window: widget.set_parent_window(self.offscreen_window) widget.set_parent(self) self.child = widget def do_remove(self, widget): was_visible = widget.get_visible() if self.child == widget: widget.unparent() self.child = None if was_visible and self.get_visible(): self.queue_resize() def do_forall(self, include_internals, callback, *callback_data): if not callback: return if self.child: callback(self.child, *callback_data) def set_angle(self, angle): self.angle = angle self.queue_resize() self.offscreen_window.geometry_changed() def size_request(self): requisition = Gtk.Requisition() child_requisition = Gtk.Requisition() child_requisition.width = 0 child_requisition.height = 0 if self.child and self.child.get_visible(): child_requisition = self.child.get_preferred_size()[0] s = sin(self.angle) c = cos(self.angle) w = c * child_requisition.width + s * child_requisition.height h = s * child_requisition.width + c * child_requisition.height border_width = self.get_border_width() requisition.width = border_width * 2 + w requisition.height = border_width * 2 + h return requisition def do_get_preferred_width(self): requisition = self.size_request() return requisition.width, requisition.width def do_get_preferred_height(self): requisition = self.size_request() return requisition.height, requisition.height def do_size_allocate(self, allocation): self.set_allocation(allocation) border_width = self.get_border_width() w = allocation.width - border_width * 2 h = allocation.height - border_width * 2 if self.get_realized(): self.get_window().move_resize(allocation.x + border_width, allocation.y + border_width, w, h) if self.child and self.child.get_visible(): child_allocation = Gdk.Rectangle() s = sin(self.angle) c = cos(self.angle) child_requisition = self.child.get_preferred_size()[0] child_allocation.x = 0 child_allocation.y = 0 child_allocation.height = child_requisition.height if c == 0.0: child_allocation.width = h / s elif s == 0.0: child_allocation.width = w / c else: child_allocation.width = min((w - s * child_allocation.height) / c, (h - c * child_allocation.height) / s) if self.get_realized(): self.offscreen_window.move_resize( child_allocation.x, child_allocation.y, child_allocation.width, child_allocation.height) child_allocation.x = child_allocation.y = 0 self.child.size_allocate(child_allocation) def do_damage_event(self, event): self.get_window().invalidate_rect(None, False) return True def do_draw(self, cr): window = self.get_window() if Gtk.cairo_should_draw_window(cr, window): if self.child and self.child.get_visible(): surface = Gdk.offscreen_window_get_surface(self.offscreen_window) child_area = self.child.get_allocation() # transform s = sin(self.angle) c = cos(self.angle) w = c * child_area.width + s * child_area.height h = s * child_area.width + c * child_area.height cr.translate((w - child_area.width) / 2, (h - child_area.height) / 2) cr.translate(child_area.width / 2, child_area.height / 2) cr.rotate(self.angle) cr.translate(-child_area.width / 2, -child_area.height / 2) # clip cr.rectangle( 0, 0, self.offscreen_window.get_width(), self.offscreen_window.get_height()) cr.clip() # paint cr.set_source_surface(surface, 0, 0) cr.paint() if Gtk.cairo_should_draw_window(cr, self.offscreen_window): Gtk.render_background(self.get_style_context(), cr, 0, 0, self.offscreen_window.get_width(), self.offscreen_window.get_height()) if self.child: self.propagate_draw(self.child, cr) return False class OffscreenWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="GdkOffscreenWindow Rotated Button") # self.set_size_request(200, 150) self.set_border_width(10) box = Gtk.VBox(spacing=6) scale = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0, GLib.PI_2, 0.01) scale.set_draw_value(False) box.pack_start(scale, False, False, 0) bin = RotatedBin.new() box.pack_start(bin, True, True, 0) scale.connect("value-changed", self.scale_changed, bin) button = Gtk.Button("A Button") bin.add(button) self.add(box) @staticmethod def scale_changed(scale, bin): bin.set_angle(scale.get_value()) def main(): win = OffscreenWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() if __name__ == "__main__": main()
例三.控件倒影2
#!/usr/bin/env python3 # Created by xiaosanyu at 16/7/17 # section 044 # # author: xiaosanyu # website: yuxiaosan.tk \ # http://blog.csdn.net/a87b01c14 # created: 16/7/17 TITLE = "Effects" DESCRIPTION = """ Offscreen windows can be used to render elements multiple times to achieve various effects. """ import gi import cairo gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gdk, GLib, GObject from math import * class MirrorBin(Gtk.Bin): def __init__(self, *args, **kwargs): Gtk.Bin.__init__(self, *args, **kwargs) self.set_has_window(True) self.child = None self.offscreen_window = None @classmethod def new(cls, *args, **kwargs): return GObject.new(cls, *args, **kwargs) @staticmethod def to_child(widget_x, widget_y): x = widget_x y = widget_y return x, y @staticmethod def to_parent(offscreen_x, offscreen_y): x = offscreen_x y = offscreen_y return x, y def pick_offscreen_child(self, offscreen_window, widget_x, widget_y): if self.child and self.child.get_visible(): x, y = self.to_child(widget_x, widget_y) child_area = self.child.get_allocation() if 0 <= x < child_area.width and 0 <= y < child_area.height: return self.offscreen_window def offscreen_window_to_parent(self, window, parent_x, parent_y, offscreen_x, offscreen_y): parent_x, parent_y = self.to_parent(offscreen_x, offscreen_y) return parent_x, parent_y def offscreen_window_from_parent(self, window, parent_x, parent_y, offscreen_x, offscreen_y): offscreen_x, offscreen_y = self.to_child(parent_x, parent_y) return offscreen_x, offscreen_y def do_realize(self): attributes = Gdk.WindowAttr() child_requisition = Gtk.Requisition() self.set_realized(True) allocation = self.get_allocation() border_width = self.get_border_width() attributes.x = allocation.x + border_width attributes.y = allocation.y + border_width attributes.width = allocation.width - 2 * border_width attributes.height = allocation.height - 2 * border_width attributes.window_type = Gdk.WindowType.CHILD attributes.event_mask = self.get_events() \ | Gdk.EventMask.EXPOSURE_MASK \ | Gdk.EventMask.POINTER_MOTION_MASK \ | Gdk.EventMask.BUTTON_PRESS_MASK \ | Gdk.EventMask.BUTTON_RELEASE_MASK \ | Gdk.EventMask.SCROLL_MASK \ | Gdk.EventMask.ENTER_NOTIFY_MASK \ | Gdk.EventMask.LEAVE_NOTIFY_MASK attributes.visual = self.get_visual() attributes.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT attributes_mask = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.VISUAL window = Gdk.Window.new(self.get_parent_window(), attributes, attributes_mask) self.set_window(window) window.set_user_data(self) window.connect("pick-embedded-child", self.pick_offscreen_child) attributes.window_type = Gdk.WindowType.OFFSCREEN child_requisition.width = child_requisition.height = 0 if self.child and self.child.get_visible(): child_allocation = self.child.get_allocation() attributes.width = child_allocation.width attributes.height = child_allocation.height self.offscreen_window = Gdk.Window.new(self.get_screen().get_root_window(), attributes, attributes_mask) self.offscreen_window.set_user_data(self) if self.child: self.child.set_parent_window(self.offscreen_window) Gdk.offscreen_window_set_embedder(self.offscreen_window, window) self.offscreen_window.connect("to-embedder", self.offscreen_window_to_parent) self.offscreen_window.connect("from-embedder", self.offscreen_window_from_parent) self.offscreen_window.show() def do_unrealize(self): self.offscreen_window.set_user_data(None) self.offscreen_window.destroy() self.offscreen_window = None self.child.unrealize() def do_child_type(self): if self.child: return GObject.TYPE_NONE return Gtk.Widget def do_add(self, widget): if not self.child: if self.offscreen_window: widget.set_parent_window(self.offscreen_window) widget.set_parent(self) self.child = widget def do_remove(self, widget): was_visible = widget.get_visible() if self.child == widget: widget.unparent() self.child = None if was_visible and self.get_visible(): self.queue_resize() def do_forall(self, include_internals, callback, *callback_data): if not callback: return if self.child: callback(self.child) def size_request(self): requisition = Gtk.Requisition() child_requisition = Gtk.Requisition() child_requisition.width = 0 child_requisition.height = 0 if self.child and self.child.get_visible(): child_requisition = self.child.get_preferred_size()[0] border_width = self.get_border_width() requisition.width = border_width * 2 + child_requisition.width + 10 requisition.height = border_width * 2 + + child_requisition.height * 2 + 10 return requisition def do_get_preferred_width(self): requisition = self.size_request() return requisition.width, requisition.width def do_get_preferred_height(self): requisition = self.size_request() return requisition.height, requisition.height def do_size_allocate(self, allocation): self.set_allocation(allocation) border_width = self.get_border_width() w = allocation.width - border_width * 2 h = allocation.height - border_width * 2 if self.get_realized(): self.get_window().move_resize(allocation.x + border_width, allocation.y + border_width, w, h) if self.child and self.child.get_visible(): child_allocation = Gdk.Rectangle() child_requisition = self.child.get_preferred_size()[0] child_allocation.x = 0 child_allocation.y = 0 child_allocation.height = child_requisition.height child_allocation.width = child_requisition.width if self.get_realized(): self.offscreen_window.move_resize( child_allocation.x, child_allocation.y, child_allocation.width, child_allocation.height) self.child.size_allocate(child_allocation) def do_damage_event(self, event): self.get_window().invalidate_rect(None, False) return False def do_draw(self, cr): window = self.get_window() if Gtk.cairo_should_draw_window(cr, window): if self.child and self.child.get_visible(): surface = Gdk.offscreen_window_get_surface(self.offscreen_window) height = self.offscreen_window.get_height() # paint the offscreen child cr.set_source_surface(surface, 0, 0) cr.paint() matrix = cairo.Matrix(1.0, 0.0, 0.3, 1.0, 0.0, 0.0) matrix.scale(1.0, -1.0) matrix.translate(-10, - 3 * height - 10) cr.transform(matrix) cr.set_source_surface(surface, 0, height) # create linear gradient as mask-pattern to fade out the source */ mask = cairo.LinearGradient(0.0, height, 0.0, 2 * height) mask.add_color_stop_rgba(0.0, 0.0, 0.0, 0.0, 0.0) mask.add_color_stop_rgba(0.25, 0.0, 0.0, 0.0, 0.01) mask.add_color_stop_rgba(0.5, 0.0, 0.0, 0.0, 0.25) mask.add_color_stop_rgba(0.75, 0.0, 0.0, 0.0, 0.5) mask.add_color_stop_rgba(1.0, 0.0, 0.0, 0.0, 1.0) # paint the reflection */ cr.mask(mask) elif Gtk.cairo_should_draw_window(cr, self.offscreen_window): Gtk.render_background(self.get_style_context(), cr, 0, 0, self.offscreen_window.get_width(), self.offscreen_window.get_height()) if self.child: self.propagate_draw(self.child, cr) return False class OffscreenWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="GdkOffscreenWindow Effects") # self.set_size_request(300, 150) self.set_border_width(10) vbox = Gtk.VBox() bin = MirrorBin.new() group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.VERTICAL) hbox = Gtk.HBox(spacing=6) backbutton = Gtk.Button() backbutton.add(Gtk.Image.new_from_icon_name("go-previous", 4)) group.add_widget(backbutton) entry = Gtk.Entry() entry.set_text("Hello World") entry.set_editable(True) entry.connect("focus-in-event", self.focus_in) entry.connect("focus_out_event", self.focus_out) entry.connect("changed", self.changed) group.add_widget(entry) applybutton = Gtk.Button.new_with_label("Apply") group.add_widget(applybutton) bin.connect("key-press-event", self.window_key_press_event_cb, entry) self.add(vbox) vbox.pack_start(bin, True, True, 0) bin.add(hbox) hbox.pack_start(backbutton, False, False, 0) hbox.pack_start(entry, True, True, 0) hbox.pack_start(applybutton, False, False, 0) def focus_in(self, widget, event): return True def focus_out(self, widget, event): return True def changed(self, widget): return True def window_key_press_event_cb(self, window, event, entry): if entry.is_focus(): entry.emit("insert-at-cursor", event.string) return False def main(): win = OffscreenWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() if __name__ == "__main__": main()
代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728
相关文章推荐
- Python动态类型的学习---引用的理解
- Python3写爬虫(四)多线程实现数据爬取
- 垃圾邮件过滤器 python简单实现
- 下载并遍历 names.txt 文件,输出长度最长的回文人名。
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- Python将excel导入到mysql中
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- FREEBASIC 编译可被python调用的dll函数示例
- Python 七步捉虫法