Python Tk仅在以下情况下复制到剪贴板;粘贴";在程序退出之前使用

Python Tk仅在以下情况下复制到剪贴板;粘贴";在程序退出之前使用,python,tkinter,windows-10,clipboard,Python,Tkinter,Windows 10,Clipboard,环境 Python 3.6.2 视窗10 问题 我使用tk方法clipboard_append()将字符串复制到剪贴板 当我的程序从Python解释器运行时,数据被正确地复制到剪贴板 然而,当使用“C:\Python36.exe myprogram.py”运行时,我会出现一些奇怪的行为 如果在程序仍在运行时粘贴数据,它将按预期工作 如果我在程序运行时粘贴数据,然后关闭程序,我可以继续粘贴数据 如果在复制之后而在粘贴之前关闭程序,则剪贴板为空 问题 如何使tk拷贝到剪贴板,而不管包含窗口发生了

环境

  • Python 3.6.2
  • 视窗10
问题

我使用tk方法clipboard_append()将字符串复制到剪贴板

当我的程序从Python解释器运行时,数据被正确地复制到剪贴板

然而,当使用“C:\Python36.exe myprogram.py”运行时,我会出现一些奇怪的行为

  • 如果在程序仍在运行时粘贴数据,它将按预期工作
  • 如果我在程序运行时粘贴数据,然后关闭程序,我可以继续粘贴数据
  • 如果在复制之后而在粘贴之前关闭程序,则剪贴板为空
  • 问题

    如何使tk拷贝到剪贴板,而不管包含窗口发生了什么

    我的代码

    from tkinter import *
    from tkinter import messagebox
    
    url = 'http://testServer/feature/'
    
    def copyToClipboard():
        top.clipboard_clear()
        top.clipboard_append(fullURL.get())
        top.update()
        top.destroy()
    
    def updateURL(event):
        fullURL.set(url + featureNumber.get())
    
    def submit(event):
        copyToClipboard()
    
    top = Tk()
    top.geometry("400x75")
    top.title = "Get Test URL"
    
    topRow = Frame(top)
    topRow.pack(side = TOP)
    
    bottomRow = Frame(top)
    bottomRow.pack(side = BOTTOM)
    
    featureLabel = Label(topRow, text="Feature Number")
    featureLabel.pack(side = LEFT)
    
    featureNumber =  Entry(topRow)
    featureNumber.pack(side = RIGHT)
    
    fullURL = StringVar()
    fullURL.set(url)
    
    fullLine = Label(bottomRow, textvariable=fullURL)
    fullLine.pack(side = TOP)
    
    copyButton = Button(bottomRow, text = "Copy", command = copyToClipboard)
    copyButton.pack(side = TOP)
    
    featureNumber.focus_set()
    featureNumber.bind("<KeyRelease>", updateURL)
    featureNumber.bind("<Return>", submit)
    
    top.mainloop()
    
    从tkinter导入*
    从tkinter导入消息框
    url='1〕http://testServer/feature/'
    def copyToClipboard():
    top.clipboard_clear()
    top.clipboard\u append(fullURL.get())
    top.update()
    top.destroy()
    def updateURL(事件):
    fullURL.set(url+featureNumber.get())
    def提交(事件):
    copyToClipboard()
    top=Tk()
    顶部几何图形(“400x75”)
    top.title=“获取测试URL”
    顶行=框架(顶部)
    topRow.pack(侧面=顶部)
    底部行=框架(顶部)
    底部行。包装(侧面=底部)
    featureLabel=标签(顶行,text=“特征编号”)
    featureLabel.pack(侧面=左侧)
    featureNumber=条目(顶行)
    功能编号。包装(侧面=右侧)
    fullURL=StringVar()
    fullURL.set(url)
    fullLine=Label(bottomRow,textvariable=fullURL)
    完整包装(侧面=顶部)
    copyButton=按钮(底部行,text=“Copy”,command=copyToClipboard)
    copyButton.pack(侧面=顶部)
    featureNumber.focus_set()
    featureNumber.bind(“,updateURL)
    featureNumber.bind(“,submit)
    top.mainloop()
    
    计划的目的

    我的公司有一个用于新功能的测试服务器。每次我们创建一个新特性时,我们都需要在测试服务器上发布一个指向它的url。除了功能编号,url是相同的,所以我创建了这个python程序来为我生成url并将其复制到剪贴板


    如果我在手动关闭窗口之前注释掉“top.destroy”并粘贴url,我就可以实现这一点,但我真的希望避免这种情况。在一个完美的世界里,我会按一个快捷键,弹出窗口,输入我的功能编号,然后只需按enter键关闭窗口并粘贴新的url,所有这些都不会让我的手离开键盘。

    如果在粘贴剪贴板之前关闭tk应用程序,您关于剪贴板为空的问题是由于tkinter本身的问题。这已经被报道了好几次,这是由于tkinter处理剪贴板的懒惰方式造成的

    如果某些内容已设置到tkinter剪贴板但未粘贴,则tkinter在关闭应用程序之前不会附加windows剪贴板。因此,一种方法是告诉tkinter附加到windows剪贴板

    我一直在测试一种方法来做到这一点,但是它会在应用程序过程中造成一些延迟,所以它可能不是最好的解决方案,但只是一个开始。使用import
    os
    system
    方法查看代码的这个修改版本

    from tkinter import *
    from tkinter import messagebox
    import os
    
    top = Tk()
    top.geometry("400x75")
    top.title = "Get Test URL"
    
    url = 'http://testServer/feature/'
    fullURL = StringVar()
    fullURL.set(url)
    
    def copyToClipboard():
        top.clipboard_clear()
        top.clipboard_append(fullURL.get())
        os.system('echo {}| clip'.format(fullURL.get()))
        top.update()
        top.destroy()
    
    def updateURL(event):
        fullURL.set(url + featureNumber.get())
    
    def submit(event):
        copyToClipboard()
    
    topRow = Frame(top)
    topRow.pack(side = TOP)
    bottomRow = Frame(top)
    bottomRow.pack(side = BOTTOM)
    featureLabel = Label(topRow, text="Feature Number")
    featureLabel.pack(side = LEFT)
    featureNumber =  Entry(topRow)
    featureNumber.pack(side = RIGHT)
    fullLine = Label(bottomRow, textvariable=fullURL)
    fullLine.pack(side = TOP)
    copyButton = Button(bottomRow, text = "Copy", command = copyToClipboard)
    copyButton.pack(side = TOP)
    featureNumber.focus_set()
    featureNumber.bind("<Return>", submit)
    
    top.mainloop()
    

    featureNumber.bind(“,updateLink)”中的
    ipdateLink
    未显示在代码中,导致代码不可测试。请提供代码的可测试版本。这篇文章应该会有所帮助:这似乎是我建议尝试一下这里的建议,看看它是否解决了你的问题:@SierraMountainTech道歉,这是一个复制错误。我已将其更正为“updateURL”。@Bryan Oakly。除了Ubuntu,这听起来和我面临的问题完全一样。从下面的信息来看,这似乎是tk本身的一个问题。不过,链接中的解决方案确实提供了有效的解决方法。谢谢,很好用。就像你说的有一点延迟,但我每天最多只需要运行一到两次,所以这不是一个破坏交易的因素。谢谢我很高兴它对你有用。我仍然会寻找更好的方法,因为延迟不应该发生。Bryan Oakly提供的链接还指出了一个解决方案,在一个小延迟后使用“after”运行“destroy”并返回主循环。这是可行的,没有延迟,但我个人并不喜欢“延迟并希望最好”的解决方案。@TripleD我刚刚在我的答案中添加了第二个选项,使用导入
    pyperclip
    ,它可以毫不延迟地完美工作!您需要将pyperclip库添加到python。@TripleD我确实尝试了
    after()
    方法,但这并没有解决我的问题。即使是5秒的延迟。所以我提出了
    os.system
    方法。
    from tkinter import *
    from tkinter import messagebox
    import pyperclip
    
    top = Tk()
    top.geometry("400x75")
    top.title = "Get Test URL"
    
    url = 'http://testServer/feature/'
    fullURL = StringVar()
    fullURL.set(url)
    
    def copyToClipboard():
        top.clipboard_clear()
        pyperclip.copy(fullURL.get())
        pyperclip.paste()
        top.update()
        top.destroy()
    
    def updateURL(event):
        fullURL.set(url + featureNumber.get())
    
    def submit(event):
        copyToClipboard()
    
    topRow = Frame(top)
    topRow.pack(side = TOP)
    bottomRow = Frame(top)
    bottomRow.pack(side = BOTTOM)
    featureLabel = Label(topRow, text="Feature Number")
    featureLabel.pack(side = LEFT)
    featureNumber =  Entry(topRow)
    featureNumber.pack(side = RIGHT)
    fullLine = Label(bottomRow, textvariable=fullURL)
    fullLine.pack(side = TOP)
    copyButton = Button(bottomRow, text = "Copy", command = copyToClipboard)
    copyButton.pack(side = TOP)
    featureNumber.focus_set()
    featureNumber.bind("<Return>", submit)
    
    top.mainloop()