【问题标题】:Tkinter OptionMenu Portable Message BoxTkinter OptionMenu 便携式消息框
【发布时间】:2011-04-14 04:49:44
【问题描述】:

我正在尝试创建一个包含项目列表的轻量级跨平台消息框。理想情况下,它有一个 API,允许您传递要显示的消息、标题和选择元组。当按下 OK 时,它将返回当前选择的选项。还希望所需的模块是标准 python 发行版的一部分。

Easygui 有我在http://easygui.sourceforge.net/download/version0.95/tutorial/index.html#contents_item_10.1 找到的选择框。然而,它弹出的窗口是可怕的,它总是按字母顺序对您的选择列表进行排序。由于这些“功能”,easygui 并不理想。

我还研究了 bwidgets、pmw 和 Tix。在尝试这些时,我遇到了一些问题,包括:难以找到有效的示例以及跨不同平台的失败。

我的工作模型是使用 Tkinter 的 OptionMenu 和 pickle 来返回数据(参见下面的代码示例)。虽然这可行,但必须将选择保存到文件系统以避免使用全局变量是相当烦人的。 有没有办法在破坏 gui 时返回选择?

任何帮助/建议将不胜感激。请注意,这些示例仅供参考,它们可能会或可能不会在您的系统上正常运行。

状态管理模块

import pickle

def store(pkl_path, data_to_store):
    try:
        fid = open(pkl_path, 'w')
        pickle.dump(data_to_store, fid)
    except:
        print 'Unable to store data in ' + pkl_path
    else:
        fid.close()

def load(pkl_path):
    try:
        fid = open(pkl_path, 'r')
        loaded_state = pickle.load(fid)
        fid.close()
    except:
        loaded_state = None
    else:
        fid.close()

    return loaded_state

菜单模块

from Tkinter import *

def Prompt_Dropdown_Ok_Cancel(title, options, pickle_file, default_selection=0):
    master = Tk()
    master.title(title)

    var = StringVar(master)
    var.set(options[default_selection]) # default value

    w = OptionMenu(master, var, *options)
    w.pack()

    def ok():
        state.store(pickle_file, var.get())
        master.quit()

    def cancel():
        state.store(pickle_file, None)
        master.quit()

    button = Button(master, text="OK", command=ok)
    button.pack()
    b2 = Button(master, text="Cancel", command=cancel)
    b2.pack()

    mainloop()

使用示例

from menu_module import *

def display_com_selection():
    pkl_path = '.tmp/comm_selection'

    title = 'COM Port Selection'
    Prompt_Dropdown_Ok_Cancel(title,get_available_com(),pkl_path)

    selection = state.load(pkl_path)

    return selection

编辑

不管我对全局变量的关注,我尝试了一个使用它们的实现,看看它是否更容易。它使事情变得更加容易,但是我的问题仍然代表一种更好的方法来做到这一点。

下面是重新设计的菜单模块

from Tkinter import *
Prompt_Dropdown_Ok_Cancel_Selection = None

def Prompt_Dropdown_Ok_Cancel(title, message, options, default_selection=0):
    master = Tk()
    master.title(title)
    var = StringVar(master)
    var.set(options[default_selection]) # default value
    l = Label(master, text=message)
    l.pack()
    w = OptionMenu(master, var, *options)
    w.pack(fill=BOTH, expand=1)

    def ok():
        global Prompt_Dropdown_Ok_Cancel_Selection
        Prompt_Dropdown_Ok_Cancel_Selection = str(var.get())
        master.destroy()

    def cancel():
        global Prompt_Dropdown_Ok_Cancel_Selection
        Prompt_Dropdown_Ok_Cancel_Selection = str(var.get())
        master.destroy()

    button = Button(master, text="OK", command=ok)
    button.pack(side=LEFT)
    b2 = Button(master, text="Cancel", command=cancel)
    b2.pack(side=LEFT)

    mainloop()

    return Prompt_Dropdown_Ok_Cancel_Selection

【问题讨论】:

    标签: python tkinter tk


    【解决方案1】:

    对话框的正常工作方式是这样的:

    mydialog = SomeDialogClass(...)
    result = mydialog.Show()
    if  result == "OK":
        print "you clicked OK; dialog value is", mydialog.GetValue()
    else:
        print "you clicked cancel"
    mydialog.Destroy()
    

    这是伪代码,旨在与 GUI 工具包无关(尽管不可否认,它看起来很像 wxPython)。主要思想是,您将对话框创建为一个对象,要求对象显示自己,等到用户完成(通过单击“确定”或“取消”),然后向对象询问其数据,然后最后销毁对象(或者,保留它以供重复使用)。

    第二种方法是编写代码,让对话框调用一个函数来设置值。像这样的:

    mydialog = SomeDialogClass(..., callback=self.foo)
    ....
    def foo(self, button, result):
        if button == "OK":
            print "you clicked OK; result is", result
        elif button == "Cancel":
            print "you clicked Cancel"
    

    如果您的对话框不是模态的(即:您的程序在对话框存在时继续运行),则第二种方法效果很好。

    【讨论】:

    • 感谢您的回复。首先,我完全同意你的说法。我想要实现的是第一个示例,但我面临的问题是“SomeDialogClass”不以我喜欢的方式存在。我必须创建自己的课程来实现这一目标。话虽如此,您对如何在不使用全局变量的情况下从对话框返回值有什么想法吗?
    • @Adam Lewis:我不明白你的问题——我的例子不使用全局变量。
    • 问题是如何从现有的 TK 对象返回一个值,而不是仅仅打印一些东西到标准输出。我能够做到这一点的唯一方法是使用泡菜或全局变量(我都不喜欢)。我知道一些现有的对话框会返回诸如“是”或“否”之类的内容,但是没有内置的下拉对话框可以返回所选值。
    • @Adam Lewis:我还是不明白这个问题。我的第一个例子展示了如何返回一个值。你没有看到返回值的位置吗?印刷品仅用于说明目的。您实例化该类,调用 Show 方法,当它返回时,您可以询问对话框该值是什么。当然,如果您愿意,您可以修改 Show() 以返回“是”或“否”...
    • 我看到它在哪里返回。正如我在第一条评论中所说,这是我正在寻找的用例,但我正在寻找的“SomeDialogClass”不存在。我正在尝试自己动手,当我调用 mainloop(请参阅上面的示例)时,我在返回任何值时都没有成功(它返回一个空列表)。如上述问题所述:有没有办法从 Tk() 对象中返回销毁值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 2011-02-01
    相关资源
    最近更新 更多