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

PyGobject(三十一)布局容器之EventBox

2016-07-28 11:09 567 查看
GtkEventBox
继承关系

Methods

Virtual Methods

Properties

Signals

例子
捕捉鼠标按键事件



附录
GdkEventButton
Fields

Gtk.EventBox

Gtk.EventBox有自己的窗口。对于那些没有自己窗口的部件捕捉事件是非常有用的

继承关系

Gtk.EventBox是Gtk.Bin的直接子类



Methods

方法修饰词方法名及参数
staticnew ()
get_above_child ()
get_visible_window ()
set_above_child (above_child)
set_visible_window (visible_window)

Virtual Methods

Properties

NameTypeFlagsShort Description
above-childboolr/w/enWhether the event-trapping window of the eventbox is above the window of the child widget as opposed to below it.
visible-windowboolr/w/enWhether the event box is visible, as opposed to invisible and only used to trap events.

Signals

NameShort Description

例子

捕捉鼠标按键事件



代码:

#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/12
# section 037
#
# author: xiaosanyu
# website: yuxiaosan.tk \
#          http://blog.csdn.net/a87b01c14 # created: 16/7/12

TITLE = "EventBox"
DESCRIPTION = """
The Gtk.EventBox widget is a subclass of Gtk.Bin which also has its own window.
It is useful since it allows you to catch events for widgets which do not have their own window.
"""
import gi

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk

class EventBoxWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="EventBox Example")
self.set_size_request(200, 200)
self.set_border_width(10)

box = Gtk.VBox()
label = Gtk.Label("press your mouse.")
box.add(label)
label = Gtk.Label()
box.add(label)
eventbox = Gtk.EventBox()
eventbox.connect("button-press-event", self.on_button_press_event, label)
eventbox.add(box)
self.add(eventbox)

@staticmethod
def on_button_press_event(widget, event, label):
# Check if right mouse button was preseed
if event.type == Gdk.EventType.BUTTON_PRESS:
if event.button == Gdk.BUTTON_PRIMARY:
label.set_label("you press The left mouse button")
if event.button == Gdk.BUTTON_MIDDLE:
label.set_label("you press The middle mouse button")
if event.button == Gdk.BUTTON_SECONDARY:
label.set_label("you press The right mouse button")

def main():
win = EventBoxWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

if __name__ == "__main__":
main()


代码解析:

创建一个Gtk.EventBox

eventbox = Gtk.EventBox()


连接Gtk.Widget::button_press_event(widget, event)信号

eventbox.connect("button-press-event", self.on_button_press_event, label)


在on_button_press_event方法中,先判断事件(Gdk.EventButton)的类别是否为按键,

再判断按下的键是哪一个



代码

#!/usr/bin/env python3
# Created by xiaosanyu at 16/7/12
# section 038
# Event Axes

# Demonstrates advanced handling of event information from exotic
# input devices.
#
# On one hand, this snippet demonstrates management of input axes,
# those contain additional information for the pointer other than
# X/Y coordinates.
#
# Input axes are dependent on hardware devices, on linux/unix you
# can see the device axes through xinput list <device>. Each time
# a different hardware device is used to move the pointer, the
# master device will be updated to match the axes it provides,
# these changes can be tracked through GdkDevice::changed, or
# checking gdk_event_get_source_device().
#
# On the other hand, this demo handles basic multitouch events,
# each event coming from an specific touchpoint will contain a
# GdkEventSequence that's unique for its lifetime, so multiple
# touchpoints can be tracked.
# author: xiaosanyu
# website: yuxiaosan.tk \
#          http://blog.csdn.net/a87b01c14 # created: 16/7/12

TITLE = "EventBox(1)"
DESCRIPTION = ""
import gi
import cairo

gi.require_version('Gtk', '3.0')
gi.require_version('PangoCairo', '1.0')
from gi.repository import Gtk, Gdk, GLib, PangoCairo, GObject

class AxesInfo(object):
def __init__(self, event=None, last_source=None, last_tool=None, axes=None, color=None, x=None, y=None):
# GObject.GObject.__init__(self)
self.event = event
self.last_source = last_source  # Gdk.Device
self.last_tool = last_tool  # Gdk.DeviceTool
self.axes = axes  # [Gdk.EventMotion.axes] or [Gdk.EventButton.axes]
self.color = color  # Gdk.RGBA
self.x = x  # double
self.y = y  # double

