【问题标题】:Tkinter: Making a button panel contained in a classTkinter:制作一个包含在类中的按钮面板
【发布时间】:2018-08-09 03:16:06
【问题描述】:

为了清楚起见,我编辑了这篇文章。我想使用一个类从列表中生成按钮。在当前脚本中,我没有使用列表,我只是用变量 app1 实例化类,然后全屏显示:

如果我取消注释 list = [1,2,3],并取消注释 def button(): 函数,我会得到一个空白屏幕。我怀疑使用“Place Buttons Grid”布局时按钮会相互重叠,所以我制作了一个“Place Buttons Fill”布局用于测试。

我的最终目标是生成一个如下所示的 GUI:

但我知道我没有正确引用该类。我该怎么做?

import tkinter as tk
from tkinter import font
from tkinter import *

class alertButton(object):

    def __init__(self, Canvas):

        self.canvas=Canvas
        myFont = font.Font(family='Helvetica', size=36, weight='bold')

        #Configure Buttons
        self.alertButton = Button(Canvas,text="Button 1",font=myFont, command=self.alertCycle, height=2, width=6)
        self.quitButton = Button(canvas,text="Quit",font=myFont, command=canvas.quit, height=2, width=6)

        #Place Buttons Pack
        #self.alertButton.pack(padx=25, ipady=15, side=LEFT)  # Pack from right to left
        #self.quitButton.pack(padx=25, ipady=15, side=LEFT)
        ##This quit button only exists to exit full screen.  Will remove later

        #Place Buttons Grid
        self.alertButton.grid(row=0,column=0,padx=20)
        self.quitButton.grid(row=0,column=1,padx=20)
        ##This quit button only exists to exit full screen.  Will remove later

    def alertCycle(self):
        print("Button Pressed")
        #print (alertButton.i)
        return

#list = [1,2,3]

#def button():
#    for i in range(list):
#        app[i]=alertButton(canvas)

root = tk.Tk()

root.title("Sensor GUI")
root.wm_attributes('-fullscreen', 'true')

canvas = tk.Canvas(root, bd=0, highlightthickness=0)
canvas.pack(fill=BOTH, expand=1)

app1 = alertButton(canvas)

root.mainloop()

【问题讨论】:

  • 你能把它变成一个我们可以实际运行的minimal reproducible example吗?如果我删除所有明显的语法错误和对我没有的目录中的图像文件的引用,我得到的是大约 8 个高而窄的按钮,分布在屏幕上。没有 20 个(或 40 个)的唯一原因是,您无法在 700 像素宽的画布中放置这么多具有​​ 25 像素填充的按钮。因此,如果您没有看到相同的内容,那么您的实际代码和我通过尝试修复您粘贴的非运行代码得到的代码之间可能存在一些不同。
  • 另外,def button 行没有被评论,所以我不明白你取消评论是什么意思。 (如果你评论它,你只会得到一个NameError 并且程序退出......)
  • @abarnert 我更改了代码以使其正常工作。我认为我的“网格”放置会导致新按钮彼此重叠,所以我将“包装”放置部分留在里面并注释掉。我不知道如何引用该类来生成多个按钮。我犯了哪些语法错误,您更改为生成多个又高又窄的按钮?如果我能越过那个障碍,我就能弄清楚按钮的排列方式。我使用带有 list = [1,2,3] 的注释按钮()函数的方式是正确的方向吗?我想稍后用 JSON 填充我的按钮。

标签: python class oop tkinter


【解决方案1】:

您可能会设法将所有按钮都放在一个循环中以稍微简化它们的创建。

  • 我让AlertPanel 继承自tk.Frame,这是存放按钮集合的合适容器;所以本质上,AlertPanel 是一个tk.Frame。在您发布的代码中使用tk.Canvas 尽管可能,但似乎并不正确。
  • AlertPanel 正在管理tk.Buttons 的集合,以及由每个按钮激活的方法所代表的一系列动作。 Button 1 和 2 绑定到 alert_cycle_1 和 2;剩下的到alert_cycle_3_to_8,您可以将其替换为您希望每个按钮触发的相应操作。
  • make_alert_buttons 正在使用正确的文本创建每个按钮,为其附加正确的操作,并将按钮放置在面板上的相应位置。
  • 按钮的大小和外观可能需要稍作调整才能更好看;我没有碰你的规格。
  • 请注意删除全屏是因为我的系统出现故障似乎无法关闭窗口。

这给出了这样的结果:

import tkinter as tk       # <-- avoid star imports
from tkinter import font

class AlertPanel(tk.Frame):   # <-- is a tk.Frame, and can be manipulated as such

    def __init__(self, master):
        self.master = master
        super().__init__(self.master)

        self.myFont = font.Font(family='Helvetica', size=36, weight='bold')

        self.alert_actions = tuple([self.alert_cycle_1, self.alert_cycle_2] +\
                                   [self.alert_cycle_3_to_8] * 6 +\
                                   [self._quit])
        self.alert_buttons = []
        self.make_alert_buttons()
        self.pack(fill=tk.BOTH, expand=True)   # <-- because self is a tk.Frame

    def make_alert_buttons(self):
        btn_idx = 0
        for row in range(3):
            for col in range(3):
                action = self.alert_actions[btn_idx]
                b_text = f"Button {btn_idx + 1}"
                if row == 2 and col == 2:
                    b_text = "Quit"
                b = tk.Button(self, 
                              text=b_text,
                              font=self.myFont, 
                              command=action, 
                              height=2, width=6)
                b.grid(row=row, column=col, padx=20)
                self.alert_buttons.append(b)
                btn_idx += 1
        self.alert_buttons = tuple(self.alert_buttons)


    def alert_cycle_1(self):
        print("Alert Button 1 Pressed")

    def alert_cycle_2(self):
        print("Alert Button 2 Pressed")

    def alert_cycle_3_to_8(self):   # <-- replace with appropriate action for  buttons 3 to 8
                                    #     and update self.alert_actions accordingly
        print("Alert Button 3 to 8 Pressed")

    def _quit(self):
        self.master.destroy()


root = tk.Tk()
root.title("Sensor GUI")
# root.wm_attributes('-fullscreen', 'true')  # <-- untested
app1 = AlertPanel(root)
root.mainloop()

[编辑]:再想一想,将类命名为 AlertButtonPanel 可能是一个更好的主意

【讨论】:

  • 感谢您非常完整的回答!这绝对完成了我开始学习的内容。我想使用 tk.canvas 因为你可以用画布绘制背景。我正在添加的脚本当前使用 LED 来指示与我的服务器的连接,红色 = 坏 绿色 = 好。我的想法是使用背景作为连接的快速视觉指示器,但我认为我可能可以在 tk.frame 中使用绿色和红色标签元素。非常感谢!
  • 酷,很高兴我能帮上忙
  • 我的警报按钮面板应该在课堂之外吗?我开始认为类对象应该只描述按钮及其操作。我不会实例化多个面板,只实例化按钮。我正在自学 Python,我这样做是为了正确理解类。
  • 您可以定义一个 class App(tk.Frame)(继承自 Frame),其中包含一个用于按钮的 AlertPanel Frame。您可能可以直接使用它,只需要进行更改以将正确的操作附加到您的按钮,并对按钮的外观进行一些外观更改。
  • 不,我的意思是,我了解您发送的脚本(或者我认为我了解)。但是,为什么类中包含框架?我不想实例化多个框架,只是多个按钮。
猜你喜欢
  • 2020-04-21
  • 2013-02-07
  • 2012-10-29
  • 2021-12-03
  • 1970-01-01
  • 2016-03-10
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多