繁体   English   中英

使用tkinter根据OptionMenu答案更改复选框列表

[英]Change checkbox list based on OptionMenu answer with tkinter

我对tkinter有点麻烦

事情是这样的:我有一个dropdown (OptionMenu),可以选择某些内容。

我在OptionMenu的变量上设置了tracer ,当下拉列表更改时,该OptionMenu将调用函数。 (函数callback_project_name_changed

调用回调时,我检查已选择了哪个项目,并显示所需的复选框的适当列表。

这是我到目前为止的代码:

from tkinter import *
import os
import sys
from tkinter import filedialog


class Checkbar(Frame):
    def __init__(self, parent=None, picks=[], side=LEFT, anchor=W):
        Frame.__init__(self, parent)
        self.vars = []
        for pick in picks:
            var = IntVar()
            chk = Checkbutton(self, text=pick, variable=var)
            chk.pack(side=side, anchor=anchor, expand=YES)
            self.vars.append(var)

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


class Application():
    def __init__(self):
        self.window = Tk()

    def close_window(self):
        self.window.destroy()
        sys.exit()

    def close_window_escape(self, event):
        self.window.destroy()
        sys.exit()

    def get_project_path(self):
        self.path = filedialog.askdirectory()
        print(self.path)

    def callback_project_name_changed(self, *args):
        # @todo: Make groups like when you tick `tests` it ticks all the tests
        self.project_selected = self.project.get()
        if self.project_selected == "other":
            # @todo: whitelist/blacklist for options
            self.options = Checkbar(self.window, ['author', 'norme', 'Makefile'])
            self.options.pack(side=LEFT)

        if self.project_selected == "42commandements":
            self.options = None

        if self.project_selected == "libft":
            self.options = Checkbar(self.window, ['author', 'forbidden-functions', 'makefile', 'norme', 'static', 'extra', 'required', 'bonus', 'benchmark', 'tests', 'libftest', 'maintest', 'moulitest', 'fillit-checker', 'libft-unit-test'])
            self.options.pack(side=LEFT)

        if self.project_selected == "fillit":
            self.options = Checkbar(self.window, ['author', 'forbidden-functions', 'makefile', 'norme', 'tests', 'fillit-checker'])
            self.options.pack(side=LEFT)

    def start(self):
        if self.options != None:
            print(list(self.options.state()))

    def create_window(self):
        self.window.title("42PyChecker")
        self.window.minsize(width=800, height=800)
        # @todo: Set a icon for app image
        #self.window.iconbitmap(os.path.dirname(os.path.realpath(__file__)) + "/favicon.ico")
        # @todo: Find a way to loop through gif frames to have animated logo
        logo = PhotoImage(file=os.path.dirname(os.path.realpath(__file__)) + "/logo.gif")
        Label(self.window, image=logo).pack()
        Button(self.window, text="Select Project Path", width=20, command=self.get_project_path).pack()

        self.project = StringVar(self.window)
        dropdown = OptionMenu(self.window, self.project, "other", "42commandements", "libft", 'fillit')
        dropdown.pack()

        Button(self.window, text="Start", command=self.start).pack(side=BOTTOM)

        Button(self.window, text="Exit", command=self.close_window).pack(side=BOTTOM)
        self.window.bind('<Escape>', self.close_window_escape)

        self.project.trace("w", self.callback_project_name_changed)
        self.window.mainloop()
app = Application()
app.create_window()

如果您运行它并多次更改下拉菜单(更改为相同的一个或不同的选项),它将仅添加更多复选框,而不会删除任何复选框。 我猜想这是应该发生的,因为我没有删除任何内容,而是在每次更改下拉菜单时都添加了CheckBars。

现在,让我们更改一些代码,并尝试添加.destroy().pack_forget()

    def callback_project_name_changed(self, *args):
        # @todo: Make groups like when you tick `tests` it ticks all the tests
        self.project_selected = self.project.get()
        if self.project_selected == "other":
            self.options.destroy()
            # @todo: whitelist/blacklist for options
            self.options = Checkbar(self.window, ['author', 'norme', 'Makefile'])
            self.options.pack(side=LEFT)

        if self.project_selected == "42commandements":
            self.options = None

        if self.project_selected == "libft":
            self.options.destroy()
            self.options = Checkbar(self.window, ['author', 'forbidden-functions', 'makefile', 'norme', 'static', 'extra', 'required', 'bonus', 'benchmark', 'tests', 'libftest', 'maintest', 'moulitest', 'fillit-checker', 'libft-unit-test'])
            self.options.pack(side=LEFT)

        if self.project_selected == "fillit":
            self.options.destroy()
            self.options = Checkbar(self.window, ['author', 'forbidden-functions', 'makefile', 'norme', 'tests', 'fillit-checker'])
            self.options.pack(side=LEFT)

现在,当选择该选项时,输出会给我一个错误,因为self.options尚未初始化。 因此,我找到了一种解决方法,只是将is_initialized设置为0或1可以解决问题。

但是,复选框并没有被删除,只是一直被添加。

TL; DR:更改后不会删除复选框。 我要实现的是基于通过OptionMenu选择的内容具有不同的复选框列表

有没有更简单的方法?

好吧,我研究了一段时间,基于这个答案,我能够使它工作。 这是代码:

from tkinter import *
import os
import sys
from tkinter import filedialog


class Checkbar(Frame):
    def __init__(self, parent=None, picks=[], side=LEFT, anchor=W):
        Frame.__init__(self, parent)
        self.vars = []
        for pick in picks:
            var = IntVar()
            chk = Checkbutton(self, text=pick, variable=var)
            chk.pack(side=side, anchor=anchor, expand=YES)
            self.vars.append(var)

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


class Application():
    def __init__(self):
        self.window = Tk()
        self.window.title("42PyChecker")
        self.window.minsize(width=800, height=800)
        self.options_dict = {'other': ['author', 'norme', 'Makefile'],
                              'libft': ['author', 'forbidden-functions', 'makefile', 'norme', 'static', 'extra', 'required', 'bonus', 'benchmark', 'tests', 'libftest', 'maintest', 'moulitest', 'libft-unit-test'],
                              'fillit': ['author', 'forbidden-functions', 'makefile', 'norme', 'tests', 'fillit-checker'],
                              '42commandements': []}
        # @todo: Make groups like when you tick `tests` it ticks all the tests
        # @todo: Set a icon for app image
        #self.window.iconbitmap(os.path.dirname(os.path.realpath(__file__)) + "/favicon.ico")
        # @todo: Find a way to loop through gif frames to have animated logo
        logo = PhotoImage(file=os.path.dirname(os.path.realpath(__file__)) + "/logo.gif")
        Label(self.window, image=logo).pack()
        Button(self.window, text="Select Project Path", width=20, command=self.get_project_path).pack()
        self.project = StringVar(self.window)
        self.options = ['None', 'NULL']
        self.project.trace("w", self.update_options)
        dropdown = OptionMenu(self.window, self.project, *self.options_dict.keys())
        dropdown.pack()
        self.options_choices = Checkbar(self.window, self.options)
        self.options_choices.pack(side=BOTTOM)
        Button(self.window, text="Start", command=self.start).pack(side=BOTTOM)
        Button(self.window, text="Exit", command=self.close_window).pack(side=BOTTOM)
        self.window.bind('<Escape>', self.close_window_escape)

    def close_window(self):
        self.window.destroy()
        sys.exit()

    def close_window_escape(self, event):
        self.window.destroy()
        sys.exit()

    def get_project_path(self):
        self.path = filedialog.askdirectory()
        print(self.path)

    def start(self):
        print(list(self.options_choices.state()))

    def update_options(self, *args):
        self.options = self.options_dict[self.project.get()]
        self.options_choices.destroy()
        self.options_choices = Checkbar(self.window, self.options)
        self.options_choices.pack(side=BOTTOM)

    def create_window(self):
        self.window.mainloop()

它的工作方式非常简单。 您有一个包含所有项目和选项的字典。 更改下拉列表后,我们将更新列表,删除当前列表并打包新列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM