Python Tkinter, modify Text from outside the class

2019-07-24 18:18发布

问题:

I am trying to access the Text widget defined in class FirstPage from outside of the class. I tried to solve this problem by creating a new instance of FirstPage, but could not find the right arguments to use. Also tried to use instance of GUI to gain the access, but unsuccessfully.

My problem is solved when I can use text.insert(0.0, t) from outside of the classes. It would help me modify the text displayed with Tkinter by functions that are not directly related with the GUI.

The origin of the code I am trying to use is found: Switch between two frames in tkinter

Also I removed lines that were not necessary for this question..

import Tkinter as tk

class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.geometry(self, '580x410')
        container = tk.Frame(self)

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

        self.frames = {}

        frame = FirstPage(container, self)
        self.frames[FirstPage] = frame
        frame.grid(row=0, column=0, sticky="nsew")

        frame = self.frames[FirstPage]
        frame.tkraise()


class FirstPage(tk.Frame):

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

        text = tk.Text(self , height=25, width=80)
        text.grid(column=0, row=0, sticky="nw")



app = GUI()
app.mainloop()

EDIT: Here is the working code:

import Tkinter as tk

class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.geometry(self, '580x410')
        container = tk.Frame(self)

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

        self.frames = {}

        frame = FirstPage(container, self)
        self.frames[FirstPage] = frame
        frame.grid(row=0, column=0, sticky="nsew")

        frame = self.frames[FirstPage]
        frame.tkraise()

        page_name = FirstPage.__name__
        self.frames[page_name] = frame


    def get_page(self, page_name):
        return self.frames[page_name]


class FirstPage(tk.Frame):

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

        self.text = tk.Text(self , height=25, width=80)
        self.text.grid(column=0, row=0, sticky="nw")



app = GUI()
app.get_page("FirstPage").text.insert("1.0", "Hello, world")
app.mainloop()

回答1:

There's nothing special you need to do. As with any python object, you simply need a reference to the object in order to manipulate it.

The concept in the code you started with is to have a "controller" that controls access to all of the pages, since that object is where the pages are created. You can add a function in the controller that gives you a reference to a page, and then you can use that to call a function on that page.

Here's the changes you need to make to the controller:

class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):
        ...
        page_name = FirstPage.__name__
        self.frames[page_name] = frame
        ...

    def get_page(self, page_name):
        return self.frames[page_name]

You also need to modify FirstPage to keep a reference to the widget so that you can access it later:

class FirstPage(tk.Frame):
    def __init__(self, parent, controller):
        ...
        self.text = tk.Text(...)
        ...

From within any other code you can now access the text widget via get_page (but your pages must save a reference to the controller for this to work).

class AnotherPage(tk.Frame):

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

    def some_function(self):
        ...
        first_page = self.controller.get_page("FirstPage")
        text = first_page.text.get("1.0", "end-1c")
        ...
        first_page.text.insert("end", "some new text\n")

Note that this technique works outside of any GUI pages. In your code, app is the controller, so you can do something like this:

app = GUI()
app.get_page("FirstPage").text.insert("1.0", "Hello, world")