I'm working on an APA citation maker in Python using tkinter. I use the Text widget to display the citation once it's generated, but whenever I copy the text (using the ctrl+c shortcut, at the moment) it loses its formatting. Is there some way to copy formatted text (italicized, for instance) from the Text widget rather than unformatted text?
-
1This looks like it'll be an interesting (read: a lot of trouble) project. You need to access the system clipboard, including formatting. Accessing the clipboard is easy: http://coffeeghost.net/2010/10/09/pyperclip-a-cross-platform-clipboard-module-for-python/. However, accessing the clipboard with formatting looks more complex: http://stackoverflow.com/questions/9630235/how-to-get-content-with-format-from-clipboard, http://msdn.microsoft.com/en-us/library/windows/desktop/ms649013%28v=vs.85%29.aspx. This thread looks promising: http://www.gossamer-threads.com/lists/python/python/180532. – pycoder112358 Mar 31 '13 at 00:29
1 Answers
To copy formatted text to the clipboard, you need an interface between python and the system's clipboard which supports text formatting. I have found klembord which should works in Linux and Windows (Mac users can probably adapt the below solution to richxerox).
The idea is to (1) convert the formatted text from the text widget to html then to (2) add it to the clipboard:
With
text.dump(index1, index2, tag=True, text=True)
it is possible to retrieve the text and tags from the widget. It returns a list like (this is the content of the widget in the example below):[('text', 'Author et al. (2012). The title of the article. ', '1.0'), ('tagon', 'italic', '1.48'), ('text', 'Journal Name', '1.48'), ('tagoff', 'italic', '1.60'), ('text', ', ', '1.60'), ('tagon', 'bold', '1.62'), ('text', '2', '1.62'), ('tagoff', 'bold', '1.63'), ('text', '(599), 1–5.', '1.63'), ('text', '\n', '1.74')]
So it is easy to associate each
('tagon/off', tagname)
pair with the corresponding html tag using a dictionary and convert the widget content to html.klembord.set_with_rich_text(txt, rich_txt)
puts the stringtxt
and its html formatted equivalent in the clipboard.
Here is a full example (tested in Linux, I was able to copy the text from the text widget and paste it into a word processor with the formatting):
import tkinter as tk
import klembord
root = tk.Tk()
text = tk.Text(root)
text.pack(fill='both', expand=True)
text.tag_configure('italic', font='TkDefaultFont 9 italic')
text.tag_configure('bold', font='TkDefaultFont 9 bold')
TAG_TO_HTML = {
('tagon', 'italic'): '<i>',
('tagon', 'bold'): '<b>',
('tagoff', 'italic'): '</i>',
('tagoff', 'bold'): '</b>',
}
def copy_rich_text(event):
try:
txt = text.get('sel.first', 'sel.last')
except tk.TclError:
# no selection
return "break"
content = text.dump('sel.first', 'sel.last', tag=True, text=True)
html_text = []
for key, value, index in content:
if key == "text":
html_text.append(value)
else:
html_text.append(TAG_TO_HTML.get((key, value), ''))
klembord.set_with_rich_text(txt, ''.join(html_text))
return "break" # prevent class binding to be triggered
text.bind('<Control-c>', copy_rich_text)
text.insert("1.0", "Author et al. (2012). The title of the article. ")
text.insert("end", "Journal Name", "italic")
text.insert("end", ", ")
text.insert("end", "2", "bold")
text.insert("end", "(599), 1–5.")
root.mainloop()

- 15,431
- 3
- 34
- 61