【问题标题】:Can't see tkinter buttons/labels in frame在框架中看不到 tkinter 按钮/标签
【发布时间】:2020-09-23 04:18:59
【问题描述】:

我为框架定义了 2 个按钮和一个标签,但我看不到它们。 我尝试使用 pack()、grid()、place()。 如果我注释掉框架线,我可以看到容器框架(右框架)上的效果。

大图:

import tkinter as tk
import subprocess as sub
import multiprocessing as mp
import shutil
import time
import io
import os

class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.geometry("640x478")
        self.title("Gil Shwartz GUI Project")
        self.resizable(0, 0)
        menu = tk.Frame(self, height=250, width=10, relief="solid")
        container = tk.Frame(self, relief="flat", height=200, bg="black")
        menu.pack(side=tk.LEFT, fill="both", anchor="w")
        container.pack(side=tk.TOP, fill="both", expand=True)
        menu.grid_rowconfigure(0, weight=1)

        self.frames = ["Menu", "MainWelcome", "TestPing", "PageOne", "UptimeCheck"]

        self.frames[0] = Menu(parent=menu, controller=self)
        self.frames[1] = MainWelcome(parent=container, controller=self)
        self.frames[2] = TestPing(parent=container, controller=self)
        self.frames[3] = PageOne(parent=container, controller=self)
        self.frames[4] = UptimeCheck(parent=container, controller=self)

        self.frames[0].grid(row=0, column=0, sticky="nsew")
        self.frames[1].grid(row=0, column=0, sticky="nsew")
        self.frames[2].grid(row=0, column=0, sticky="nsew")
        self.frames[3].grid(row=0, column=0, sticky="nsew")
        self.frames[4].grid(row=0, column=0, sticky="nsew")

        self.show_frame(1)

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        print(frame)
        frame.tkraise()
        frame.grid(row=0, column=0, sticky="nsew")

