Home tkinter gui which loads a flie and can print out the file name
Reply: 1

tkinter gui which loads a flie and can print out the file name

Matthias K
1#
Matthias K Published in 2017-12-06 21:54:42Z

I am starting with python and I already created a nice plotting function with matplotlib. Now I want to insert the function into a GUI using tkinter. As I learned from youtube and this forum I should use classes. Unfortunately I have some problems with that. What I have so far (where I do not understand everything in detail) is:

import tkinter as tk
from tkinter import filedialog

LARGE_FONT=('Verdana',12)


class XPSPlotApp(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(0,weight=1)#0 is min size
        container.grid_columnconfigure(0,weight=1)


        #adding a menubar#
        self.menuBar = tk.Menu(master=self)
        self.filemenu = tk.Menu(self.menuBar, tearoff=0)
        self.filemenu.add_command(label="Open", command=self.browse_file)
        self.filemenu.add_command(label="Quit!", command=self.quit)
        self.menuBar.add_cascade(label="File", menu=self.filemenu)
        self.config(menu=self.menuBar)

        self.frames={}

        for F in (HRXPSPlotter, SurveyXPSPlotter):

            frame=F(container,self)

            self.frames[F]=frame

            frame.grid(row=0,column=1,sticky='nsew')

        self.show_frame(HRXPSPlotter)

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

    #Question if it should be here because maybe overwrites the filename   form other window?
    def browse_file(self):
        self.filename =  filedialog.askopenfilename(initialdir = "E:/Images",title = "choose your file",filetypes = (("txt files","*.txt"),("all files","*.*")))
        print(self.filename)
    def printFN(self):
        print(self.filename)


class HRXPSPlotter(tk.Frame):

    def __init__(self,parent, controller):
        tk.Frame.__init__(self,parent)
        lable=tk.Label(self,text='Sart Page',font=LARGE_FONT)
        lable.pack(pady=10,padx=10)
        #button to go to another page
        button1=tk.Button(self, text='Visit Page 1',command=lambda:controller.show_frame(SurveyXPSPlotter))
        button1.pack()

class SurveyXPSPlotter(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        lable=tk.Label(self,text='Page One',font=LARGE_FONT)
        lable.pack(pady=10,padx=10)
        button1=tk.Button(self, text='Back to Page 1',command=lambda:controller.show_frame(HRXPSPlotter))
        button1.pack()

app=XPSPlotApp()
app.mainloop()

The program has two pages (because I want to use different plotter) and a menu which can open a file from a directory.

  1. Now I want to implement a function which plots the filename+filepath when I click a button, but I do not get it work? The problem is simply that I do not really know where I have to define the function — in the __init__ or in the subclasses? and also...
  2. How the command=lambda:controller works, it is still magic for me!
  3. Why are the subclasses (e.g. pageOne) methods of tk.Frame and not tk.Tk like the __init__?
martineau
2#
martineau Reply to 2017-12-07 18:09:49Z

I'm not going to address all your three sub-questions directly because it would wind-up being a whole mini-tutorial on tkinter. However I can show you how to add a Button to do the plotting. Note especially the lines with the comment # ADDED on them.

Below a modified version of your code with a number of things added showing where and how to put a plotting function function could be put in. I've also changed the coding style so it follows the PEP 8 - Style Guide for Python Code more closely and is much more readable.

In a several spots I also changed the name of variables to make it clearer how this kind of gui architecture based on tkinter operates.

import tkinter as tk
from tkinter import filedialog
LARGE_FONT=('Verdana', 12)


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

        container = tk.Frame(self)
        container.pack(side='top', fill='both', expand=True)
        container.grid_rowconfigure(0, weight=1)  # 0 is min size
        container.grid_columnconfigure(0, weight=1)

        # Add menubar and subcommands.
        self.menuBar = tk.Menu(master=self)
        self.filemenu = tk.Menu(self.menuBar, tearoff=0)
        self.filemenu.add_command(label="Open", command=self.browse_file)
        self.filemenu.add_command(label="Plot", command=self.plot_file)  # ADDED
        self.filemenu.add_command(label="Quit!", command=self.quit)
        self.menuBar.add_cascade(label="File", menu=self.filemenu)
        self.config(menu=self.menuBar)

        self.frames={}

        for FrameSubclass in (HRXPSPlotter, SurveyXPSPlotter):
            frame = FrameSubclass(container, self)  # create class instance.
            self.frames[FrameSubclass] = frame
            frame.grid(row=0, column=1, sticky='nsew')

        self.show_frame(HRXPSPlotter)

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

    def browse_file(self):
        self.filename = filedialog.askopenfilename(
            initialdir="E:/Images", title="Choose your file",
            filetypes=(("text files", "*.txt"), ("all files", "*.*"))
        )
        print(self.filename)

    def plot_file(self):  # ADDED
        try:
            print('Plotting:', self.filename)
        except AttributeError:
            print('No filename has been selected to plot!')


class HRXPSPlotter(tk.Frame):
    def __init__(self, parent, controller):
        super().__init__(parent)
        label = tk.Label(self, text='Start Page', font=LARGE_FONT)
        label.pack(pady=10, padx=10)
        # Button to go to another page.
        button1 = tk.Button(self, text='Visit Page 1',
                        command=lambda: controller.show_frame(SurveyXPSPlotter))
        button1.pack()


class SurveyXPSPlotter(tk.Frame):
    def __init__(self, parent, controller):
        super().__init__(parent)
        label = tk.Label(self, text='Page One', font=LARGE_FONT)
        label.pack(pady=10, padx=10)
        # Button to go to another page.
        button1 = tk.Button(self, text='Back to Page 1',
                        command=lambda: controller.show_frame(HRXPSPlotter))
        button1.pack()


app=XPSPlotApp()
app.mainloop()

The command=lambda: controller.show_frame(<tk.Frame subclass>) arguments used to construct the tk.Buttons creates an anonymous function which calls controller.show_frame(<tk.Frame subclass>) when the corresponding button is pressed (as opposed to it happening as the Button itself is created).

The show_frame() function looks up the Frame subclass instance in the self.frames dictionary that was created in the XPSPlotApp class __init__() method and "raises" it so it becomes as the top-most frame displayed (which effectively hides all the rest of them which are the same size and at the same position but now "below" it).

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.296655 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO