【问题标题】:Select and plot lists through checkbuttons (python, tkinter)通过复选按钮选择和绘制列表(python、tkinter)
【发布时间】:2020-10-13 12:02:37
【问题描述】:

假设我有一个多维列表:

my_list = [[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7]]

现在我想用 Tkinter 创建一个 GUI,可以通过复选框来选择哪些子列表应该绘制在直方图中。所以对于这个例子,我想象三个复选框(标记为 0、1、2)和一个Button“显示直方图”。假设我选中了标记为 1 和 2 的复选框并按下“显示直方图”按钮,它应该显示 my_list[0]my_list[1] 的直方图(最好作为一个画布上的子图)。 方法是什么?

【问题讨论】:

标签: python tkinter checkbox tkinter.checkbutton


【解决方案1】:

OOP 示例

定义一个class SubplotCheckbutton ...,继承自tk.Checkbutton
扩展 tk.Checkbutton 小部件:

  • 命名参数subplot=
  • 必填tk.Variable,这里是tk.IntVar
  • 类方法checked(),根据检查状态返回True/False

参考


  1. init方法中的参数parent**kwargs是什么意思?
    每个Tkinter 小部件都需要一个parent。因此,所有Tkinterwidgets 类对象的第一个参数采用parent 参数。 Tkinter 中的父级指定您的小部件(此处为Checkbutton)在哪个小部件中进行布局。
    • class App(tk.Tk): => self
    • SubplotCheckbutton(self, ...
    • def __init__(..., parent, ...
    • super().__init__(parent, ... => tk.Checkbutton(parent)

**kwargs已知单词参数 的缩写,类型为 dict
这里:text=str(i)subplot=subplot

  1. 将继续...

import tkinter as tk


class SubplotCheckbutton(tk.Checkbutton):
    def __init__(self, parent, **kwargs):
        # Pop the 'subplot=' argument and save to class member
        self.subplot = kwargs.pop('subplot')

        # Extend this class with the required tk.Variable
        self.variable = tk.IntVar()

        # __init__ the inherited (tk.Checkbutton) class object
        # Pass the argument variable= and all other passed arguments in kwargs
        super().__init__(parent, variable=self.variable, **kwargs)

    # Extend this object with a checked() method
    def checked(self):
        # Get the value from the tk.Variable and return True/False
        return self.variable.get() == 1

用法

注意:不是root,类对象App是根对象,所以必须使用self作为父对象:

  • SubplotCheckbutton(self, ...
  • Button(self, ...
class App(tk.Tk):
    def __init__(self):
        super().__init__()

        my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
        self.channels = []

        for i, subplot in enumerate(my_list):
            self.channels.append(SubplotCheckbutton(self, text=str(i), subplot=subplot))
            self.channels[-1].pack()

        tk.Button(self, text="Show Histograms", command=self.show).pack()

    def show(self):
        for channel in self.channels:
            if channel.checked():
                fig, ax = plt.subplots()
                y, x, _ = ax2.hist(channel.subplot, bins = 150)
                plt.show()


if __name__ == '__main__':
    App().mainloop()

【讨论】:

  • 谢谢!我不明白一切。 1、init方法中的参数parent**kwargs是什么意思?在初学者教程中,我了解到您将 self 和所有类变量放在 init 方法中。父母是什么意思?它是否会损害我继承自的类的所有类变量(在这种情况下为 tk.Checkbutton)? 2. kwargs.pop() 究竟是做什么的?子情节参数在哪里传递,什么被弹出? 3. super().__innit__() 方法没有参数是什么意思(在 App(tk.Tk) 类中) 4. 一般来说,OOP 方法有什么好处?
  • @Jailbone 那么父母只是约定?:是的。 **kwargs 事情清楚了吗?
  • 不是 100%。让我解释一下我是如何理解代码的。所以App() 类只是通过my_list 的枚举将SubplotCheckbutton 类附加到具有相应**kwargs 的列表中,并在屏幕上打包Checkbuttons。如果检查通道,它们会被绘制出来。我缺少的链接是,如果检查了频道,它是如何被验证的。这发生在SubplotCheckbutton 类本身中。正如我所看到的,这个类有两个类变量(子图和变量)。为什么不需要在innit 方法中指定它们?所以基本上我不明白这个类是做什么的。
  • 将 Checkbutton 打包到屏幕上。:在Tkinter 中说:小部件,这里是SubplotCheckbutton,布局在@987654364 中@ Toplevel 窗口,当您使用 Pack Layout Managerself 传递为 parent 时。
  • 我缺少的链接是,如果检查了频道,它是如何实现的。:它在def checked(... 内部完成。它和你的一样:if varChannels[i].get() == 1: 但面向对象,意味着对象SubplotCheckbutton 知道检查状态。这是 OOP 的一个好处,ALL 都在同一个对象中。因此它被称为面向对象编程
【解决方案2】:
root = Tk()

my_list = [[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7]]

var = IntVar()
var2 = IntVar()
var3 = IntVar()

def show():
    

    if var.get() == 1: 
        fig, ax = plt.subplots()
        y, x, _ = ax.hist(my_list[0], bins = 150)
        

    if var2.get() == 1:
        fig2, ax2 = plt.subplots()
        y, x, _ = ax2.hist(my_list[1], bins = 150)
        

    if var3.get()    def checked(self):
        return self.variable.get() == 1

 == 1:
        fig3, ax3 = plt.subplots()
        y, x, _ = ax3.hist(my_list[2], bins = 150)
    
    plt.show()





button = Button(root, text = "Show Histograms", command = show).pack()

c = Checkbutton(root, text = 'first list', variable = var).pack()
c2 = Checkbutton(root, text = 'second list', variable = var2).pack()
c3 = Checkbutton(root, text = 'third list', variable = var3).pack()


root.mainloop()

更新:我设法把它写得更紧凑,但它不是那样工作的:

my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
varChannels = []
checkbuttonChannels = []

def show():
    for i in range(3):
        if varChannels[i] == 1:
            fig, ax = plt.subplots()
            y, x, _ = ax2.hist(my_list[i], bins = 150)
            plt.show()



for _ in range(3):
    varChannels.append(IntVar())
    checkbuttonChannels.append('0')

for i in range(3):
    checkbuttonChannels[i] = Checkbutton(root, text = str(i), variable = varChannels[i]).pack()

button = Button(root, text = "Show Histograms", command = show).pack()

root.mainloop()

【讨论】:

  • 但它不起作用:应该是:if varChannels[i].get() == 1:
  • 非常感谢!现在可以了。你能用几句话解释一下你的代码是如何工作的吗?我对上课的东西真的很陌生。所以我可以学习。
猜你喜欢
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 2012-12-02
  • 2016-09-11
相关资源
最近更新 更多