您的位置:首页 > 移动开发 > Objective-C

PyGobject(三十六)布局容器之OffscreenWindow

2016-07-29 15:53 519 查看
GtkOffscreenWindow
继承关系

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

方法修饰词方法名及参数
staticnew ()
get_pixbuf ()
get_surface ()

Virtual Methods

Properties

NameTypeFlagsShort Description

Signals

NameShort 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 ()
staticconstrain_size (geometry, flags, width, height)
staticnew (parent, attributes, attributes_mask)
staticprocess_all_updates ()
staticset_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

NameTypeFlagsShort Description
cursor Gdk.Cursor r/w Cursor

Signals

NameShort Description
create-surfaceThe ::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-embedderThe ::from-embedder signal is emitted to translate coordinates
in the embedder of an offscreen window to the offscreen window.
pick-embedded-childThe ::pick-embedded-child signal is emitted to find an embedded
child at the given position.
to-embedderThe ::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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息