Tkinter OptionMenu 便携式消息框

发布于 2024-11-01 08:51:04 字数 3242 浏览 4 评论 0原文

我正在尝试创建一个包含项目列表的轻量级跨平台消息框。理想情况下,它有一个 API,允许您传递要显示的消息、标题和选择元组。当按“确定”时,它将返回当前选择的选项。所需的模块最好是标准 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

I am trying to create a light weight cross platform Message Box that contains a list of items. Ideally it has an API that allows you to pass in a message to to display, a title, and tuple of choices. When pressing OK it would return the currently selected choice. It would also be preferred that the required modules be part of the standard python distributions.

Easygui has what I am looking for called a choicebox found at http://easygui.sourceforge.net/download/version0.95/tutorial/index.html#contents_item_10.1. However the window it pops up is monstrous and it always sorts your list of choices alphabetically. Because of these 'features', easygui is not ideal.

I have also looked into bwidgets, pmw, and Tix. While trying these I have come across a few issues including: difficultly finding working examples and failures across different platforms.

My working model is using Tkinter's OptionMenu and pickle to return the data (see code samples below). While this works, it is rather annoying having to save the choice to the file system to avoid using global variables. Is there a way to return the selection upon destruction of the gui?

Any help / advice would be greatly appreciated. Note that these examples are only for reference, they may or may not run properly on your system.

State Management Module

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

Menu Module

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

Example Usage

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

EDIT

Disregarding my concern about global variables, I tried an implementation using them to see if it was any easier. It makes things substantially easier, however my question still stands for a better way to do this.

Below is the reworked Menu Module

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

错々过的事 2024-11-08 08:51:04

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

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"

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

The normal way dialogs work is something like this:

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

This is pseudocode, intended to be GUI toolkit agnostic (though admittedly it looks a lot like wxPython). The main idea is, you create the dialog as an object, ask the object to show itself, wait until the user is done (by virtue of clicking "OK" or "Cancel"), then asking the object for its data and then finally destroying the object (or, keep it around for re-use).

A second way to do this is to write your code such that you give the dialog a function to call in order to set the value. Something like this:

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"

This second method works well if your dialog is not modal (ie: your program continues to run while the dialog is present).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文