Как обновить / обновить sh виджеты при переключении фреймов в tkinter? - PullRequest
1 голос
/ 20 июня 2020

У меня есть приложение gui, в котором на панели навигации есть кнопки для переключения между кадрами. На стартовой странице есть виджет ввода для получения имени файла и список для отображения всех сохраненных имен файлов. Когда имя файла выбирается из списка, открывается другая страница, на которой отображается выбранное имя файла. здесь создает объекты фрейма в начале, складывает их и поднимает в зависимости от того, какой фрейм вызывается. Но я думаю, что мое окно должно обновляться каждый раз, когда оно вызывается, чтобы отображать другое имя файла. Кроме того, он находится в том же месте, что и другие фреймы, так что я все еще могу использовать кнопки панели навигации для переключения на другой дом и другие windows. Я нашел что-то похожее на этот здесь , но я не могу этого понять.

(мое фактическое приложение немного сложнее, чем это, но я думаю, что это небольшое и точное представление моей проблемы )

Редактировать :

import tkinter as tk

class MainApplication(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(1, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames={}
        for F in (StartPage,PageOne):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=1, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        self.list_box = tk.Listbox(self)
        self.list_box.pack()
        for item in ["file 1", "file 2", "file 3"]:
            self.list_box.insert(tk.END, item)
        button1 = tk.Button(self, text='Go to next Page', command=lambda: self.getvalue(controller))
        button1.pack()

    def getvalue(self, controller):
        clicked_item=self.list_box.curselection()
        selected_file=self.list_box.get(clicked_item)
        print(selected_file)
        controller.show_frame('PageOne')

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        # ....selected file name to be displayed here....
        button1 = tk.Button(self, text="Back to Home", command=lambda: controller.show_frame('StartPage'))
        button1.pack()


app = MainApplication()
app.geometry("400x400")
app.mainloop()

Ответы [ 2 ]

2 голосов
/ 22 июня 2020

Вопрос : как передавать имя selected_file каждый раз, когда я хочу go на PageOne из StartPage.

Основная точка :

Перегрузите метод класса Frame.tkraise, чтобы обновлять виджеты PageOne при каждом вызове .tkraise из controller

Примечание: я показываю только измененные части вашего примера кода, внимательно сравниваю и копирую ваш реальный код.

  1. Без изменений class MainApplication(tk.Tk):

    class MainApplication(tk.Tk):
       ...
    
  2. class StartPage(tk.Frame):

    class StartPage(tk.Frame):
        def __init__(self, parent, controller):
            ...
            .Button(..., command=lambda: controller.show_frame('PageOne'))
    
        def getvalue(self):
            ...
            return selected_file
    
    
  3. class PageOne(tk.Frame):

    class StartPage(tk.Frame):
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            self.controller = controller
            # ....selected file name to be displayed here....
            self.label = tk.Label(self, text='')
            self.label.pack()
    
        def tkraise(self, aboveThis=None):
            # Get a reference to StartPage
            start_page = self.controller.frames['StartPage']
    
            # Get the selected item from start_page
            self.label.configure(text=start_page.getvalue())
    
            # Call the real .tkraise
            super().tkraise(aboveThis)
    
    

Альтернативы :

1 голос
/ 21 июня 2020

#Multiple Screens

from tkinter import *

class screen(Frame):
    """
    A screen is area
    for content in a program
    """
    def __init__(self,master,name):
        Frame.__init__(self,master)
        #Attributes
        self.master=master
        self.name=name
        #Initalise with master
        self.master.addScreen(self)
    def show(self):
        """
        Method will show screen
        """
        self.master.showScreen(self.name)

class screenController(Frame):
    """
    Screen Controller
    will manage screens 
    in the program
    """
    def __init__(self,parent):
        Frame.__init__(self,parent)
        #Configure
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        #Attributes
        self.allScreens={}
        self.currentScreen=None

    def addScreen(self,screenObject):
        """
        Adds a Screen object to the screenController
        """
        #Place the screen
        screenObject.grid(row=0, column=0, sticky="nsew")
        #Add to dictionary
        self.allScreens[screenObject.name]=screenObject

    def showScreen(self,screenName):
        if screenName in self.allScreens:
            #Display
            self.allScreens[screenName].tkraise()
            #Update variable
            self.currentScreen=screenName
            
    
#Create a Tkinter Window
window=Tk()
window.title("Multiple Screens")
window.geometry("400x300")
window.columnconfigure(0,weight=1)
window.rowconfigure(1,weight=1)


#Create a Controller for the screens
screenMaster=screenController(window)
screenMaster.grid(row=1,column=0,sticky="NSEW")

#Create SCREEN 1
screen1=screen(screenMaster, "S1")
Label(screen1,text="This is screen 1").grid(row=0,column=0) 
screen1.config(bg="red")

#Create SCREEN 2
screen2=screen(screenMaster, "S2")
Label(screen2,text="This is screen 2").grid(row=0,column=0) 
screen2.config(bg="blue")

#Create SCREEN 3
screen3=screen(screenMaster, "S3")
Label(screen3,text="This is screen 3").grid(row=0,column=0) 
screen3.config(bg="green")

#Create a navigation bar
navBar=Frame(window)
navBar.grid(row=0,column=0,sticky="EW")
navBar.config(bg="#F1F0F2")

b1=Button(navBar,text="Screen 1",command=lambda: screen1.show())
b1.grid(row=0,column=0)

b1=Button(navBar,text="Screen 2",command=lambda: screen2.show())
b1.grid(row=0,column=1)

b1=Button(navBar,text="Screen 3",command=lambda: screen3.show())
b1.grid(row=0,column=2)


#Show screen 1 by default
screen1.show()

window.mainloop()

Это способ, которым я бы использовал объектно-ориентированное программирование для решения этой проблемы, панель навигации оставалась бы c независимо от того, на каком «экране» вы были, и просто поднимая экраны друг над другом, вы этого не делаете. необходимо продолжать создавать новые объекты и экономить много памяти.

Это решение также очень модульное и просто позволяет добавлять экраны, как если бы они были кадрами Tkinter.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...