以脚本

时间:2018-04-03 10:02:49

标签: python tkinter widget

我定义了一个tkinter checkbutton小部件,用于根据用户定义的列表创建复选框,并返回包含所选元素的新列表。当我直接在IPython控制台上运行它时,它按预期工作(我大部分时间都使用Spyder3)。如果我将函数保存为Python脚本并在Python控制台中将其称为模块函数,它也可以工作。但是,如果我运行包含此函数的脚本,那些检查按钮的所有更改根本不会反映到实际值的行为很奇怪;无论我选择哪些项目,所有值都 False 。以下是代码和示例:

CheckBox.py

import tkinter as tk
from tkinter.messagebox import askyesno
import sys

def CheckBox(picks, *Args):
    class checkboxfromlist(tk.Frame):
        def __init__(self, parent, picks):
            tk.Frame.__init__(self, parent)
            self.vars = []
            for pick in picks:
                var = tk.BooleanVar()
                chk = tk.Checkbutton(self, text=pick, variable=var, onvalue=True, offvalue=False)
                chk.pack()
                self.vars.append(var)

        def state(self):
            return list(map((lambda var: var.get()), self.vars))

    class MainWindow(tk.Tk):
        def __init__(self, picks, text):
            tk.Tk.__init__(self)
            self.resizable(width=False, height=False)
            self.title('Select desired download')
            self.protocol('WM_DELETE_WINDOW', self.on_exit)
            self.l = tk.Label(self, text='Please select desired download {}'.format(text))
            self.l.pack()
            self.ChkBox = checkboxfromlist(self, picks)
            self.ChkBox.pack()
            self.Button = tk.Button(self, text='Ok', width=40, height=2, command=self.quit)
            self.Button.pack()
            # Make popup window at the centre
            self.update_idletasks()
            w = self.winfo_screenwidth()
            h = self.winfo_screenheight()
            size = tuple(int(_) for _ in self.geometry().split('+')[0].split('x'))
            x = w/2 - size[0]/2
            y = h/2 - size[1]/2
            self.geometry('%dx%d+%d+%d' % (size + (x, y)))

        def on_exit(self):
        # When you click x to exit, this function is called
            if askyesno("Exit", "Do you want to quit the application?"):
                self.destroy()
                sys.exit(0)

    text = ' for '.join(Args)
    App = MainWindow(picks, text)
    App.mainloop()
    mask = App.ChkBox.state()
    App.destroy()
    selected = [item for index, item in enumerate(picks) if mask[index]]
    return selected

以下是小部件的快照: widget screenshot

这些工作:

  1. 直接在IPython控制台中粘贴代码然后运行 CheckBox(MyList,' item')
  2. 在终端输入 Python ,然后导入CheckBox ,运行 CheckBox.CheckBox(MyList,&#39; item&#39;) < / LI>

    这些不能工作:

    以spyder,终端或双击

    作为脚本运行
    if __name__ == '__main__':
        CheckBox(MyList, 'item')
    

    在spyder,terminal或者脚本中作为外部模块运行     双击

    import CheckBox
    if __name__ == '__main__':
        CheckBox.CheckBox(MyList, 'item')
    

    我尝试在Ubuntu上使用Python 3.5.2,在Windows 10上使用3.6.4,它们都给了我同样的问题。我花了一整天时间搞清楚发生了什么,但没有运气。任何评论都会非常感激。

    修改
    我发现小部件有效,直到我在main函数的开头添加以下代码:

    root = tk.Tk()
    root.withdraw()
    

    我这样做的原因是因为在此过程中稍后会有一些用户提示窗口小部件。如果没有 root.withdraw(),屏幕上将始终显示一个空白窗口。以上代码的效果持续到我重新启动Spyder3;这意味着我只需删除上面的代码就可以让我的代码再次运行。这是该计划的快照:

    这有效:
    Screenshot of Spyder

    正如您所看到的,打印输出列表正是我选择的项目(我运行一次然后再次运行它以获取小部件的快照)。

    这不是:
    Screenshot of Spyder

    无论我如何选择项目,打印列表都是空的。

    PS fuck_tk 与我在上面发布的 CheckBox.py 完全相同。

    EDIT2
    我发现为了使所有小部件工作而不显示空白主tkinter窗口,我需要将所有tkinter消息框作为单独的函数,如下所示:

    def User_Confirm():
        root = tk.Tk()
        root.withdraw()
        answer = askquestion('test', 'tkinter sucks')
        root.destroy()
        return answer
    

    然而,这种解决方法对我来说听起来非常愚蠢。是否有任何优雅的方法来隐藏主tkinter窗口,而不影响我的CheckBox小部件的功能?

0 个答案:

没有答案