FAQ
Tkinter makes it very easy to drag jpeg images around on a
canvas, but I would like to have a "target" change color when
the cursor dragging an image passes over it. I seem to be
blocked by the fact that the callbacks that might tell the
target that the mouse has entered it (<Enter>, <Any-Enter>,
even <Motion>) aren't called if the mouse's button is down.
What am I missing? Have I failed to find the right Tkinter
document? Is Tkinter the wrong tool for this job? Thanks.

--
To email me, substitute nowhere->spamcop, invalid->net.

Search Discussions

  • Guilherme Polo at Jun 20, 2008 at 4:41 pm

    On Fri, Jun 20, 2008 at 1:11 PM, Peter Pearson wrote:
    Tkinter makes it very easy to drag jpeg images around on a
    canvas, but I would like to have a "target" change color when
    the cursor dragging an image passes over it. I seem to be
    blocked by the fact that the callbacks that might tell the
    target that the mouse has entered it (<Enter>, <Any-Enter>,
    even <Motion>) aren't called if the mouse's button is down.
    What am I missing? Have I failed to find the right Tkinter
    document? Is Tkinter the wrong tool for this job? Thanks.
    I believe the only way to achieve this is binding <Motion> to the
    entire canvas, then checking if the x, y coords are inside the
    "target".
    --
    To email me, substitute nowhere->spamcop, invalid->net.
    --
    http://mail.python.org/mailman/listinfo/python-list
    --
    -- Guilherme H. Polo Goncalves
  • Matimus at Jun 20, 2008 at 6:10 pm

    On Jun 20, 9:11?am, Peter Pearson wrote:
    Tkinter makes it very easy to drag jpeg images around on a
    canvas, but I would like to have a "target" change color when
    the cursor dragging an image passes over it. ?I seem to be
    blocked by the fact that the callbacks that might tell the
    target that the mouse has entered it (<Enter>, <Any-Enter>,
    even <Motion>) aren't called if the mouse's button is down.
    What am I missing? ?Have I failed to find the right Tkinter
    document? ?Is Tkinter the wrong tool for this job? ?Thanks.

    --
    To email me, substitute nowhere->spamcop, invalid->net.
    I have used a combination of <Motion> and <B1-Motion>. You might also
    throw in a <Button-1> event to keep track of whether or not the mouse
    button was down when it entered the widget or not.

    Depending on what you really want to do though, you might take
    advantage of the 'active' state:

    import Tkinter as tk

    can = tk.Canvas()
    can.pack(fill=tk.BOTH, expand=True)

    can.create_rectangle(
    10,10,100,100,
    fill="black",
    activewidth=5,
    activeoutline="blue"
    )

    can.mainloop()

    The 'active*' options take effect when the mouse is on top of that
    item.

    If all you are _really_ interested in is a visual indicator, this
    should work for you. Note that there is also a disabled state. I only
    discovered this by looking at the options available and guessing.
    from pprint import pprint
    import Tkinter as tk
    can = tk.Canvas()
    can.pack(fill=tk.BOTH, expand=True)
    r = can.create_rectangle(10,10,100,100)
    pprint(can.itemconfig(r))
    {'activedash': ('activedash', '', '', '', ''),
    'activefill': ('activefill', '', '', '', ''),
    'activeoutline': ('activeoutline', '', '', '', ''),
    'activeoutlinestipple': ('activeoutlinestipple', '', '', '', ''),
    'activestipple': ('activestipple', '', '', '', ''),
    'activewidth': ('activewidth', '', '', '0.0', '0.0'),
    'dash': ('dash', '', '', '', ''),
    'dashoffset': ('dashoffset', '', '', '0', '0'),
    'disableddash': ('disableddash', '', '', '', ''),
    'disabledfill': ('disabledfill', '', '', '', ''),
    'disabledoutline': ('disabledoutline', '', '', '', ''),
    'disabledoutlinestipple': ('disabledoutlinestipple', '', '', '', ''),
    'disabledstipple': ('disabledstipple', '', '', '', ''),
    'disabledwidth': ('disabledwidth', '', '', '0.0', '0'),
    'fill': ('fill', '', '', '', ''),
    'offset': ('offset', '', '', '0,0', '0,0'),
    'outline': ('outline', '', '', 'black', 'black'),
    'outlineoffset': ('outlineoffset', '', '', '0,0', '0,0'),
    'outlinestipple': ('outlinestipple', '', '', '', ''),
    'state': ('state', '', '', '', ''),
    'stipple': ('stipple', '', '', '', ''),
    'tags': ('tags', '', '', '', ''),
    'width': ('width', '', '', '1.0', '1.0')}

    The 'state' option can be set to 'normal', 'hidden' or 'disabled'. So
    if you want to make your canvas items look different when they are
    disabled, set the disabled* options and set 'state' to 'disabled'.

    Matt
  • Matimus at Jun 20, 2008 at 9:10 pm

    On Jun 20, 11:10?am, Matimus wrote:
    On Jun 20, 9:11?am, Peter Pearson wrote:

    Tkinter makes it very easy to drag jpeg images around on a
    canvas, but I would like to have a "target" change color when
    the cursor dragging an image passes over it. ?I seem to be
    blocked by the fact that the callbacks that might tell the
    target that the mouse has entered it (<Enter>, <Any-Enter>,
    even <Motion>) aren't called if the mouse's button is down.
    What am I missing? ?Have I failed to find the right Tkinter
    document? ?Is Tkinter the wrong tool for this job? ?Thanks.
    --
    To email me, substitute nowhere->spamcop, invalid->net.
    I have used a combination of <Motion> and <B1-Motion>. You might also
    throw in a <Button-1> event to keep track of whether or not the mouse
    button was down when it entered the widget or not.

    Depending on what you really want to do though, you might take
    advantage of the 'active' state:

    import Tkinter as tk

    can = tk.Canvas()
    can.pack(fill=tk.BOTH, expand=True)

    can.create_rectangle(
    ? ? ? ? 10,10,100,100,
    ? ? ? ? fill="black",
    ? ? ? ? activewidth=5,
    ? ? ? ? activeoutline="blue"
    ? ? ? ? )

    can.mainloop()

    The 'active*' options take effect when the mouse is on top of that
    item.

    If all you are _really_ interested in is a visual indicator, this
    should work for you. Note that there is also a disabled state. I only
    discovered this by looking at the options available and guessing.
    from pprint import pprint
    import Tkinter as tk
    can = tk.Canvas()
    can.pack(fill=tk.BOTH, expand=True)
    r = can.create_rectangle(10,10,100,100)
    pprint(can.itemconfig(r))
    {'activedash': ('activedash', '', '', '', ''),
    ?'activefill': ('activefill', '', '', '', ''),
    ?'activeoutline': ('activeoutline', '', '', '', ''),
    ?'activeoutlinestipple': ('activeoutlinestipple', '', '', '', ''),
    ?'activestipple': ('activestipple', '', '', '', ''),
    ?'activewidth': ('activewidth', '', '', '0.0', '0.0'),
    ?'dash': ('dash', '', '', '', ''),
    ?'dashoffset': ('dashoffset', '', '', '0', '0'),
    ?'disableddash': ('disableddash', '', '', '', ''),
    ?'disabledfill': ('disabledfill', '', '', '', ''),
    ?'disabledoutline': ('disabledoutline', '', '', '', ''),
    ?'disabledoutlinestipple': ('disabledoutlinestipple', '', '', '', ''),
    ?'disabledstipple': ('disabledstipple', '', '', '', ''),
    ?'disabledwidth': ('disabledwidth', '', '', '0.0', '0'),
    ?'fill': ('fill', '', '', '', ''),
    ?'offset': ('offset', '', '', '0,0', '0,0'),
    ?'outline': ('outline', '', '', 'black', 'black'),
    ?'outlineoffset': ('outlineoffset', '', '', '0,0', '0,0'),
    ?'outlinestipple': ('outlinestipple', '', '', '', ''),
    ?'state': ('state', '', '', '', ''),
    ?'stipple': ('stipple', '', '', '', ''),
    ?'tags': ('tags', '', '', '', ''),
    ?'width': ('width', '', '', '1.0', '1.0')}

    The 'state' option can be set to 'normal', 'hidden' or 'disabled'. So
    if you want to make your canvas items look different when they are
    disabled, set the disabled* options and set 'state' to 'disabled'.

    Matt
    I appologize. I didn't actually test this before posting the code, but
    if you have the mouse button down before entering an item on the
    canvas, even the active state doesn't seem apply. So, well, I hope
    someone finds this information useful, but I guess it isn't going to
    solve the original posters issue.

    Matt
  • Hamish McKenzie at Jun 20, 2008 at 9:19 pm
    I have this class:

    class Vector(object):
    TOL = 1e-5
    def __eq__( self, other, tolerance=TOL ):
    print tolerance


    shortened for clarity obviously. so I want to subclass this class like
    so:

    class BigVector(Vector)
    TOL = 100


    for example if I was working with large vectors which I knew would never
    be very close hence the large tolerance. this doesn't work however -
    the TOL class variable, while overridden in BigVector, is still using
    the Vector.TOL variable in the __eq__ method.


    which kinda makes sense to a certain degree, but how do I get the
    behaviour where doing:

    BigVector().__eq__( otherVec )


    prints 100 instead of 1e-5?

    does this question make sense? not sure how clearly I'm phrasing my
    question... any of you guys python experts?


    I *could* do this, but its ugly:

    class Vector(object):
    TOL = 1e-5
    def __eq__( self, other, tolerance=None ):
    if tolerance is None: tolerance = self.TOL
    print tolerance
  • Guilherme Polo at Jun 20, 2008 at 10:20 pm

    On Fri, Jun 20, 2008 at 6:19 PM, Hamish McKenzie wrote:

    I have this class:

    class Vector(object):
    TOL = 1e-5
    def __eq__( self, other, tolerance=TOL ):
    print tolerance


    shortened for clarity obviously. so I want to subclass this class like
    so:

    class BigVector(Vector)
    TOL = 100


    for example if I was working with large vectors which I knew would never
    be very close hence the large tolerance. this doesn't work however -
    the TOL class variable, while overridden in BigVector, is still using
    the Vector.TOL variable in the __eq__ method.


    which kinda makes sense to a certain degree, but how do I get the
    behaviour where doing:

    BigVector().__eq__( otherVec )
    No, don't do this. Just do "avector == othervector"

    prints 100 instead of 1e-5?

    does this question make sense? not sure how clearly I'm phrasing my
    question... any of you guys python experts?


    I *could* do this, but its ugly:

    class Vector(object):
    TOL = 1e-5
    def __eq__( self, other, tolerance=None ):
    if tolerance is None: tolerance = self.TOL
    print tolerance
    class Vector(object):
    TOL = 1e-5
    def __eq__(self, other):
    print self.TOL


    --
    -- Guilherme H. Polo Goncalves
  • Eric Brunel at Jun 23, 2008 at 9:08 am
    Preamble: when posting a brand new question, you'd better not replying to
    an existing completely unrelated message. In most viewers, this will cause
    your message to appear in the thread for the original question and far
    less people will see it. So better create a brand new thread.

    On Fri, 20 Jun 2008 23:19:37 +0200, Hamish McKenzie
    wrote:
    I have this class:

    class Vector(object):
    TOL = 1e-5
    def __eq__( self, other, tolerance=TOL ):
    print tolerance


    shortened for clarity obviously. so I want to subclass this class like
    so:

    class BigVector(Vector)
    TOL = 100


    for example if I was working with large vectors which I knew would never
    be very close hence the large tolerance. this doesn't work however -
    the TOL class variable, while overridden in BigVector, is still using
    the Vector.TOL variable in the __eq__ method.


    which kinda makes sense to a certain degree, but how do I get the
    behaviour where doing:

    BigVector().__eq__( otherVec )


    prints 100 instead of 1e-5?

    does this question make sense? not sure how clearly I'm phrasing my
    question... any of you guys python experts?
    There's just no way. The default values for function/method arguments are
    evaluated when the function definition is interpreted. When the __eq__
    method is defined, TOL is 1e-5, so that will be the value used in the
    method, whatever you may do afterwards.
    I *could* do this, but its ugly:

    class Vector(object):
    TOL = 1e-5
    def __eq__( self, other, tolerance=None ):
    if tolerance is None: tolerance = self.TOL
    print tolerance
    Well, ugliness is in the eye of the beholder... ;-) Even if you find it
    ugly, that's the Python way to do it.

    HTH
    --
    python -c "print ''.join([chr(154 - ord(c)) for c in
    'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
  • Peter Pearson at Jun 23, 2008 at 2:41 am

    On Fri, 20 Jun 2008 13:41:35 -0300, Guilherme Polo wrote:
    On Fri, Jun 20, 2008 at 1:11 PM, Peter Pearson wrote:
    Tkinter makes it very easy to drag jpeg images around on a
    canvas, but I would like to have a "target" change color when
    the cursor dragging an image passes over it. I seem to be
    blocked by the fact that the callbacks that might tell the
    target that the mouse has entered it (<Enter>, <Any-Enter>,
    even <Motion>) aren't called if the mouse's button is down.
    What am I missing? Have I failed to find the right Tkinter
    document? Is Tkinter the wrong tool for this job? Thanks.
    I believe the only way to achieve this is binding <Motion> to the
    entire canvas, then checking if the x, y coords are inside the
    "target".
    Ugh. OK, thanks.

    --
    To email me, substitute nowhere->spamcop, invalid->net.
  • Simon Forman at Jun 23, 2008 at 4:53 am

    On Jun 22, 7:41?pm, Peter Pearson wrote:
    On Fri, 20 Jun 2008 13:41:35 -0300, Guilherme Polo wrote:
    On Fri, Jun 20, 2008 at 1:11 PM, Peter Pearson wrote:
    Tkinter makes it very easy to drag jpeg images around on a
    canvas, but I would like to have a "target" change color when
    the cursor dragging an image passes over it. ?I seem to be
    blocked by the fact that the callbacks that might tell the
    target that the mouse has entered it (<Enter>, <Any-Enter>,
    even <Motion>) aren't called if the mouse's button is down.
    What am I missing? ?Have I failed to find the right Tkinter
    document? ?Is Tkinter the wrong tool for this job? ?Thanks.
    I believe the only way to achieve this is binding <Motion> to the
    entire canvas, then checking if the x, y coords are inside the
    "target".
    Ugh. ?OK, thanks.

    --
    To email me, substitute nowhere->spamcop, invalid->net.

    Yep, but it's not so bad:

    from Tkinter import *

    c = Canvas()
    c.pack()
    i = c.create_oval(1, 1, 100, 100, fill='green')

    def cb(e):
    items = c.find_overlapping(
    e.x, e.y,
    e.x + 1, e.y + 1
    )
    if not items:
    return
    print items

    c.bind("<B1-Motion>", cb)

    mainloop()




    The c.find_overlapping() method returns a tuple. I believe the item
    ids in the tuple (if any) will be in the same order as the items Z
    order on the canvas, so "items[-1]" should always be the "topmost"
    graphic item (again, if any.)

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJun 20, '08 at 4:11p
activeJun 23, '08 at 9:08a
posts9
users6
websitepython.org

People

Translate

site design / logo © 2022 Grokbase