Discussion:
[Tkinter-discuss] Editing text in Canvas
Martin B
2011-08-26 12:27:42 UTC
Permalink
Hi all,
I'm write some custom widgets for my app.
Now i write custom Scale widget like in Gimp2.7.

Here is the code:
http://www.tbs-software.com/spookyln/py/Tk_Scale.py

but i need some kick how to make it editable.When i click to Canvas
focus set to editable entry.First value ok and next is error that focus
not set in item :(

BTW: is possible make gradient fill in Canvas.create_rectangle() ?
thanks for info
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Tk_Scale.py
Type: text/x-python
Size: 2956 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20110826/50019648/attachment.py>
Martin B
2011-08-26 13:27:05 UTC
Permalink
V Fri, 26 Aug 2011 14:27:42 +0200
Martin B <spooky.ln at tbs-software.com> naps?no:

sorry for bothering problem is solved. But another raised.
How i remove insertion from text object after i hit Return.
If i click on canvas insert cursor dissapear but if i write some
numbers then these numbers is written in new pos on text object.
Thanks
Michael Lange
2011-08-26 19:50:07 UTC
Permalink
Hi,

Thus spoketh Martin B <spooky.ln at tbs-software.com>
Post by Martin B
V Fri, 26 Aug 2011 14:27:42 +0200
sorry for bothering problem is solved. But another raised.
How i remove insertion from text object after i hit Return.
If i click on canvas insert cursor dissapear but if i write some
numbers then these numbers is written in new pos on text object.
Thanks
Hm, here I get:

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1413, in __call__
return self.func(*args)
File "test7.py", line 79, in __edit_value
self.dchars(item, SEL_FIRST, SEL_LAST)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 2181, in dchars
self.tk.call((self._w, 'dchars') + args)
TclError: selection isn't in item

I guess you changed your code a litle since the last post ?

Anyway, your problem is that the Canvas still has keyboard focus and so
the __edit_value() callback will be called no matter which of its items
the canvas focusses. To understand this you need to be aware that the
Canvas' internal focus is not the same as the "normal" widget focus, as
"man canvas" says:

"""Once the focus has been set to an item, the item will display the
insertion cursor and all keyboard events will be directed to that item.
The focus item within a canvas and the focus window on the screen (set
with the focus command) are totally independent: a given item does not
actually have the input focus unless (a) its canvas is the focus window
and (b) the item is the focus item within the canvas. In most cases it is
advisable to follow the focus widget command with the focus command to
set the focus window to the canvas (if it was not there already)."""

So you need to either add a callback for Button-1 (and maybe other)
events that checks the x and y-coords of the event and moves keyboard
focus away from the canvas, which could basically look like:

self.bind('<1>', self._set_focus, add=True)

def _set_focus(self, event):
if not self.objects['entry'] in self.find('overlapping', event.x,
event.y, event.x, event.y):
self.main.focus()

or let your __edit_value () callback handle the situation, although I
admit that at a quick glance I have no idea how to do that.

The third solution that comes to mind seems the best to me: use
self.create_window() to replace your text object with an Entry widget
which should handle keyboard focus properly.

Regards

Michael

.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.

Vulcans do not approve of violence.
-- Spock, "Journey to Babel", stardate 3842.4
Martin B
2011-08-26 20:26:16 UTC
Permalink
Thanks for info.
Yes i slowly updating source. using web for my backup sometimes.

Now when i arrive from my bike trip with clean head i tried use
'unbind' in __edit_value method and created new bind in __select value.
seems to work.

as for entry. i dont know how i may change background under entry if
filled rect is under object.
And for question which i posted before. Is some way to fill this rect
with gradient or only way is to create gradient image and use
create_bitmap instead create_rect. this is my first idea how to do this.

quickly updated source is on web. same link as before.
Martin B
2011-08-27 08:26:57 UTC
Permalink
Post by Martin B
And for question which i posted before. Is some way to fill this rect
with gradient or only way is to create gradient image and use
create_bitmap instead create_rect. this is my first idea how to do this.
Hello, problem is solved.
Now i implemented vertical and horizontal gradients using
Canvas.create_line()
Michael Lange
2011-08-27 10:15:08 UTC
Permalink
Thus spoketh Martin B <spooky.ln at tbs-software.com>
Post by Martin B
Post by Martin B
And for question which i posted before. Is some way to fill this rect
with gradient or only way is to create gradient image and use
create_bitmap instead create_rect. this is my first idea how to do this.
Hello, problem is solved.
Now i implemented vertical and horizontal gradients using
Canvas.create_line()
Can you post a brief example how you implemented the gradients?

Michael


.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.

Genius doesn't work on an assembly line basis. You can't simply say,
"Today I will be brilliant."
-- Kirk, "The Ultimate Computer", stardate 4731.3

Michael Lange
2011-08-27 08:57:15 UTC
Permalink
Hi,

Thus spoketh Martin B <spooky.ln at tbs-software.com>
Post by Martin B
Thanks for info.
Yes i slowly updating source. using web for my backup sometimes.
Now when i arrive from my bike trip with clean head i tried use
'unbind' in __edit_value method and created new bind in __select value.
seems to work.
as for entry. i dont know how i may change background under entry if
filled rect is under object.
You are right, this is not possible. Maybe a way to go is to temporarily
create an Entry, as in this example:

from Tkinter import *
root = Tk()
c = Canvas(root)
c.pack()
textvar = StringVar()
t = c.create_text(100, 100, text='foo', anchor='nw')

def edit_begin(event):
x, y = c.coords(t)
textvar.set(c.itemcget(t, 'text'))
e = Entry(c, width=5, textvariable=textvar, bd=0,
highlightthickness=0, bg=c['bg'])
e.selection_range(0, 'end')
w = c.create_window(x, y, window=e, tags=('editwindow',), anchor='nw')
e.focus_set()
e.bind('<Return>', edit_end)
e.bind('<Escape>', edit_cancel)

def edit_cancel(event):
c.delete('editwindow')
event.widget.destroy()
c.focus_set()

def edit_end(event):
c.itemconfigure(t, text=textvar.get())
edit_cancel(event)

c.bind('<Control-e>', edit_begin)

c.focus_set()
root.mainloop()

Regards

Michael


.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.

Earth -- mother of the most beautiful women in the universe.
-- Apollo, "Who Mourns for Adonais?" stardate 3468.1
Martin B
2011-08-27 09:44:23 UTC
Permalink
Yes this is good idea !
Saved into my examples for later use.

Now i quickly updated example on web with gradient fills.
No errors check yet. I need rewrite some things etc. etc.

BTW : i found on inet TkZinc which use OpenGL for writing into canvas.
Someone using this in apps ? thanks
Loading...