如何在项目的多个模块中构建 GUI 屏幕?

huangapple go评论74阅读模式
英文:

How to build gui screens in multiple modules of a project?

问题

以下是您要翻译的内容:

This is a simplification of my project. The code should run when all files are put in the same folder and mainframe.py is run. I want to be able to return to the mainframe screen from the auxscreen after refreshing the auxscreen (the counter should be > 0). While returning to the mainframe is possible if the auxscreen is not refreshed, it will not return if auxscreen has been refreshed. I can't figure out what is going on or how to fix it.

I've been putting all the gui classes in the mainframe.py file, but it is getting overcrowded now and the automatic inspections in pycharm are taking a long time to complete. I want to start putting gui classes another module which run on the same tkinter root (vars.root in the example). The first problem I had was circular dependancies, so I needed a way to return to the main screen after the auxscreen finished. You can see in the command of the button going to the auxframe, I coded a boomerang that returns and rebuilds the mainframe once the auxscreen is quit and destroyed. The problem is that it stops working after the auxscreen has been recreated.

The first file is named vars.py

root = None

The second file is called mainframe.py

from tkinter import Tk, Label, Button, BOTH, BOTTOM
import vars
from makewindow import MakeWindow
from auxframe import AuxFrame


class MainFrame:
    def __init__(self):
        self.win = None

    def start_up(self, frame=None):
        self.win = MakeWindow()  # call makewindow.py
        self.win.create(frame)  # creates the frame for the root
        Label(self.win.topframe, text="Main Screen").pack()
        Button(self.win.topframe, text="Go to auxframe", command=lambda: (AuxFrame().create(self.win.topframe), MainFrame().start_up())).pack(fill=BOTH, side=BOTTOM)
        Button(self.win.topframe, text="Quit", command=lambda: vars.root.quit()).pack(fill=BOTH, side=BOTTOM)
        self.win.finish()


vars.root = Tk()
MainFrame().start_up()

The third file is called auxframe.py

from tkinter import Label, Button, BOTH, BOTTOM
from makewindow import MakeWindow


class AuxFrame:
    def __init__(self):
        self.win = None

    def create(self, frame, counter=0):
        self.win = MakeWindow()  # call makewindow.py
        self.win.create(frame)  # destroy passed frame, create new frame for the root
        Label(self.win.topframe, text="Auxiliary Screen").pack()
        Label(self.win.topframe, text="Refresh Counter: {}".format(counter)).pack()
        counter += 1
        Button(self.win.topframe, text="Refresh",command=lambda:AuxFrame().create(self.win.topframe, counter=counter)).pack(fill=BOTH, side=BOTTOM)
        Button(self.win.topframe, text="Go back to mainframe",command=lambda: (self.win.topframe.quit(), self.win.topframe.destroy())).pack(fill=BOTH, side=BOTTOM)
        self.win.finish()

The last file is called makewindow.py

import vars
from tkinter import Frame


class MakeWindow:
    def __init__(self):
        self.topframe = Frame(vars.root)

    def create(self, frame):
        if frame is not None:
            frame.destroy()
        self.topframe.pack()  # pack topframe on the root

    def finish(self):
        vars.root.update()
        vars.root.mainloop()
英文:

This is a simplification of my project. The code should run when all files are put in the same folder and mainframe.py is run. I want to be able to return to the mainframe screen from the auxscreen after refreshing the auxscreen (the counter should be > 0). While returning to the mainframe is possible if the auxscreen is not refreshed, it will not return if auxscreen has been refreshed. I can't figure out what is going on or how to fix it.

I've been putting all the gui classes in the mainframe.py file, but it is getting overcrowded now and the automatic inspections in pycharm are taking a long time to complete. I want to start putting gui classes another module which run on the same tkinter root (vars.root in the example). The first problem I had was circular dependancies, so I needed a way to return to the main screen after the auxscreen finished. You can see in the command of the button going to the auxframe, I coded a boomerang that returns and rebuilds the mainframe once the auxscreen is quit and destoyed. The problem is that it stops working after the auxscreen has been recreated.

The first file is named vars.py

root = None

The second file is called mainframe.py

from tkinter import Tk, Label, Button, BOTH, BOTTOM
import vars
from makewindow import MakeWindow
from auxframe import AuxFrame


class MainFrame:
	def __init__(self):
		self.win = None

	def start_up(self, frame=None):
		self.win = MakeWindow()  # call makewindow.py
		self.win.create(frame)  # creates the frame for the root
		Label(self.win.topframe, text="Main Screen").pack()
		Button(self.win.topframe, text="Go to auxframe", command=lambda: (AuxFrame().create(self.win.topframe), MainFrame().start_up())).pack(fill=BOTH, side=BOTTOM)
		Button(self.win.topframe, text="Quit", command=lambda: vars.root.quit()).pack(fill=BOTH, side=BOTTOM)
		self.win.finish()


vars.root = Tk()
MainFrame().start_up()

The third file is called auxframe.py

from tkinter import Label, Button, BOTH, BOTTOM
from makewindow import MakeWindow


class AuxFrame:
	def __init__(self):
		self.win = None

	def create(self, frame, counter=0):
		self.win = MakeWindow()  # call makewindow.py
		self.win.create(frame)  # destroy passed frame, create new frame for the root
		Label(self.win.topframe, text="Auxiliary Screen").pack()
		Label(self.win.topframe, text="Refresh Counter: {}".format(counter)).pack()
		counter += 1
		Button(self.win.topframe, text="Refresh",command=lambda:AuxFrame().create(self.win.topframe, counter=counter)).pack(fill=BOTH, side=BOTTOM)
		Button(self.win.topframe, text="Go back to mainframe",command=lambda: (self.win.topframe.quit(), self.win.topframe.destroy())).pack(fill=BOTH, side=BOTTOM)
		self.win.finish()

