如何用 Python 和 GTK 记录用户按下鼠标按钮的位置?

How can I record the position where the user pressed the mouse button with Python and GTK?

我想让我的应用程序的用户画一些东西。我为此使用哪个信号/事件?

这是我目前得到的:

#!/usr/bin/env python

import gtk


class DrawingAreaExample:
    def __init__(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title("Drawing Area Example")
        window.set_default_size(800, 600)
        window.connect('button-press-event', self.callback)
        window.connect("destroy", lambda w: gtk.main_quit())
        self.area = gtk.DrawingArea()
        self.area.set_size_request(400, 300)
        self.pangolayout = self.area.create_pango_layout("")
        self.sw = gtk.ScrolledWindow()
        self.sw.add_with_viewport(self.area)
        self.table = gtk.Table(2, 2)
        self.table.attach(self.sw, 1, 2, 1, 2)
        window.add(self.table)
        self.area.connect("expose-event", self.area_expose_cb)
        self.area.show()
        self.sw.show()
        self.table.show()
        window.show()

    def callback(self, window, event):
        self.draw_point(int(event.x), int(event.y))

    def area_expose_cb(self, area, event):
        self.style = self.area.get_style()
        self.gc = self.style.fg_gc[gtk.STATE_NORMAL]
        return True

    def draw_point(self, x, y):
        # self.area.window.draw_point(self.gc, x, y)
        self.area.window.draw_arc(self.gc, True, x, y, 5, 5, 5, 360*64)


def main():
    gtk.main()
    return 0

if __name__ == "__main__":
    DrawingAreaExample()
    main()

button-press-event 是正确的,但是您想将它连接到 GtkDrawingArea,而不是 GtkWindow。您还需要 motion-notify-event 来处理按下按钮期间的鼠标移动。

The tutorial here will show you how to do what you want to do. There are a few other slight problems with your code (such as the use of expose-event instead of draw) that this code should show how to do right. Unfortunately it's in C; IDK if the Python GTK+ 3 tutorial有相同的例子。

我刚开始工作。感谢http://zetcode.com/gfx/pycairo/basicdrawing/的教程,对我帮助很大!

#!/usr/bin/python

"""Write on a canvas, store on-line data."""


from gi.repository import Gtk, Gdk
import time
import math
__version__ = '0.1'


class FormulaWriter(Gtk.Window):

    def __init__(self):
        super(FormulaWriter, self).__init__()
        self.odata = []  # On-line writing information, grouped by strokes

        # General properties
        self.set_title("Formula Writer %s" % __version__)
        self.resize(400, 400)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.connect("delete-event", Gtk.main_quit)

        # Set up canvas
        self.canvas = Gtk.DrawingArea()
        self.canvas.connect("draw", self.on_draw)
        self.canvas.connect("button-press-event", self.on_button_press)
        self.canvas.connect("motion-notify-event", self.on_mouse_move)
        self.canvas.connect("motion-notify-event", self.on_mouse_move)
        self.canvas.set_events(self.canvas.get_events() |
                               Gdk.EventMask.BUTTON_MOTION_MASK |
                               Gdk.EventMask.BUTTON1_MOTION_MASK |
                               Gdk.EventMask.BUTTON2_MOTION_MASK |
                               Gdk.EventMask.BUTTON3_MOTION_MASK |
                               Gdk.EventMask.BUTTON_PRESS_MASK)

        self.add(self.canvas)
        self.show_all()

    def on_button_press(self, w, event):
        """When a button is pressed, the location gets stored and the canvas
        gets updated.
        """
        self.odata.append([{'x': event.x, 'y': event.y, 'time': time.time()}])
        self.canvas.queue_draw()

    def on_mouse_move(self, w, event):
        """When mouse is moved, the mouse position gets stored."""
        point = {'x': event.x, 'y': event.y, 'time': time.time()}
        self.odata[-1].append(point)
        self.canvas.queue_draw()

    def on_draw(self, wid, cr):
        """Handler for drawing action. Draw all strokes.
        :param wid: The DrawingArea
        :param cr: Context
        """

        cr.set_source_rgb(1, 0, 0)  # All strokes get drawn in red
        cr.set_line_width(2.5)

        for stroke in self.odata:
            for i, point in enumerate(stroke):
                if len(stroke) == 1:
                    radius = 2
                    cr.arc(point['x'], point['y'], radius, 0, 2.0*math.pi)
                    cr.fill()
                    cr.stroke()
                elif i != 0:
                    cr.move_to(stroke[i-1]['x'], stroke[i-1]['y'])
                    cr.line_to(point['x'], point['y'])
                    cr.stroke()


def main():
    FormulaWriter()
    Gtk.main()


if __name__ == "__main__":
    main()