Copying formatted text from Text widget in tkinter

流过昼夜 提交于 2020-12-29 07:44:00

问题


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?


回答1:


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:

  1. 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.

  2. klembord.set_with_rich_text(txt, rich_txt) puts the string txt 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()


来源:https://stackoverflow.com/questions/15724936/copying-formatted-text-from-text-widget-in-tkinter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!