class EventData(object):
def __init__(self, pointer_info=None, touch_info=None):
# GObject.GObject.__init__(self)
self.pointer_info = pointer_info  # dict {Gdk.Device}
self.touch_info = touch_info  # dict {Gdk.EventSequence}

colors = ("black", "orchid", "fuchsia", "indigo", "thistle", "sienna",
"azure", "plum", "lime", "navy", "maroon", "burlywood")

cur_color = 0

class EventBoxWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Event Axes")
self.set_default_size(400, 400)

eventbox = Gtk.EventBox()
eventbox.set_support_multidevice(True)
eventbox.add_events(
Gdk.EventMask.POINTER_MOTION_MASK |
Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.BUTTON_RELEASE_MASK |
Gdk.EventMask.SMOOTH_SCROLL_MASK |
Gdk.EventMask.ENTER_NOTIFY_MASK |
Gdk.EventMask.LEAVE_NOTIFY_MASK |
Gdk.EventMask.TOUCH_MASK)

event_data = self.event_data_new()

eventbox.connect("event", self.event_cb, event_data)
eventbox.connect("draw", self.draw_cb, event_data)
self.add(eventbox)

@staticmethod
def axes_info_new():
global cur_color
info = AxesInfo()
info.color = Gdk.RGBA.from_color(Gdk.Color.parse(colors[cur_color])[1])

cur_color = (cur_color + 1) % len(colors)

return info

@staticmethod
def event_data_new():
data = EventData()
data.pointer_info = {}
data.touch_info = {}

return data

def update_axes_from_event(self, event, data):
device = event.get_device()
source_device = event.get_source_device()
sequence = event.get_event_sequence()
tool = event.get_device_tool()
if event.type == Gdk.EventType.TOUCH_END or event.type == Gdk.EventType.TOUCH_CANCEL:
return data.touch_info.pop(sequence, False)

elif event.type == Gdk.EventType.LEAVE_NOTIFY:
return data.pointer_info.pop(device, False)

if not sequence:
info = data.pointer_info.get(device, None)

if not info:
info = self.axes_info_new()
data.pointer_info.setdefault(device, info)
else:
info = data.touch_info.get(sequence, None)

if not info:
info = self.axes_info_new()
data.touch_info.setdefault(sequence, info)

info.event = event
if info.last_source != source_device:
info.last_source = source_device

if info.last_tool != tool:
info.last_tool = tool
info.axes = None

if event.type == Gdk.EventType.TOUCH_BEGIN or event.type == Gdk.EventType.TOUCH_UPDATE:
if sequence and event.touch.emulating_pointer:
data.pointer_info.remove(device)
if event.type == Gdk.EventType.MOTION_NOTIFY:
info.axes = [event.motion.axes for _ in range(source_device.get_n_axes())]
elif event.type == Gdk.EventType.BUTTON_PRESS or event.type == Gdk.EventType.BUTTON_RELEASE:
info.axes = [event.button.axes for _ in range(source_device.get_n_axes())]
rlt, info.x, info.y = event.get_coords()

def event_cb(self, widget, event, user_data):
self.update_axes_from_event(event, user_data)
widget.queue_draw()
return False

@staticmethod
def render_arrow(cr, x_diff, y_diff, label):
cr.save()
cr.new_path()
cr.move_to(0, 0)
cr.line_to(x_diff, y_diff)
cr.stroke()

cr.move_to(x_diff, y_diff)
cr.show_text(label)

cr.restore()

@staticmethod
def draw_axes_info(widget, cr, info, allocation):
axes = info.last_source.get_axes()
cr.save()

cr.set_line_width(1)
Gdk.cairo_set_source_rgba(cr, info.color)

cr.move_to(0, info.y)
cr.line_to(allocation.width, info.y)
cr.move_to(info.x, 0)
cr.line_to(info.x, allocation.height)
cr.stroke()
cr.translate(info.x, info.y)
if not info.axes:
cr.restore()
return
if axes & Gdk.AxisFlags.PRESSURE:
_, pressure = info.event.get_axis(Gdk.AxisUse.PRESSURE)

pattern = cairo.RadialGradient(0, 0, 0, 0, 0, 100)
pattern.add_color_stop_rgba(pressure, 1, 0, 0, pressure)
pattern.add_color_stop_rgba(1, 0, 0, 1, 0)

cr.set_source(pattern)

cr.arc(0, 0, 100, 0, 2 * GLib.PI)
cr.fill()

