简体   繁体   English

如何自动激活Tkinter SimpleDialog弹出窗口?

[英]How to auto-activate a tkinter simpledialog pop-up window?

I have this function inside one of my python scripts which throws up a Tkinter simple dialog screen to ask for some simple user-input. 我在一个python脚本中包含此功能,该脚本抛出Tkinter简单对话框屏幕,要求一些简单的用户输入。 The function works. 该功能有效。 However, there are 2 problems with it. 但是,它有两个问题

  1. It opens up two windows, while all I need is one. 它打开了两个窗口,而我只需要一个。 But if I remove the master = Tk() I get the error: 但是,如果我删除master = Tk(),则会收到错误消息:

AttributeError: 'NoneType' object has no attribute 'winfo_viewable' AttributeError:“ NoneType”对象没有属性“ winfo_viewable”

It would be nice to at one point figure that one out, but my main problem however is the second one: 一方面可以说出这一点很好,但是我的主要问题是第二个:

  1. Whenever the simple dialog screen turns up, I have to click it first before it gets activated, which is annoying. 每当简单的对话框屏幕出现时,我必须先单击它才能激活它,这很烦人。 To fix it I tried the solutions offered here and here but they do not work. 为了解决此问题,我尝试了此处此处提供的解决方案,但是它们不起作用。 The first link didn't do anything for me at all, the second link helped me to lift the master.Tk() window to the front, but that is not what I need. 第一个链接对我根本没有任何帮助,第二个链接帮助我将master.Tk()窗口提升到了前面,但这不是我所需要的。 I need the simple dialog window to become the topmost window and I need it to be auto-activated so that when I run my code and the screen pops-up I can automatically type in it without having to click on it first. 我需要简单的对话框窗口成为最上面的窗口,并且需要将其自动激活,以便在运行代码并弹出屏幕时,可以自动键入它而不必先单击它。

Any help would be greatly appreciated! 任何帮助将不胜感激!

My code: 我的代码:

def getUser():
    master = Tk()
    newList2=str(newList).replace(", ","\n")
    for ch in ['[',']',"'"]:
        if ch in newList2:
            newList5=newList2.replace(ch,"")
    userNr=simpledialog.askinteger("Enter user number", newList2)
    chosenUsernr= userNr - 1
    global chosenUsernrdef
    chosenUsernrdef = chosenUsernr
    master.destroy()

I don't think there is a way to lift/give focus to it but askinteger is merely a combination of couple widgets so you can easily recreate it yourself. 我不认为有办法askinteger /赋予焦点,但是askinteger只是几个小部件的组合,因此您可以轻松地自己重新创建它。

import tkinter as tk
from tkinter import messagebox

class CustomAskInteger(tk.Tk):
    def __init__(self,  numbers):
        tk.Tk.__init__(self)

        self.value = None
        self.label = tk.Label(self, text=", ".join(map(str, numbers))).pack(fill="both", expand=True)
        self.entry = tk.Entry(self)
        self.button = tk.Button(self, text="Ok", command=self.get_number)

        self.entry.pack()
        self.button.pack()

    def get_number(self):
        """
        You can customize these error handlings as you like to
        """
        if self.entry.get():
            try:
                int(self.entry.get())
                self.value = self.entry.get()
                self.destroy()
            except ValueError:
                messagebox.showwarning("Illegal Value", "Not an integer.\nPlease try again.")
        else:
            messagebox.showwarning("Illegal Value", "Not an integer.\nPlease try again.")

To use this in your code, you can do 要在您的代码中使用此代码,您可以

def getUser():       
    newList2=str(newList).replace(", ","\n")
    askInteger = CustomAskInteger("Enter user number", newList2)
    #since it is a Tk() instance, you can do lift/focus/grab_set etc. on this
    askInteger.lift()
    askInteger.mainloop()
    userNr = askInteger.value

First, credits to Lafexlos for showing a solution of how to apply .lift() and similar commands on a Tkinter simpledialog.askinteger() window by recreating such a window as a Tk() instance. 首先,感谢Lafexlos展示了如何通过重新创建诸如Tk()实例之类的窗口来在Tkinter simpledialog.askinteger()窗口上应用.lift()和类似命令的解决方案。

For those however looking how to automatically activate a Tk-window (so you do not have to click on it before being able to type in it), there appear to be multiple options. 但是对于那些希望如何自动激活Tk窗口的用户(因此您不必在键入之前就可以单击它),似乎有多个选项。

The most common solution seems to be to use .focus() or .force_focus() as seen implemented here and here . 最常见的解决方案似乎是使用.focus().force_focus() ,如此此处所示 However over here it seems those options may not work on (at least some versions of) Windows OS. 但是,在这里看来,这些选项可能不适用于Windows OS(至少某些版本)。 This question shows a possible solution for those systems. 这个问题显示了这些系统的可能解决方案。 Also, the previous solutions appear not to work on multiple versions of OS X. Based on the solution offered here , using Apple's osascript, I was able to solve my problem. 另外,以前的解决方案似乎无法在OS X的多个版本上使用。基于此处提供的解决方案,使用Apple的osascript,我能够解决自己的问题。

The working code eventually looks like this: 工作代码最终如下所示:

def getUser():
    master = Tk()
    newList2=str(newList).replace(", ","\n")
    for ch in ['[',']',"'"]:
        if ch in newList2:
            newList2=newList2.replace(ch,"")
    cmd = """osascript -e 'tell app "Finder" to set frontmost of process "Python" to true'"""
    def stupidtrick():
        os.system(cmd)
        master.withdraw()
        userNr=simpledialog.askinteger("Enter user number", newList2)
        global chosenUsernrdef
        chosenUsernr= userNr - 1
        chosenUsernrdef = chosenUsernr
    stupidtrick()
    master.destroy()

Simplified / general solution: 简化/通用解决方案:

import os
from tkinter import Tk
from tkinter import simpledialog

def get_user():
    root = Tk()
    cmd = """osascript -e 'tell app "Finder" to set frontmost of process "Python" to true'"""
    def stupid_trick():
        os.system(cmd)
        root.withdraw()
        new_window=simpledialog.askinteger("Title of window", "Text to show above entry field")
    stupid_trick()
    root.destroy()

get_user()

EDIT : Now I am figuring out what to look for the solution appears to be found already by multiple posts. 编辑 :现在,我正在寻找寻找解决方案的东西,似乎已经被多个职位找到。 For those on OS X wanting to activate a specific Tkinter window when multiple instances of Tkinter and/or python are running simultaneously, you might want to look here . 对于OS X上希望同时运行多个Tkinter和/或python实例时激活特定Tkinter窗口的用户,您可能需要在这里查看

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

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