how to make tkinter event work when <button-1> is pressed?

前端 未结 1 808
天命终不由人
天命终不由人 2021-01-21 19:01

I want to fill rectangles just like in paint. When mouse button is pressed I want every rectangle I enter to be filled and otherwise I want no event to take place.

相关标签:
1条回答
  • 2021-01-21 19:59

    There's no need to use <Enter> at all. Try:

    from tkinter import Canvas
    import tkinter
    
    _width = 50
    _height = 50
    _size = 8
    
    root = tkinter.Tk()
    root.title("draw me a lovely matrix")
    canv = Canvas(root, width=_width * _size, height=_height * _size)
    rects = []
    
    # B1-Motion activates every time the mouse is moved with button 1 held down
    # See https://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
    # We fill every item that the mouse comes in contact with while button 1 is held
    # The tag tied to the item the event was called on, "current", points to the
    #   item under the pointer when the button was pressed, i.e. the first box.
    # Only the x and y properties change, so we configure the item closest to those.
    def motion(event):
      canv.itemconfig(canv.find_closest(event.x, event.y), fill="#aaa")
    canv.bind("<B1-Motion>", motion)
    
    for i in range(_size):
      for j in range(_size):
        rects.append(canv.create_rectangle(_width * j, _height * i, _width * (j + 1), _height * (i + 1), fill="#fff", width=0))
        # don't need to bind anything to <Enter>
    
    canv.pack()
    root.mainloop()
    

    Unfortunately, there's no possible solution using <Enter>. The following non-working code would theoretically be correct if <Enter> worked the way you wanted it to.

    import tkinter
    
    _width = 50
    _height = 50
    _size = 8
    
    root = tkinter.Tk()
    root.title("draw me a lovely matrix")
    canv = tkinter.Canvas(root, width=_width * _size, height=_height * _size)
    rects = []
    
    # This javascript-like approach doesn't work in tkinter because
    # <Enter> and <Leave> events aren't called while any mouse buttons
    # are held.
    def fill(tag):
      canv.itemconfig(tag, fill="#aaa")
    def enter(event):
      fill("current")
    def mousedown(event):
      fill("current")
      canv.tag_bind("all", "<Enter>", enter, add="+")
    def mouseup(event):
      canv.tag_unbind("all", "<Enter>")
    canv.bind("<Button-1>", mousedown)
    canv.bind("<ButtonRelease-1>", mouseup)
    
    for i in range(_size):
      for j in range(_size):
        rects.append(canv.create_rectangle(_width * j, _height * i, _width * (j + 1), _height * (i + 1), fill="#fff", width=0))
    
    canv.pack()
    root.mainloop()
    

    Tested in python 3.8.2, tkinter 8.6

    0 讨论(0)
提交回复
热议问题