【问题标题】:How to auto-activate a tkinter simpledialog pop-up window?如何自动激活 tkinter simpledialog 弹出窗口?
【发布时间】:2017-04-12 03:21:08
【问题描述】:

我的一个 python 脚本中有这个函数,它会抛出一个 Tkinter 简单对话框屏幕来要求一些简单的用户输入。该功能有效。但是,它存在 2 个问题

  1. 它打开了两个窗口,而我只需要一个。但是如果我删除 master = Tk() 我会得到错误:

AttributeError: 'NoneType' 对象没有属性 'winfo_viewable'

在某一点上解决一个问题会很好,但我的主要问题是第二个问题:

  1. 每当出现简单的对话框屏幕时,我必须先单击它才能激活它,这很烦人。为了解决这个问题,我尝试了herehere 提供的解决方案,但它们不起作用。第一个链接根本没有为我做任何事情,第二个链接帮助我将 master.Tk() 窗口提升到前面,但这不是什么我需要。我需要简单的对话框窗口成为最顶层的窗口,并且我需要它自动激活,这样当我运行我的代码并弹出屏幕时,我可以自动输入它而无需先单击它。

任何帮助将不胜感激!

我的代码:

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()

【问题讨论】:

  • 你在master=Tk()之后试过master.withdraw()吗?
  • 不,谢谢!那确实解决了问题 1。现在..还有 1 个问题要解决..

标签: python python-3.x tkinter python-3.5 simpledialog


【解决方案1】:

我不认为有办法提升/关注它,但 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.")

要在您的代码中使用它,您可以这样做

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

【讨论】:

  • 感谢 Lafexlos,因为您已经投入时间,所以我支持您的回答,它解决了我无法在上述 tkinter- 上应用 .lift() (和类似命令)的第二个问题-窗口,但最终结果证明使用 .lift() 仍然无助于自动激活窗口,这是我提出问题的主要原因。我最终找到了一个不同的解决方案,我将上传该解决方案作为未来访问者对该问题的答案。
【解决方案2】:

首先,感谢 Lafexlos 通过将这样的窗口重新创建为 Tk() 实例来展示如何在 Tkinter simpledialog.askinteger() 窗口上应用 .lift() 和类似命令的解决方案。

对于那些希望如何自动激活 Tk 窗口(因此您不必在能够输入之前单击它)的人来说,似乎有多个选项。

最常见的解决方案似乎是使用.focus().force_focus(),如已实现的herehere。然而,在here 上,这些选项似乎可能不适用于(至少某些版本的)Windows 操作系统。 This 问题显示了这些系统的可能解决方案。此外,以前的解决方案似乎不适用于多个版本的 OS X。基于提供的解决方案 here,使用 Apple 的 osascript,我能够解决我的问题。

工作代码最终如下所示:

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()

简化/通用解决方案:

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()

编辑:现在我正在弄清楚要寻找什么解决方案似乎已经被多个帖子找到了。对于那些在 OS X 上想要在多个 Tkinter 和/或 python 实例同时运行时激活特定 Tkinter 窗口的用户,您可能需要查看here

【讨论】:

    猜你喜欢
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多