Python 从tkinter中的文本小部件复制格式化文本

Python 从tkinter中的文本小部件复制格式化文本,python,text,widget,format,tkinter,Python,Text,Widget,Format,Tkinter,我正在使用tkinter开发Python中的APA引文生成器。我使用文本小部件在引文生成后显示引文,但每当我复制文本时(此时使用ctrl+c快捷键),它就会丢失格式。是否有某种方法可以从文本小部件复制格式化文本(例如,斜体),而不是复制未格式化文本?要将格式化文本复制到剪贴板,您需要在python和支持文本格式化的系统剪贴板之间建立一个接口。我已经发现哪些应该在Linux和Windows下工作(Mac用户可能会根据需要调整以下解决方案) 想法是:(1)将格式化文本从文本小部件转换为html,然后

我正在使用tkinter开发Python中的APA引文生成器。我使用文本小部件在引文生成后显示引文,但每当我复制文本时(此时使用ctrl+c快捷键),它就会丢失格式。是否有某种方法可以从文本小部件复制格式化文本(例如,斜体),而不是复制未格式化文本?

要将格式化文本复制到剪贴板,您需要在python和支持文本格式化的系统剪贴板之间建立一个接口。我已经发现哪些应该在Linux和Windows下工作(Mac用户可能会根据需要调整以下解决方案)

想法是:(1)将格式化文本从文本小部件转换为html,然后(2)将其添加到剪贴板:

  • 使用
    text.dump(index1,index2,tag=True,text=True)
    可以从小部件中检索文本和标记。它返回如下列表(这是下面示例中小部件的内容):

    因此,使用字典将每个
    ('tagon/off',标记名)
    对与相应的html标记相关联并将小部件内容转换为html是很容易的

  • klembord.set_with_rich_text(txt,rich_txt)
    将字符串
    txt
    及其html格式的等价物放入剪贴板

  • 下面是一个完整的示例(在Linux中测试,我能够从文本小部件复制文本并将其粘贴到具有格式的字处理器中):

    将tkinter作为tk导入
    进口克伦博德
    root=tk.tk()
    text=tk.text(根)
    text.pack(fill='both',expand=True)
    text.tag_configure('italic',font='TkDefaultFont 9 italic')
    text.tag_configure('bold',font='TkDefaultFont 9 bold')
    标记到HTML={
    ('tagon','italic'):'',
    ('tagon','bold'):'',
    (“标记”、“斜体”):“”,
    (“标记”、“粗体”):“”,
    }
    def copy_rich_文本(事件):
    尝试:
    txt=text.get('sel.first','sel.last')
    除了tk.TclError:
    #没有选择
    返回“中断”
    content=text.dump('sel.first','sel.last',tag=True,text=True)
    html_text=[]
    对于内容中的键、值和索引:
    如果键==“文本”:
    html_text.append(值)
    其他:
    html_text.append(TAG_TO_html.get((键,值),“”))
    klembord.set_与_富_文本(txt),.join(html_文本))
    返回“break”#防止触发类绑定
    text.bind(“”,复制富文本)
    插入(“1.0”,“作者等(2012年)”。文章标题。)
    文本。插入(“结束”、“日记账名称”、“斜体”)
    文本。插入(“结束”、“结束”、“结束”)
    文本。插入(“结束”、“2”、“粗体”)
    文本。插入(“结束”,“(599),1-5。”)
    root.mainloop()
    
    这看起来将是一个有趣的(阅读:很多麻烦)项目。您需要访问系统剪贴板,包括格式化。访问剪贴板很容易:。但是,使用格式访问剪贴板看起来更复杂:。这个线程看起来很有希望:。看看pyperclip,我很确定我看到了一些类似于您正在寻找的东西,您只需要使用模块创建自定义命令并将它们绑定到Ctrl+C键。
     [('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')]
    
    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()