如何自动激活tkinter simpledialog弹出窗口?

时间:2016-11-28 11:55:11

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

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

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

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

    在某一点上可以很好地说出一个,但我的主要问题然而是第二个:

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

      我的代码:

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

首先,通过重新创建这样一个窗口作为Tk()实例,向Lafexlos展示如何在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