class Menu(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        button1 = tk.Button(self, text="Ping Test", bg="royalblue2",
                            command=lambda: controller.show_frame(2))
        button2 = tk.Button(self, text="Uptime Check", bg="dark violet",
                            command=lambda: controller.show_frame(4))
        buttun3 = tk.Button(self, text="Home", bg="pale goldenrod",
                            command=lambda : controller.show_frame(1))
        button4 = tk.Button(self, text="Quit", bg="gray40",
                            command=lambda: self.terminate())

        button1.pack(fill="both", expand=True)
        button2.pack(fill="both", expand=True)
        buttun3.pack(fill="both", expand=True)
        button4.pack(fill="both", expand=True)

    def terminate(self):

        path = fr'c:/users/{os.getlogin()}/desktop/Gui-Skeleton'

        try:
            os.rmdir(path)
        except OSError as err:
            print(f"Error Deleting tmp folder! {err}")

        exit()


class MainWelcome(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        canvas = tk.Canvas(self, bg="black")
        canvas.pack(expand=True, fill="both")


class TestPing(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, bg="skyblue1")
        self.controller = controller

        self.output = tk.LabelFrame(self, text="Output", height=325, width=580, padx=3, pady=3)
        self.output.pack(side=tk.BOTTOM, fill="both", expand=True)
        self.textbox = tk.Text(self, height=320, width=550, pady=3, padx=3)
        self.textbox.pack(side=tk.BOTTOM, fill="both", expand=True)
        self.clear_file = tk.BooleanVar()
        self.clear_file.set(False)
        self.url_label = tk.Label(self, text="Enter URL : ", padx=7, pady=5, bg="skyblue1")
        self.url_input_box = tk.Entry(self)
        self.url = self.url_input_box.get()
        self.url_input_box.grid_columnconfigure(0, weight=0)
        self.file_name_label = tk.Label(self, text="Enter Filename: ", bg="skyblue1")
        self.file_name_input_box = tk.Entry(self)
        self.filename = self.file_name_input_box.get()
        self.default_file = fr'c:/users/{os.getlogin()}/desktop/default-tmp.txt'
        self.clear_file_label = tk.Label(self, text="Clear File?", padx=5, pady=5, bg="skyblue1")
        self.clear_file_radio_yes = tk.Radiobutton(self, text="yes", value=True, var=self.clear_file, bg="skyblue1",
                                           command=lambda: self.callback(self.clear_file.get()))
        self.clear_file_radio_no = tk.Radiobutton(self, text="no", value=False, var=self.clear_file, bg="skyblue1",
                                          command=lambda: self.callback(self.clear_file.get()))
        self.submit_button = tk.Button(self, text="Submit", width=10, height=1,
                                    command=lambda: self.condition(self.url_input_box.get(),
                                                             self.clear_file.get(), self.file_name_input_box.get()))
        self.clear_fields_button = tk.Button(self, text="Clear Fields", width=10,
                                      command=lambda: self.clear_boxes(self.url_input_box, self.file_name_input_box))

        self.url_label.pack(anchor="w")
        self.url_input_box.pack(anchor="w", padx=10)
        self.file_name_label.pack(anchor="w", padx=7, pady=5)
        self.file_name_input_box.pack(anchor="w", padx=10)
        self.clear_file_label.pack(anchor="w")
        self.clear_file_radio_yes.pack(anchor="w")
        self.clear_file_radio_no.pack(anchor="w")
        self.submit_button.pack(anchor="w", pady=1)
        self.clear_fields_button.pack(anchor="w")

    @classmethod
    def clear_boxes(self, urlInputBox, fileNameInputBox):
        urlInputBox.delete(0, "end")
        fileNameInputBox.delete(0, "end")

    @classmethod
    def callback(self, clearFile):
        print(f'Clear file = {clearFile}')  # Debugging Mode - check Radio box Var.

    def condition(self, host, clearFile, filenameInputBox):

        print(clearFile, filenameInputBox)  # Debugging - Input Validation
        if clearFile is True and filenameInputBox == '':
            self.handler_clr_yes_fn_no(host)
        elif clearFile is False and filenameInputBox == '':
            self.handler_clr_no_fn_no(host)
        elif clearFile is True and filenameInputBox != '':
            self.handler_clr_yes_fn_yes(host, filenameInputBox)
        elif clearFile is False and filenameInputBox != '':
            self.handler_clr_no_fn_yes(host, filenameInputBox)

    def handler_clr_yes_fn_no(self, host):

        startprocs = []
        # nextprocs = []
        lastprocs = []

        proc1 = mp.Process(name="Clear + No Filename + WriteFile",
                           target=self.clr_yes_fn_no_writefile, args=(host,))
        proc2 = mp.Process(name="Clear + No Filename + PrintOutput",
                          target=self.clr_yes_fn_no_print_output, args=(host,))
        # proc3 = mp.Process(name="Clear + No Filename + Generate PrintOutput to GUI",
        #                    target=self.generate_clr_yes_fn_no_print_output_to_gui, args=(host,))
        # proc4 = mp.Process(name="Clear + No Filename + PrintOutput to GUI",
        #                    target=self.clr_yes_fn_no_print_output_to_gui, args=(host,))
        proc5 = mp.Process(name="Remove first line + Write new default file",
                           target=self.delete_default_lines)

        startprocs.append(proc1)
        startprocs.append(proc2)
        # startprocs.append(proc3)
        # startprocs.append(proc4)

        # nextprocs.append(proc1)

        lastprocs.append(proc5)

        for s in startprocs:
            s.start()

        for s2 in startprocs:
            s2.join()

        # for n in nextprocs:
        #     n.start()
        #
        # for p in nextprocs:
        #     p.join()

        for l in lastprocs:
            l.start()

    def handler_clr_no_fn_no(self, host):

        procs = []
        nextprocs = []

        proc1 = mp.Process(name="Append to default file",
                           target=self.clr_no_fn_no_writefile, args=(host,))
        proc2 = mp.Process(name="Print Output", target=self.clr_no_fn_no_printoutput, args=(host,))

        procs.append(proc1)
        procs.append(proc2)

        for proc in procs:
            proc.start()
        for proc in procs:
            proc.join()

        for p in nextprocs:
            p.start()

    def handler_clr_yes_fn_yes(self, host, filenameInputBox):

        procs = []
        nextprocs = []

        proc1 = mp.Process(name="Clear file + userFilename + Write to file",
                           target=self.clr_yes_fn_yes_writefile, args=(host, filenameInputBox,))
        proc2 = mp.Process(name="Clear file + user filename + Print output",
                           target=self.clr_yes_fn_yes_printoutput, args=(host,))
        proc3 = mp.Process(name="Remove Empty Lines from user filename",
                           target=self.delete_userfile_lines, args=(filenameInputBox,))

        procs.append(proc1)
        procs.append(proc2)
        nextprocs.append(proc3)

        for proc in procs:
            proc.start()

        for p in procs:
            p.join()

        for np in nextprocs:
            np.start()

    def handler_clr_no_fn_yes(self, host, filenameInputBox):

        procs = []

        proc1 = mp.Process(name="Keep File + Userfilename + Append to Userfile",
                           target=self.clr_no_fn_yes_writefile, args=(host, filenameInputBox,))
        proc2 = mp.Process(name="Keep File + Userfilename + Print Output",
                           target=self.clr_no_fn_yes_printoutput, args=(host,))

        procs.append(proc1)
        procs.append(proc2)

        for p in procs:
            p.start()

        for p2 in procs:
            p2.join()

    @classmethod
    def delete_default_lines(cls):

        time.sleep(1.5)
        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}')
        file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt'
        newfile = fr'c:/users/{os.getlogin()}/Desktop/default.txt'

        with open(file, 'r') as inp, open(newfile, 'w+') as out:
            for line in inp:
                if not line.isspace():
                    out.write(line.lstrip())
                    out.write('')
            inp.close()
            out.close()
        os.remove(file)

    @classmethod
    def delete_userfile_lines(cls, filename):

        time.sleep(1.5)
        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}')
        file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/{filename}-tmp.txt'
        newfile = fr'c:/users/{os.getlogin()}/Desktop/{filename}.txt'

        with open(file, 'r+') as inp, open(newfile, 'w+') as out:
            for line in inp:
                if not line.isspace():
                    out.write(line.lstrip())
                    out.write('')
            inp.close()
            out.close()
        os.remove(file)

    @classmethod
    def clr_yes_fn_no_print_output(self, host):

        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
        with sub.Popen(["ping", "-n", "4", f'{host}'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    @classmethod
    def generate_clr_yes_fn_no_print_output_to_gui(self, host):
        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')

        sub.run(f"ping {host}", shell=True, capture_output=True)

    @classmethod
    def clr_yes_fn_no_print_output_to_gui(self):
        tk.Frame.__init__(self, parent)
        self.textbox.insert(tk.END, proc.stdout.decode())

    @classmethod
    def clr_yes_fn_no_writefile(self, host):

        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
        file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt'
        ping = sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE)
        with open(file, 'w+') as output:
            data = output.read()
            for line in ping.stdout.readlines():
                data += str(line.decode())
            ping.stdout.close()
            output.seek(0)
            output.write(data.lstrip())

    @classmethod
    def clr_no_fn_no_printoutput(self, host):

        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
        with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    @classmethod
    def clr_no_fn_no_writefile(self, host):

        print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}')
        with open(fr'c:/users/{os.getlogin()}/Desktop/default.txt', 'a') as output:
            sub.call(["ping", "-n", '4', f'{host}'], stdout=output)

    @classmethod
    def clr_yes_fn_yes_printoutput(self, host):

        with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    @classmethod
    def clr_yes_fn_yes_writefile(self, host, filename):

        file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/{filename}-tmp.txt'
        with open(file, 'w') as output:
            sub.call(["ping", "-n", '4', f'{host}'], stdout=output)

    @classmethod
    def clr_no_fn_yes_printoutput(self, host):

        with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    @classmethod
    def clr_no_fn_yes_writefile(self, host, filename):

        with open(fr'c:/users/{os.getlogin()}/Desktop/{filename}.txt', 'a') as output:
            sub.call(["ping", "-n", '4', f'{host}'], stdout=output)


