【问题标题】:tkinter widgets not showing in frame widgetstkinter 小部件未显示在框架小部件中
【发布时间】:2021-05-29 18:50:20
【问题描述】:

我正在尝试使用 Tkinter 库在 python 中制作 GUI。我使用了类,以便可以设置外观统一的按钮和框架。我遇到的问题是,当我将按钮放置、打包或网格到框架中时,没有显示小部件。我正在尝试让播放小部件显示在控件小部件中。

import tkinter as tk

HEIGHT = 457
WIDTH = 600
MAIN_COLOR = '#0e2625'
FG_COLOR = 'white'


photo = []


def playing():
    print('is playing')


# Create a frame framework
class Frames(tk.LabelFrame):
    def __init__(self, name, master, width, height, color=MAIN_COLOR, **kw):
        super().__init__(master, **kw)
        self.name = name
        self.master = master
        self.width = width
        self.height = height
        self.color = color

        self.frame = tk.LabelFrame(self.master, text=self.name, width=self.width, height=self.height, bg=self.color)
        self.frame['foreground'] = FG_COLOR

    def grid(self, row, column, rowspan=None, columnspan=None):
        self.frame.grid(row=row, column=column, rowspan=rowspan, columnspan=columnspan, padx=5)


# class to use as blueprint for buttons
class Buttons(tk.Button):
    counter = 0

    def __init__(self, name, master, command, image, **kw):
        super().__init__(master, **kw)

        self.name = name
        self.image = image
        self.master = master
        self.command = command
        self.ref = Buttons.counter

        global photo

        img = tk.PhotoImage(file=self.image)
        img = img.subsample(5, 5)

        photo.append(img)
        self.name = tk.Button(self.master, text=name, command=command, width=10, image=photo[self.ref], compound='left')

        Buttons.counter += 1


# configuring the root screen

root = tk.Tk()
root.title('PlayR')
root.configure(bg=MAIN_COLOR)

screen = str(WIDTH) + 'x' + str(HEIGHT)
root.geometry(screen)
root.resizable(False, False)


detail_frame = Frames('detail', root, (WIDTH / 2) - 10, 350)
detail_frame.grid(0, 0, 1, 1)

image_frame = Frames('cover', root, (WIDTH / 2) - 10, 350)
image_frame.grid(0, 1, 1, 1)

control_frame = Frames('controls', root, WIDTH - 20, 100)
control_frame.grid(1, 0, 1, 2)


play = Buttons('play', control_frame, playing, 'Assets/play-button-arrowhead.png')
play.grid(row=0, column=0)

pause = Buttons('pause', control_frame, playing, 'Assets/pause.png')
pause.grid(row=0, column=1)

stop = Buttons('stop', control_frame, playing, 'Assets/stop.png')
stop.grid(row=0, column=2)

prev = Buttons('prev', control_frame, playing, 'Assets/previous.png')
prev.grid(row=0, column=3)

play_next = Buttons('next', control_frame, playing, 'Assets/next.png')
play_next.grid(row=0, column=4 )

root.mainloop()

【问题讨论】:

  • 您知道当您调用Frames.__init__ 方法时会创建2 个tk.LabelFrames 对吗?
  • 另外你不需要global photo,因为它是一个可变对象。

标签: tkinter button widget frame display


【解决方案1】:

您没有正确使用继承。我们来看看这段代码:

# Create a frame framework
class Frames(tk.LabelFrame):
    def __init__(self, name, master, width, height, color=MAIN_COLOR, **kw):
        super().__init__(master, **kw)
        ...
        self.frame = tk.LabelFrame(self.master, text=self.name, width=self.width, height=self.height, bg=self.color)

这会创建 两个 框架小部件。实例本身 (self) 是一个 LabelFrameself.frame 是另一个标签框。

稍后,您创建了一个名为detail_frame 的类的实例,并在其中放置了一个按钮。该按钮是detail_frame 的子元素不是内框self.frame。由于您的自定义 grid 方法适用于 self.frame 而不是 self,因此永远不会将 detail_frame 添加到根目录,因此它及其所有子代都是不可见的。

正确的解决方案是创建self.frame。由于self 已经是一个框架,因此您尝试做的事情完全没有必要。您也不需要覆盖 grid 命令,因为您没有添加任何值。

Buttons 类也犯了同样的错误。当它应该只创建一个按钮时,它会创建两个按钮。

【讨论】:

  • 非常感谢。我从来没有真正考虑过继承,现在它才开始有意义
【解决方案2】:

试试这个:

import tkinter as tk

# Well done on setting up constants
HEIGHT = 457
WIDTH = 600
MAIN_COLOR = '#0e2625'
FG_COLOR = 'white'


def playing():
    print('is playing')


# Create a frame framework
class Frames(tk.LabelFrame):
    def __init__(self, master, color=MAIN_COLOR, **kwargs):
        self.color = color

        super().__init__(self.master, bg=self.color, fg=FG_COLOR, **kwargs)

    def grid(self, **kwargs):
        # Use kwargs because later you will forget the order of your args.
        # Try it now: was it (row, column) or (column, row)
        super().grid(padx=5, **kwargs)


# class to use as blueprint for buttons
class Buttons(tk.Button):
    # Master always goes first (tkinter convention)
    def __init__(self, master, image, width=10, **kwargs):
        self.image = image

        # This is a better way of keeping a reference of the image
        self.img = tk.PhotoImage(file=self.image)
        self.img = self.img.subsample(5, 5)

        super().__init__(master, width=width, image=self.img, compound='left', **kwargs)



# configuring the root screen

root = tk.Tk()
root.title('PlayR')
root.configure(bg=MAIN_COLOR)

screen = str(WIDTH) + 'x' + str(HEIGHT)
root.geometry(screen)
root.resizable(False, False)


control_frame = Frames(root, text='controls', width=WIDTH - 20, height=100)
control_frame.grid(row=1, column=0, columnspan=2)

play = Buttons(control_frame, text='play', command=playing, image='img.png')
play.grid(row=0, column=0)

root.mainloop()

正如@BryanOakley 所说,您没有正确使用继承。您的代码也不是pythonic。我想我让它更pythonic,我认为它现在可以工作了。

【讨论】:

  • self.master = masterFrames.__init__() 不是必需的,因为每个 tkinter 小部件 self.master 都是隐式创建的。
  • @acw1668 真的谢谢。我从另一个班级中删除了self.master = master,但忘记了那个:D。
  • 你是对的。这更容易阅读,看起来更好。谢谢
  • @kayongofwoloshi 如果你想让你的代码看起来更好看this
猜你喜欢
  • 2014-09-04
  • 1970-01-01
  • 2011-08-21
  • 2019-04-23
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 2021-06-08
  • 2018-07-15
相关资源
最近更新 更多