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

  • GtkEventBox
    • 继承关系
    • Methods
    • Virtual Methods
    • Properties
    • Signals
    • 例子
      • 捕捉鼠标按键事件
  • 附录
    • GdkEventButton
      • Fields

Gtk.EventBox

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

继承关系

Gtk.EventBox是Gtk.Bin的直接子类
PyGobject(三十一)布局容器之EventBox_第1张图片

Methods

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

Virtual Methods

Properties

Name Type Flags Short Description
above-child bool r/w/en Whether the event-trapping window of the eventbox is above the window of the child widget as opposed to below it.
visible-window bool r/w/en Whether the event box is visible, as opposed to invisible and only used to trap events.

Signals

Name Short Description

例子

捕捉鼠标按键事件

PyGobject(三十一)布局容器之EventBox_第2张图片
代码:

#!/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)的类别是否为按键,
再判断按下的键是哪一个

PyGobject(三十一)布局容器之EventBox_第3张图片

代码

#!/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 . 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

Name Type Access Description
axes float r/w 移动到设备的(x,y)位置, 如果设备为鼠标这个值为None.
button int r/w 按下或释放的键值 值为1到5。通常1是鼠标左键, 2是中间键, 3是右键.
device Gdk.Device r/w the master device that the event originated from. Use Gdk.Event.get_source_device() to get the slave device.
send_event int r/w True if the event was sent explicitly.
state Gdk.ModifierType r/w a bit-mask representing the state of the modifier keys (e.g. Control, Shift and Alt) and the pointer buttons. See Gdk.ModifierType.
time int r/w 鼠标点击时的时间
type Gdk.EventType r/w 事件的类别.
window Gdk.Window r/w the window which received the event.
x float r/w 相对于依附的window的x轴位置.
x_root float r/w 相对于屏幕的x轴位置.
y float r/w 相对于依附的window的y轴位置.
y_root float r/w 相对于屏幕的y轴位置.





代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728

你可能感兴趣的:(PyGObject,PyGobject详解)