class UptimeCheck(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        frame = tk.LabelFrame(self, text="Uptime Check", bg="honeydew3", relief="flat")
        frame.pack(fill="both", expand=True)

        win7_label = tk.Label(self, text="Choose OS", padx=3)
        win7_label.pack()

        win7_button = tk.Button(self, text="Windows 7")
        win10_button = tk.Button(self, text="Windows 10")

        win7_button.pack(side=tk.TOP, anchor="n")
        win10_button.pack(side=tk.TOP, anchor="n")

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 1", bg="red")
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to page 2",
                           command=lambda: controller.show_frame(2))
        button.pack()


if __name__ == "__main__":

    path = fr'c:/users/{os.getlogin()}/desktop/Gui-Skeleton'

    try:
        os.mkdir(path)

    except OSError as err:
        print(f"[!] Operation failed! {err}")

    app = GUI()
    app.mainloop()

正常运行时间类:

class UptimeCheck(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        frame = tk.LabelFrame(self, text="Uptime Check", bg="honeydew3", relief="flat")
        frame.pack(fill="both", expand=True)

        win7_label = tk.Label(self, text="Choose OS", padx=3)
        win7_label.pack()

        win7_button = tk.Button(self, text="Windows 7")
        win10_button = tk.Button(self, text="Windows 10")

        win7_button.pack(side=tk.TOP, anchor="n")
        win10_button.pack(side=tk.TOP, anchor="n")

.................................................. ..................................................... ..................................................... ..................................................... ..................................................... ..................................................... .....................

【问题讨论】:

  • 那是很多代码。您能否确定您在使用哪些按钮时遇到问题。
  • 我将特定类粘贴在主代码下方。除了框架我什么都看不到。
  • 想不通。但似乎带有文本“正常运行时间检查”的 LabelFrame 比父级大......,在我看来,包装在 LabelFrame 中的小部件在那里,但由于某种原因你看不到它们。如果我在根窗口中单独运行 UptimeCheck() 类,它就可以工作。
  • GUI.__init__() 中添加container.rowconfigure(0, weight=1)container.columnconfigure(0, weight=1)
  • @acw1668 - 准点!你为什么不把它作为答案?

标签: python-3.x user-interface tkinter tkinter-layout


【解决方案1】:

您应该将按钮的父小部件设置为框架而不是自身。 要将项目放置在框架内,项目的父项应该是框架。

改变

win7_button = tk.Button(self, text="Windows 7")

win7_button = tk.Button(frame, text="Windows 7")

(win10 按钮也是如此)

【讨论】:

  • 不幸的是什么也没做。以下 acw1668 为我完成了这项工作。
【解决方案2】:

所以这是 acw 评论后的工作代码:

正常运行时间类:

class UptimeCheck(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, bg="skyblue1")

        self.controller = controller
        self.output = tk.LabelFrame(self, text="Output", height=250, width=580,
                                    padx=3, pady=3, relief="flat")

        self.win7_label = tk.Label(self, text="Choose OS", padx=3, pady=10, bg="skyblue1")
        self.win7_button = tk.Button(self, text="Windows 7", borderwidth=2, padx=10)
        self.win10_button = tk.Button(self, text="Windows 10", borderwidth=2, padx=10)
        self.linux_debian = tk.Button(self, text="Linux Debian", borderwidth=2, padx=10)

        self.output.pack(side=tk.BOTTOM)
        self.win7_label.pack(anchor="nw")
        self.win7_button.pack(anchor="nw")
        self.win10_button.pack(anchor="nw")
        self.linux_debian.pack(anchor="nw")

主控制器类:

class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.geometry("640x478")
        self.title("Gil Shwartz GUI Project")
        self.resizable(0, 0)
        menu = tk.Frame(self, height=250, width=10, relief="solid")
        container = tk.Frame(self, relief="flat", height=200, bg="black")
        menu.pack(side=tk.LEFT, fill="both", anchor="w")
        container.pack(side=tk.TOP, fill="both", expand=True)
        menu.grid_rowconfigure(0, weight=1)
        container.rowconfigure(0, weight=1)
        container.columnconfigure(0, weight=1)

        self.frames = ["Menu", "MainWelcome", "TestPing", "PageOne", "UptimeCheck"]

        self.frames[0] = Menu(parent=menu, controller=self)
        self.frames[1] = MainWelcome(parent=container, controller=self)
        self.frames[2] = TestPing(parent=container, controller=self)
        self.frames[3] = PageOne(parent=container, controller=self)
        self.frames[4] = UptimeCheck(parent=container, controller=self)

        self.frames[0].grid(row=0, column=0, sticky="nsew")
        self.frames[1].grid(row=0, column=0, sticky="nsew")
        self.frames[2].grid(row=0, column=0, sticky="nsew")
        self.frames[3].grid(row=0, column=0, sticky="nsew")
        self.frames[4].grid(row=0, column=0, sticky="nsew")

        self.show_frame(1)

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        print(frame)
        frame.tkraise()
        frame.grid(row=0, column=0, sticky="nsew")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-26
    • 2021-01-24
    • 2020-03-19
    • 2016-10-20
    • 2021-11-13
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    相关资源
    最近更新 更多