The last file is called makewindow.py

import vars
from tkinter import Frame


class MakeWindow:
	def __init__(self):
		self.topframe = Frame(vars.root)

	def create(self, frame):
		if frame is not None:
			frame.destroy()
		self.topframe.pack()  # pack topframe on the root

	def finish(self):
		vars.root.update()
		vars.root.mainloop()

答案1

得分: 1

以下是您提供的代码的中文翻译:

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.mainframe = tk.Frame(self)
        self.mainframe.pack()
        tk.Label(self.mainframe, text="主屏幕").pack()
        tk.Button(self.mainframe, text="转到辅助屏幕", command=self.go_to_auxframe).pack(fill=tk.BOTH, side=tk.BOTTOM)
        tk.Button(self.mainframe, text="退出", command=self.quit).pack(fill=tk.BOTH, side=tk.BOTTOM)
        self.counter = 0

    def go_to_auxframe(self):
        self.mainframe.forget()
        self.AuxFrame = tk.Frame(self)
        self.AuxFrame.pack()
        tk.Label(self.AuxFrame, text="辅助屏幕").pack()
        tk.Label(self.AuxFrame, text="刷新计数器: {}".format(self.counter)).pack()
        tk.Button(self.AuxFrame, text="刷新", command=self.Refresh).pack(fill=tk.BOTH, side=tk.BOTTOM)
        tk.Button(self.AuxFrame, text="返回主屏幕", command=self.go_to_mainframe).pack(fill=tk.BOTH, side=tk.BOTTOM)

    def Refresh(self):
        self.counter += 1
        self.AuxFrame.destroy()
        self.go_to_auxframe()

    def go_to_mainframe(self):
        self.AuxFrame.forget()
        self.mainframe.pack()

if __name__ == "__main__":
    app = App()
    app.mainloop()

或者修改您的auxframe.py如下:

from tkinter import Label, Button, BOTH, BOTTOM
from makewindow import MakeWindow

class AuxFrame:
    def __init__(self):
        self.win = None

    def create(self, frame):
        self.counter = 0
        self.win = MakeWindow()  # 调用makewindow.py
        self.win.create(frame)  # 销毁传递的frame,为root创建新的frame
        Label(self.win.topframe, text="辅助屏幕").pack()
        self.counter_label = Label(self.win.topframe, text="刷新计数器: {}".format(self.counter))
        self.counter_label.pack()
        Button(self.win.topframe, text="刷新", command=self.counter_up).pack(fill=BOTH, side=BOTTOM)
        Button(self.win.topframe, text="返回主屏幕", command=lambda: (self.win.topframe.quit(), self.win.topframe.destroy())).pack(fill=BOTH, side=BOTTOM)
        self.win.finish()

    def counter_up(self):
        self.counter += 1
        self.counter_label['text'] = f"刷新计数器: {self.counter}"
英文:

How about something like this?

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.mainframe = tk.Frame(self)
        self.mainframe.pack()
        tk.Label(self.mainframe, text="Main Screen").pack()
        tk.Button(self.mainframe, text="Go to auxframe", command=self.go_to_auxframe).pack(fill=tk.BOTH, side=tk.BOTTOM)
        tk.Button(self.mainframe, text="Quit", command=self.quit).pack(fill=tk.BOTH, side=tk.BOTTOM)
        self.counter=0

    def go_to_auxframe(self):
        self.mainframe.forget()
        self.AuxFrame = tk.Frame(self)
        self.AuxFrame.pack()
        tk.Label(self.AuxFrame, text="Auxiliary Screen").pack()
        tk.Label(self.AuxFrame, text="Refresh Counter: {}".format(self.counter)).pack()
        tk.Button(self.AuxFrame, text="Refresh", command=self.Refresh).pack(fill=tk.BOTH, side=tk.BOTTOM)
        tk.Button(self.AuxFrame, text="Go back to mainframe", command=self.go_to_mainframe).pack(fill=tk.BOTH, side=tk.BOTTOM)

    def Refresh(self):
        self.counter += 1
        self.AuxFrame.destroy()
        self.go_to_auxframe()

    def go_to_mainframe(self):
        self.AuxFrame.forget()
        self.mainframe.pack()

if __name__ == "__main__":
    app=App()
    app.mainloop()

Or modify your auxframe.py like this.

from tkinter import Label, Button, BOTH, BOTTOM
from makewindow import MakeWindow


class AuxFrame:
    def __init__(self):
        self.win = None

    def create(self, frame):
        self.counter = 0
        self.win = MakeWindow()  # call makewindow.py
        self.win.create(frame)  # destroy passed frame, create new frame for the root
        Label(self.win.topframe, text="Auxiliary Screen").pack()
        self.counter_label=Label(self.win.topframe, text="Refresh Counter: {}".format(self.counter))
        self.counter_label.pack()
        Button(self.win.topframe, text="Refresh",command=self.counter_up).pack(fill=BOTH, side=BOTTOM)
        Button(self.win.topframe, text="Go back to mainframe",command=lambda: (self.win.topframe.quit(), self.win.topframe.destroy())).pack(fill=BOTH, side=BOTTOM)
        self.win.finish()

    def counter_up(self):
        self.counter += 1
        self.counter_label['text']=f"Refresh Counter: {self.counter}"

huangapple
  • 本文由 发表于 2023年7月18日 14:40:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76710114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定