Tkinter: cut'n'paste from DISABLED window?

  • Thread starter Patrick L. Nolan
  • Start date
P

Patrick L. Nolan

Our Tkinter application has a big ScrolledText widget which is
a log of everything that happens. In order to prevent people
from making changes, we have it in DISABLED mode except when
the program wants to write a new entry. This works OK, except
that sometimes we want to copy out of piece of the contents and
paste it in another window. When it's DISABLED, it appears
that we can't even select a portion of the text.

Is this an either-or situation? Or is there some clever way to
get around it?

If it matters, we want this to work on both Linux and Windows.
 
M

Michael Geary

Patrick said:
Our Tkinter application has a big ScrolledText widget which is
a log of everything that happens. In order to prevent people
from making changes, we have it in DISABLED mode except when
the program wants to write a new entry. This works OK, except
that sometimes we want to copy out of piece of the contents and
paste it in another window. When it's DISABLED, it appears
that we can't even select a portion of the text.

Is this an either-or situation? Or is there some clever way to
get around it?

If it matters, we want this to work on both Linux and Windows.

I don't know if this will help, but maybe it will provide a hint...

In a native Windows app, the way you do this is to make the edit control
read-only instead of disabled. For example, if you right-click a file in
Windows and select Properties, you'll notice that you can select and copy
text from any of the text fields in the General tab of the property sheet.

The way this is done is by making those text fields Edit controls with the
ES_READONLY style (and without the WS_DISABLED style).

-Mike
 
P

Peter Abel

Patrick L. Nolan said:
Our Tkinter application has a big ScrolledText widget which is
a log of everything that happens. In order to prevent people
from making changes, we have it in DISABLED mode except when
the program wants to write a new entry. This works OK, except
that sometimes we want to copy out of piece of the contents and
paste it in another window. When it's DISABLED, it appears
that we can't even select a portion of the text.

Is this an either-or situation? Or is there some clever way to
get around it?

If it matters, we want this to work on both Linux and Windows.

The question is if you really need a Tkinter.Text-widget or if a
Tkinter.Listbox would satisfy your wishes. Then you could program
a scrollable Listbox as the following example:

# Vertical scrollbar for listbox
vscroll=Tkinter.Scrollbar(self,orient='vertical')
vscroll.grid(row=3,rowspan=10,column=11,sticky='ns')

# horizontal scrollbar for listbox
hscroll=Tkinter.Scrollbar(self,orient='horizontal')
hscroll.grid(row=13,column=2,columnspan=9,sticky='ew')

# Listbox
self.msgBox=Tkinter.Listbox(self,
bg='white',
relief='sunken',
xscrollcommand=hscroll.set,
yscrollcommand=vscroll.set,
)
self.msgBox.grid(row=3,rowspan=10,column=2,columnspan=9,sticky='nesw')

hscroll.configure(command=self.msgBox.xview)
vscroll.configure(command=self.msgBox.yview)


Then bind to all widgets to the event-function for Cntrl-C:

self.bind_all('<Control-KeyPress-c>',self.Copy)

Where the Copy-function could look as follows:

#-----------------------------------
def Copy (self, *event):
#-----------------------------------
"""
Copies selected lines in the Listbox to Cilpboard

@para event: Dummy-parameter
@type event: list
@return: None
@rtype: NN
"""
if self.msgBox.size():
cs=self.msgBox.curselection()
if cs:
# Overwirte the clipboardcontent
self.msgBox.clipboard_clear()
for lineno in cs:
self.msgBox.clipboard_append(self.msgBox.get(lineno)+'\n')

I use the above example in the same app under W2kprof and HP-UX and
it works fine.

Regards
Peter
 
F

Fredrik Lundh

Michael Geary wrote:

I don't know if this will help, but maybe it will provide a hint...

In a native Windows app, the way you do this is to make the edit control
read-only instead of disabled. For example, if you right-click a file in
Windows and select Properties, you'll notice that you can select and copy
text from any of the text fields in the General tab of the property sheet.

The way this is done is by making those text fields Edit controls with the
ES_READONLY style (and without the WS_DISABLED style).

Tk's Text widget is a custom widget, which doesn't rely on Windows native
widgets.

however, in recent versions, many Tk entry widgets supports both
state="disabled"
and state="readonly", but I don't think this is yet available for the Text
widget.


as for the original poster, the best way to solve this is probably to add
custom
mouse bindings for this widget. here's a start (needs a bit of tweaking,
but you
get the idea):

w.tag_config("mysel", background="blue", foreground="white")

def start(event):
index = w.index("@%d,%d" % (event.x, event.y))
w.mark_set("myanchor", index)

def drag(event):
index = w.index("@%d,%d" % (event.x, event.y))
w.tag_remove("mysel", 1.0, END)
w.tag_add("mysel", "myanchor", index)

def copy(event):
text = w.get("mysel.first", "mysel.last")
if text: add to clipboard

w.bind("<Button-1>", start)
w.bind("<B1-Motion>", drag)
w.bind("<Control-C>", copy)

</F>
 
R

Russell E. Owen

however, in recent versions, many Tk entry widgets supports both
state="disabled"
and state="readonly", but I don't think this is yet available for the Text
widget.

as for the original poster, the best way to solve this is probably to add
custom
mouse bindings for this widget. here's a start...[/QUOTE]

Glad to hear about the new state="readonly". Looking forward to that
making it into the Text widget. Meanwhile, here's the function I use. No
gurantees, but it seems to work for me. Any bug reports would be most
welcome.

-- Russell

def makeReadOnly(tkWdg):
"""Makes a Tk widget (typically an Entry or Text) read-only,
in the sense that the user cannot modify the text (but it can
still be set programmatically). The user can still select and copy
text
and key bindings for <<Copy>> and <<Select-All>> still work properly.

Inputs:
- tkWdg: a Tk widget
"""
def killEvent(evt):
return "break"

def doCopy(evt):
tkWdg.event_generate("<<Copy>>")

def doSelectAll(evt):
tkWdg.event_generate("<<Select-All>>")

# kill all events that can change the text,
# including all typing (even shortcuts for
# copy and select all)
tkWdg.bind("<<Cut>>", killEvent)
tkWdg.bind("<<Paste>>", killEvent)
tkWdg.bind("<<Paste-Selection>>", killEvent)
tkWdg.bind("<<Clear>>", killEvent)
tkWdg.bind("<Key>", killEvent)
# restore copy and select all
for evt in tkWdg.event_info("<<Copy>>"):
tkWdg.bind(evt, doCopy)
for evt in tkWdg.event_info("<<Select-All>>"):
tkWdg.bind(evt, doSelectAll)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top