简体   繁体   English

Python / Tkinter - Select 并从另一个 function 单击按钮将所有文本内容复制到剪贴板

[英]Python / Tkinter - Select and copy all Text contents to clipboard on Button click from another function

I just started teaching myself Python in the last couple days to do some application programming and have previous experience developing websites with PHP. I've been building a program that will parse a list of information, build an array of collected variables, then load and populate an html template with those variables in a new Tkinter Toplevel window. The new window is created by a function that is called by a menubar command in the root window. All it contains is a text box with scrollbars and a few buttons that should allow the user to select all of the text, copy it to the clipboard, and close the window.我最近几天刚开始自学 Python 来做一些应用程序编程,并且之前有使用 PHP 开发网站的经验。我一直在构建一个程序来解析信息列表,构建一个收集变量的数组,然后加载和用新的 Tkinter Toplevel window 中的这些变量填充 html 模板。新的 window 由根 window 中的菜单栏命令调用的 function 创建。它只包含一个带有几个按钮和滚动条的文本框用户将select的所有文本复制到剪贴板,并关闭window。

The issue I'm having, and I'm sure this will probably be a simple fix for somebody fluent in Python, is that I don't know how to properly reference everything when calling the select and copy functions from within other functions.我遇到的问题是,我确信这对于精通 Python 的人来说可能是一个简单的修复,因为我不知道如何在调用 select 和从其他函数中复制函数时正确引用所有内容。 If I strip down the code as if I'm only working out of one window, everything works as expected:如果我剥离代码,就好像我只处理一个 window 一样,一切都按预期工作:

import tkinter as tk

def clipit():
    textpop.clipboard_clear()
    textpop.event_generate("<<TextModified>>")
    textpop.clipboard_append(textarea.get('1.0', 'end'))
    textpop.update()
    
def textselect():
    textpop.event_generate("<<TextModified>>")
    textarea.tag_add('sel', "1.0", 'end-1c')

textpop = tk.Tk()
textarea = tk.Text(textpop, wrap="none")
textarea.pack(side="left", fill="both", padx=20, pady=20)
textarea.insert("1.0", "This is a test - Try to select all and copy!")
exitbutton = tk.Button(textpop, text="Close", command = textpop.destroy)
exitbutton.pack(side="right", padx=(5,20), pady=(0,20))
copybutton = tk.Button(textpop, text="Copy", command = clipit)
copybutton.pack(side="right",padx=5, pady=(0,20))
selectbutton = tk.Button(textpop, text="Select All", command = textselect)
selectbutton.pack(side="right",padx=5, pady=(0,20))
textarea.focus()
textpop.mainloop()

If I try to do the same thing, but from within a function (where textpop = tk.Toplevel()), it doesn't work any longer.如果我尝试做同样的事情,但在 function(其中 textpop = tk.Toplevel())中,它不再起作用。 I've attempted passing various references to the functions (parent, widget, etc) and modifying the function code accordingly, but haven't had any luck getting it to work.我尝试传递对函数(父函数、小部件等)的各种引用并相应地修改 function 代码,但没有任何运气让它工作。 For example:例如:

import tkinter as tk

def clipit(parent,textwidget):
    parent.clipboard_clear()
    parent.event_generate("<<TextModified>>")
    parent.clipboard_append(textwidget.get('1.0', 'end'))
    parent.update()
    
def textselect(parent,textwidget):
    parent.event_generate("<<TextModified>>")
    parent.textwidget.tag_add('sel', "1.0", 'end-1c')

def textwindow(title,content):
    textpop = tk.Toplevel()
    textpop.title(title)
    textarea = tk.Text(textpop, wrap="none")
    textarea.pack(side="left", fill="both", padx=20, pady=20)
    textarea.insert("1.0", content)
    exitbutton = tk.Button(textpop, text="Close", command = textpop.destroy)
    exitbutton.pack(side="right", padx=(5,20), pady=(0,20))
    copybutton = tk.Button(textpop, text="Copy", command = lambda: clipit(textpop,textarea))
    copybutton.pack(side="right",padx=5, pady=(0,20))
    selectbutton = tk.Button(textpop, text="Select All", command = lambda: textselect(textpop,textarea))
    selectbutton.pack(side="right",padx=5, pady=(0,20))
    textarea.focus()
    textpop.mainloop()

window = tk.Tk()
window.title("Main Window")
launchbutton = tk.Button(window, text = "Launch Window", command = lambda: textwindow("Toplevel Popup", "Text Area Text"))
launchbutton.pack(padx=20,pady=20)
window.mainloop()

In my main script (and this example code), clicking the Select All button would result in the following error:在我的主脚本(和这个示例代码)中,单击 Select All 按钮会导致以下错误:

AttributeError: 'Toplevel' object has no attribute 'textwidget' AttributeError: 'Toplevel' object 没有属性 'textwidget'

Is there something simple that I'm just missing because I'm new to the language?因为我是这门语言的新手,所以我错过了什么简单的东西吗?

Edit: Revised second example for clarity, based on Bryan's comment.编辑:为清楚起见,根据 Bryan 的评论修改了第二个示例。

In the process of building a functional example script to help people troubleshoot this for me, I think I found the culprit:在构建功能示例脚本以帮助人们为我解决此问题的过程中,我想我找到了罪魁祸首:

parent.textwidget.tag_add('sel', '1.0', 'end-1c')

Looks like I was maybe being a little too specific with my references, as removing the attempted parent reference fixed the problem with selecting the the contents of textwidget.看起来我的引用可能有点太具体了,因为删除尝试的父引用解决了选择 textwidget 内容的问题。 I did also have to add a focus call for the textwidget to make it work, which I also threw into the function:我还必须为 textwidget 添加焦点调用以使其工作,我也将其放入 function:

def textselect(parent,textwidget):
    parent.event_generate("<<TextModified>>")
    textwidget.focus()
    textwidget.tag_add('sel', '1.0', 'end')

Once I had it all working, I also realized that selecting the text is sort of redundant anyway and more of a visual thing, as the copy function will copy the entire contents of the text box regardless of whether it's highlighted.一旦一切正常,我也意识到选择文本无论如何都是多余的,更多的是视觉效果,因为副本 function 将复制文本框的全部内容,无论它是否突出显示。

Not 100% sure this is the best way to accomplish all this, but it works.不能 100% 确定这是完成这一切的最佳方式,但它确实有效。 If anyone has a better method, feel free to post it!如果谁有更好的方法,欢迎留言!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM