【问题标题】:How can I fix this issue with ttk.Checkbuttons being linked through different variables?如何通过不同的变量链接 ttk.Checkbuttons 来解决这个问题?
【发布时间】:2019-08-07 02:23:36
【问题描述】:

我已经使用 Python 大约两周了。我遇到了一种情况,我一生都无法找到解决方案。我在链接所有复选框时遇到问题。

我到处搜索,我看到的共同点是在声明 Checkbutton 和分配变量时意外地没有声明不同的变量。但是,正如您在下面发布的测试代码中看到的那样,我为每个复选框设置了唯一命名的变量。正如您将看到的,所有初始化为 FALSE 的变量都是链接的,并且所有初始化为 TRUE 的变量都是链接的。

当我谈到它时,有人能指出为什么这些框架如此糟糕吗?我很难理解这个网格系统。不像使用行/列来定位东西的常规表吗?根据我的经验,它现在就是这样工作的。

import tkinter
from tkinter import *
from tkinter import ttk, Checkbutton, Tk

checkbox0 = FALSE
checkbox1 = FALSE
checkbox2 = TRUE
checkbox3 = FALSE
checkbox4 = FALSE
checkbox5 = TRUE
checkbox6 = FALSE
checkbox7 = FALSE
checkbox8 = TRUE
checkbox9 = FALSE

mainWindow = Tk()

maincontent = ttk.Frame(mainWindow, borderwidth=5, relief='sunken', width=600, height=400).grid(row=0, column=0, padx=5, pady=5, sticky=NSEW)
content0 = ttk.Frame(maincontent, borderwidth=5, relief='sunken').grid(row=0, column=0, sticky=NSEW)
checkbox_0 = ttk.Checkbutton(content0, text="Checkbox 0", variable=checkbox0).grid(row=0, column=0, padx=5, pady=5)
checkbox_1 = ttk.Checkbutton(content0, text="Checkbox 1", variable=checkbox1).grid(row=1, column=0, padx=5, pady=5)
checkbox_2 = ttk.Checkbutton(content0, text="Checkbox 2", variable=checkbox2).grid(row=2, column=0, padx=5, pady=5)
checkbox_3 = ttk.Checkbutton(content0, text="Checkbox 3", variable=checkbox3).grid(row=3, column=0, padx=5, pady=5)
checkbox_4 = ttk.Checkbutton(content0, text="Checkbox 4", variable=checkbox4).grid(row=4, column=0, padx=5, pady=5)

content1 = ttk.Frame(maincontent, borderwidth=5, relief='sunken').grid(row=0, column=1, sticky=NSEW)
checkbox_5 = ttk.Checkbutton(content1, text="Checkbox 5", variable=checkbox5).grid(row=0, column=0, padx=5, pady=5)
checkbox_6 = ttk.Checkbutton(content1, text="Checkbox 6", variable=checkbox6).grid(row=1, column=0, padx=5, pady=5)
checkbox_7 = ttk.Checkbutton(content1, text="Checkbox 7", variable=checkbox7).grid(row=2, column=0, padx=5, pady=5)
checkbox_8 = ttk.Checkbutton(content1, text="Checkbox 8", variable=checkbox8).grid(row=3, column=0, padx=5, pady=5)
checkbox_9 = ttk.Checkbutton(content1, text="Checkbox 9", variable=checkbox9).grid(row=4, column=0, padx=5, pady=5)


mainWindow.mainloop()

非常感谢有人解释这里发生的事情以及如何使其正常工作。在过去的两周里,我几乎不间断地处理我的项目,我可能会超负荷。

感谢任何人提供的任何帮助。

【问题讨论】:

    标签: python python-3.x tkinter ttk


    【解决方案1】:

    您的代码有两个主要问题。首先,Checkbutton 需要一个Tkinter variable,即BooleanVarStringVarDoubleVarIntVar。所以你创建的所有变量都不适用于Checkbutton

    接下来,您反复执行maincontent=ttk.Frame(....).grid(...) 之类的操作。这将返回None,然后将其分配给您的变量maincontent。要正确保存对每个小部件的引用,您需要将其分成两行:

    maincontent=ttk.Frame(...)
    maincontent=grid(...)
    

    解决了这两个问题,下面是您的代码如何通过使用for 循环来减少重复代码的工作方式:

    import tkinter as tk
    from tkinter import ttk
    
    mainWindow = tk.Tk()
    
    all_var = [tk.BooleanVar() for _ in range(10)]
    
    maincontent = ttk.Frame(mainWindow, borderwidth=5, relief='sunken', width=600, height=400)
    maincontent.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
    content0 = ttk.Frame(maincontent, borderwidth=5, relief='sunken')
    content0.grid(row=0, column=0, sticky="nsew")
    content1 = ttk.Frame(maincontent, borderwidth=5, relief='sunken')
    content1.grid(row=0, column=1, sticky="nsew")
    
    for i in range(5):
        ttk.Checkbutton(content0, text=f"Checkbox {i}",variable=all_var[i],
                        command=lambda x=i: print(f"Checkbox {x}, {all_var[x].get()}")
                        ).grid(row=i, column=0, padx=5, pady=5)
        ttk.Checkbutton(content1, text=f"Checkbox {i+5}", variable=all_var[i+5],
                        command=lambda x=i+5: print(f"Checkbox {x}, {all_var[x].get()}")
                        ).grid(row=i, column=0, padx=5, pady=5)
    
    mainWindow.mainloop()
    

    【讨论】:

    • 谢谢!现在这很有意义。非常感谢您的帮助!
    • @SouthernYankee65 没问题。如果有帮助,请考虑接受答案,以便关闭问题。
    【解决方案2】:

    首先 * 表示您导入所有内容:

    from tkinter import *
    

    这是没用的:

    import tkinter
    from tkinter import ttk, Checkbutton, Tk
    

    其次,您使用此复选按钮多次写入相同的内容。尝试让您的工作更轻松,比如让 python 为您插​​入它们。
    我不知道为什么,但来自 tkinter 的 Checkbutton 在自动排列方面有一些优势。
    尝试改用 tkinter.ttk 中的 Checkbutton。
    并尝试使用更多的 pack() 而不是(grid),这样安排它们会更好更容易。

    这是我编写所有代码的方式,希望有用:)

    # From tkinter we will use just Tk for the root and an IntVar because tkinter.ttk have not them :P
    from tkinter import Tk, IntVar, Button
    # From tkinter.ttik will import same checkbuttons becase thei will look more natural
    # ttk will be much closer to default OS look them tkinter
    # But the probblem here is you can not use bg, relief and such like this on ttk elements
    # So if you want to add decorations on element try to import them from old/default tkinter :(((((
    from tkinter.ttk import Frame, Checkbutton
    
    root = Tk()
    
    # Define two check buttons list
    checkButtons_1 = []
    checkButtons_2 = []
    
    # We will set a number here what will be used to set the names on check buttons later
    # Because will be used on more then one place I like to change it just one time next time
    maxButtons = 10
    
    # Try to append some names for them
    # In programin the count start from 0 so we will increse the number with one to start from 1
    for i in range(maxButtons):
        # First of all we will add first half of the range
        # Because some time we can get a float we try to avoid that by converting the division in a intiger
        # But we will count with les 1 because: 10/2=5 so half is 5 but we will make i+1 so 5+1=6 is bigger the 5
        if i <= int((maxButtons / 2) - 1):
            checkButtons_1.append(f"Checkbox {i+1}")
        # How we will add the rest of them
        else:
            checkButtons_2.append(f"Checkbox {i+1}")
    
    class CheckBtn(Frame):
        def __init__(self, parent=None, selected=[], side="top", expand=True, fill="x"):
            Frame.__init__(self, parent)
            self.vars = []
    
            # For every itme new created
            for item in selected:
                # Because variabbles on checkbuttom are intiger (just 1 and 0) make an IntVar
                var = IntVar()
    
                # Make a little frame for every check box
                frame = Frame(self)
                frame.pack(side=side)
    
                # Make the check bok
                chk = Checkbutton(self, text=item, variable=var)
                chk.pack(expand=expand, fill=fill, side=side)
    
                # Save every variable state in a array list
                self.vars.append(var)
    
        # This stahe will be called later to see witch box are checked and witch not
        def state(self):
            return map((lambda var: var.get()), self.vars)
    
    class gui:
        def __init__(self, master):
            self.master = master
    
            # For the main screen we make two frame. One on top for the check buttons and one on bottom for the buttons
            frameTop = Frame(master)
            frameBottom = Frame(master)
            # Now we make two frame for the checkbuttons. One for left and one for the right side
            frameLeft = Frame(frameTop)
            frameRight = Frame(frameTop)
    
            # Here we will pack all frames. Here is important the order you pack, above you can make them on what order you want
            frameTop.pack(expand=True, fill="x", side="top")
            frameBottom.pack(expand=True, fill="x", side="bottom")
            frameLeft.pack(expand=True, fill="x", side="left")
            frameRight.pack(expand=True, fill="x", side="left")
    
            # Here we create tne check button
            # We define ch1 and ch2 because we will need to refer them to print the status later
            ch1 = CheckBtn(frameLeft, checkButtons_1)
            ch2 = CheckBtn(frameRight, checkButtons_2)
    
            # Here we pack the buttons on screen
            ch1.pack()
            ch2.pack()
    
            # We call lambda status here because our function will be after the button is pack
            # So wil llook on all file for that function.
            # With out that lambda function you need to put "seeStatus()" above the button.
            # We not need to make btn = Button(frame,...) because we will not check the buttons anywhere for now
            Button(frameBottom, text="Check status", command=lambda:seeStatus(),
                   bg="cyan", activebackground="cyan", relief="groove", bd=4
                   ).pack(expand=True, fill="x", side="left")
    
            # And for funn we add and this quit button :))
            Button(frameBottom, text="Quit", command=root.quit,
                   bg="tomato", activebackground="tomato", relief="groove", bd=4
                   ).pack(expand=True, fill="x", side="left")
    
            def seeStatus():
                print(list(ch1.state()), list(ch2.state()))
    
    # If the this file is the main file then make this
    # This basiclly check if you run the code from here or not.
    # If not then will not execute this, you can import them to another file and will run from that file.
    # Google it about. Is easy to undersnatnd.
    if __name__ == "__main__":
        gui(root)
        root.mainloop()
    

    但我不会回答你的问题,所以我只是给你一个完整的硬代码我认为......对不起。
    问题在于你制作一个新框架,你必须以两种不同的方式完成。

    # Like that
    Frame(root).pack()
    
    # Or you you refer them back to this frame you need to "give him a name"
    frame = Frame(root)
    frame.grid()
    
    # THIS NEVER WILL WORK SO GOOD
    frame = Frame(root).grid()
    

    所以你的主要问题是你如何编写包/网格需要在两个不同的行中分开......

    maincontent = Frame(mainWindow, borderwidth=5, relief='sunken', width=600, height=400)
    maincontent.grid(row=0, column=0, padx=5, pady=5, sticky=NSEW)
    
    content0 = Frame(maincontent, borderwidth=5, relief='sunken')
    content0.grid(row=0, column=0, sticky=NS)
    
    checkbox_0 = Checkbutton(content0, text="Checkbox 0", variable=checkbox0)
    checkbox_0.grid(row=0, column=0, padx=5, pady=5)
    #.......
    
    content1 = Frame(maincontent, borderwidth=5, relief='sunken')
    content1.grid(row=0, column=1, sticky=NS)
    
    checkbox_5 = Checkbutton(content1, text="Checkbox 5", variable=checkbox5)
    checkbox_5.grid(row=0, column=0, padx=5, pady=5)
    #.......
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-11
      • 2019-12-03
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 2020-12-07
      • 2020-02-22
      • 1970-01-01
      相关资源
      最近更新 更多