if axes & Gdk.AxisFlags.XTILT and axes & Gdk.AxisFlags.YTILT:
_, tilt_x = info.last_source.get_axis(Gdk.AxisUse.XTILT)
_, tilt_y = info.event.get_axis(Gdk.AxisUse.YTILT)

EventBoxWindow.render_arrow(cr, tilt_x * 100, tilt_y * 100, "Tilt")

if axes & Gdk.AxisFlags.DISTANCE:
dashes = (5.0, 5.0)
_, distance = info.event.get_axis(Gdk.AxisFlags.DISTANCE)

cr.save()

cr.move_to(distance * 100, 0)

cr.set_source_rgb(0.0, 0.0, 0.0)
cr.set_dash(dashes, 2, 0.0)
cr.arc(0, 0, distance * 100, 0, 2 * GLib.PI)
cr.stroke()

cr.move_to(0, -distance * 100)
extents = cr.text_extents("Distance")
cr.rel_move_to(-extents.width / 2, 0)
cr.show_text("Distance")

cr.move_to(0, 0)

cr.restore()

if axes & Gdk.AxisFlags.WHEEL:
_, wheel = info.event.get_axis(Gdk.AxisUse.WHEEL)

cr.save()
cr.set_line_width(10)
cr.set_source_rgba(0, 0, 0, 0.5)

cr.new_sub_path()
cr.arc(0, 0, 100, 0, wheel * 2 * GLib.PI)
cr.stroke()
cr.restore()

if axes & Gdk.AxisFlags.ROTATION:
_, rotation = info.event.get_axis(Gdk.AxisUse.ROTATION)
rotation *= 2 * GLib.PI

cr.save()
cr.rotate(- GLib.PI / 2)
cr.set_line_cap(cairo.LINE_CAP_ROUND)
cr.set_line_width(5)

cr.new_sub_path()
cr.arc(0, 0, 100, 0, rotation)
cr.stroke()
cr.restore()

if axes & Gdk.AxisFlags.SLIDER:
_, slider = info.event.get_axis(Gdk.AxisUse.SLIDER)

cr.save()

cr.move_to(0, -10)
cr.rel_line_to(0, -50)
cr.rel_line_to(10, 0)
cr.rel_line_to(-5, 50)
cr.close_path()

cr.clip_preserve()

pattern = cairo.LinearGradient(0, -10, 0, -60)
pattern.add_color_stop_rgb(0, 0, 1, 0)
pattern.add_color_stop_rgb(1, 1, 0, 0)
cr.set_source(pattern)

mask = cairo.LinearGradient(0, -10, 0, -60)
mask.add_color_stop_rgba(0, 0, 0, 0, 1)
mask.add_color_stop_rgba(slider, 0, 0, 0, 1)
mask.add_color_stop_rgba(slider, 0, 0, 0, 0)
mask.add_color_stop_rgba(1, 0, 0, 0, 0)
cr.mask(mask)

cr.set_source_rgb(0, 0, 0)
cr.stroke()

cr.restore()

if axes & Gdk.AxisFlags.X and axes & Gdk.AxisFlags.Y:
# Tilt
cr.save()
_, tilt_x = info.event.get_axis(Gdk.AxisUse.X)
_, tilt_y = info.event.get_axis(Gdk.AxisUse.Y)

EventBoxWindow.render_arrow(cr, tilt_x, tilt_y, "Tilt")
cr.restore()

# pressure
cr.save()
_, pressure = info.event.get_axis(Gdk.AxisUse.X)

pattern = cairo.RadialGradient(0, 0, 0, 0, 0, 100)
pattern.add_color_stop_rgba(pressure, 1, 0, 0, pressure)
pattern.add_color_stop_rgba(1, 0, 0, 1, 0)

cr.set_source(pattern)

cr.arc(0, 0, 50, 0, 2 * GLib.PI)
cr.fill()
cr.restore()

# dashes
dashes = (5.0, 5.0)
_, distance = info.event.get_axis(Gdk.AxisUse.X)
cr.save()

cr.move_to(distance, 0)

cr.set_dash(dashes)
cr.arc(0, 0, distance, 0, 2 * GLib.PI)
cr.stroke()

cr.move_to(0, -distance)
extents = cr.text_extents("Distance")
cr.rel_move_to(-extents[3] / 2, 0)
cr.show_text("Distance")

cr.move_to(0, 0)

cr.restore()

# slider
slider = 1
cr.save()

cr.move_to(0, -10)
cr.rel_line_to(0, -50)
cr.rel_line_to(10, 0)
cr.rel_line_to(-5, 50)
cr.close_path()

cr.clip_preserve()

pattern = cairo.LinearGradient(0, -10, 0, -60)
pattern.add_color_stop_rgb(0, 0, 1, 0)
pattern.add_color_stop_rgb(1, 1, 0, 0)
cr.set_source(pattern)

mask = cairo.LinearGradient(0, -10, 0, -60)
mask.add_color_stop_rgba(0, 0, 0, 0, 1)
mask.add_color_stop_rgba(slider, 0, 0, 0, 1)
mask.add_color_stop_rgba(slider, 0, 0, 0, 0)
mask.add_color_stop_rgba(1, 0, 0, 0, 0)
cr.mask(mask)

cr.set_source_rgb(0, 0, 0)
cr.stroke()

cr.restore()

#
cr.save()
cr.set_line_cap(cairo.LINE_CAP_ROUND)
cr.set_line_width(5)

cr.new_sub_path()
cr.arc(0, 0, 120, 0, 2 * GLib.PI)
cr.stroke()
cr.restore()

cr.restore()

@staticmethod
def tool_type_to_string(tool_type):
if tool_type == Gdk.InputSource.PEN:
return "Pen"
elif tool_type == Gdk.InputSource.ERASER:
return "Eraser"
elif tool_type == Gdk.InputSource.BRUSH:
return "Brush"
elif tool_type == Gdk.InputSource.PENCIL:
return "Pencil"
elif tool_type == Gdk.InputSource.AIRBRUSH:
return "Airbrush"
elif tool_type == Gdk.InputSource.MOUSE:
return "Mouse"
elif tool_type == Gdk.InputSource.LENS:
return "Lens cursor"
elif tool_type == Gdk.InputSource.UNKNOWN:
return "Unknown"
else:
return "Unknown"

@staticmethod
def draw_device_info(widget, cr, sequence, y, info):
cr.save()

string = "Source: " + info.last_source.get_name()

if sequence:
string += "\nSequence: " + str(sequence)

if info.last_tool:
tool_type = EventBoxWindow.tool_type_to_string(info.last_tool.get_tool_type())
serial = info.last_tool.get_serial()
string += "\nTool: " + tool_type

if serial != 0:
string += ", Serial: %lx" % serial

cr.move_to(10, y)
layout = widget.create_pango_layout(string)
PangoCairo.show_layout(cr, layout)
cr.stroke()
height = layout.get_pixel_size()[1]

Gdk.cairo_set_source_rgba(cr, info.color)
cr.set_line_width(10)
cr.move_to(0, y)

y = y + height
cr.line_to(0, y)
cr.stroke()

cr.restore()
return y

def draw_cb(self, widget, cr, user_data):
y = 0
data = user_data
allocation = widget.get_allocation()

# Draw Abs info
for key, value in data.pointer_info.items():
# run this
self.draw_axes_info(widget, cr, value, allocation)
for key, value in data.touch_info.items():
self.draw_axes_info(widget, cr, value, allocation)

# Draw name, color legend and misc data
for key, value in data.pointer_info.items():
# run this
self.draw_device_info(widget, cr, None, y, value)
for key, value in data.touch_info.items():
self.draw_device_info(widget, cr, key, y, value)
return False

def main():
win = EventBoxWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

if __name__ == "__main__":
main()


关于画图可参见Cairo系列

附录

Gdk.EventButton

Fields

NameTypeAccessDescription
axesfloatr/w移动到设备的(x,y)位置, 如果设备为鼠标这个值为None.
buttonintr/w按下或释放的键值 值为1到5。通常1是鼠标左键, 2是中间键, 3是右键.
deviceGdk.Devicer/wthe master device that the event originated from. Use Gdk.Event.get_source_device() to get the slave device.
send_eventintr/wTrue if the event was sent explicitly.
stateGdk.ModifierTyper/wa bit-mask representing the state of the modifier keys (e.g. Control, Shift and Alt) and the pointer buttons. See Gdk.ModifierType.
timeintr/w鼠标点击时的时间
typeGdk.EventTyper/w事件的类别.
windowGdk.Windowr/wthe window which received the event.
xfloatr/w相对于依附的window的x轴位置.
x_rootfloatr/w相对于屏幕的x轴位置.
yfloatr/w相对于依附的window的y轴位置.
y_rootfloatr/w相对于屏幕的y轴位置.
代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息