如何使用Tkinter并允许我的应用程序保持焦点?

时间:2014-06-24 12:35:36

标签: python tkinter focus lost-focus

我有一个小应用程序,用户可以作为命令行进行交互。我希望用户能够复制到应用程序刚刚在屏幕上显示的Windows剪贴板信息。显然,用户可以手动执行此操作,但需要几个步骤:右键单击窗口,选择“标记”,选择文本矩形,然后按Enter键复制它。我希望允许用户通过输入“cb”或“copy”之类的简短命令自动执行此操作。

Per this answer,获取剪贴板功能的一种简单方法是使用tkinter库。这确实很有效。但是,我发现当我的应用程序启动时,它会失去焦点。似乎隐藏的窗口(由Tk()打开然后由withdraw()隐藏)具有它。使用withdraw()隐藏窗口的行为并未将重点放在我的应用程序上。这很不方便,因为打开应用程序后,用户必须手动切换回它,而不是只能开始输入。

我想创建一个tkinter对象,并在隐藏新窗口后将焦点返回给我的应用程序,或者让我的应用程序首先不会失去焦点。我怎么能这样做?

关于tkinter和焦点有各种各样的问题,但它们似乎通常与将焦点放在tkinter本身打开的窗口有关,而我想继续关注应用程序的原始窗口,并拒绝它tkinter窗口。

我在Windows 8机器上工作。

Pastebin http://pastebin.com/6jsasiNE

1 个答案:

答案 0 :(得分:3)

在Windows NT,Windows Server 2003和Windows 7 +

您根本不需要使用Tkinter来实现目标。

clip.py:

import subprocess

def write_to_clipboard(string):
    p = subprocess.Popen(['clip'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    p.communicate(input=string)

此代码只调用标准的Windows clip.exe实用程序,粘贴string变量中传递的任何内容。

用法:

from clip import write_to_clipboard
try:
    while True:
        write_to_clipboard(raw_input())        
except KeyboardInterrupt:
    pass

在Windows 95,98,ME和XP上

那些版本的Windows没有clip.exe,所以这里只有python版本:

clip.py:

import subprocess

def write_to_clipboard(string):
    p = subprocess.Popen(['python', __file__], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    p.communicate(input=string)

if __name__ == "__main__":
    import sys
    from Tkinter import Tk

    r = Tk()
    r.withdraw()
    r.clipboard_clear()
    r.clipboard_append(sys.stdin.read())
    r.update()
    r.destroy()

这适用于所有版本的Windows,并适用于任何支持TK的操作系统。

请注意,您必须在单独的流程中运行Tk代码,因为即使我们致电r.destroy()Tk似乎也会锁定"剪贴板(在此过程退出之前,没有其他进程可以访问剪贴板。)

阅读和编写剪贴板

如果您希望能够从剪贴板中读取并写入,这就是解决方案。

clip.py:

import subprocess

def write(string):
    p = subprocess.Popen(['python', __file__, 'write'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    p.communicate(input=string)

def read():
    p = subprocess.Popen(['python', __file__, 'read'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return p.communicate()[0]

if __name__ == "__main__":
    import sys
    from Tkinter import Tk

    if len(sys.argv) != 2:
        sys.exit(1)

    r = Tk()
    try:
        r.withdraw()
        if sys.argv[1] == "write":
            r.clipboard_clear()
            r.clipboard_append(sys.stdin.read())
            r.update()
        elif sys.argv[1] == "read":
            sys.stdout.write(r.clipboard_get()),
        else:
            sys.exit(1)
    finally:
        r.destroy()

用法:

import clip
print "clipboard contains: %s" % clip.read()