-1

I am quite new for python and Tkinter, please bear the messy code.

currently I have 2 buttons (one is open file, second one is run), and 1 text box (Entry or Scrolledtext), what I want to do is

  1. press the open file button, then the file path will be displayed in the text box and this path will be also saved into local variable 'a' in main().
  2. when I press the 'run' button, the program will get latest value of variable 'a' and do something else.

The problem I faced is that this local variable 'a' cannot updated while I click 'open file' button. I search this kind of questions and I get answer that either I should use 'global var' or 'make a class and treat the file path as a attribute'. But somehow I couldn't make it. Let me put my code below.

First is use global variable. I could get updated file1 by clicking 'btn_run', console will print latest value of file one, but script_path cannot updated.

p.s. I also try the 'trace()' method. yes, I found that the var. in the function could be updated but how do I get those updated var into my local variable main? it seems go back to original point again.


from functools import partial

from tkinter import scrolledtext,INSERT,END,Entry, messagebox, filedialog, ttk, Frame,Button

from os import path

import matplotlib.pyplot as plt

from matplotlib.figure import Figure

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2TkAgg

# Tkagg allows you to draw, navigation bar is to allow you save, zoomm ....the images 
import numpy as np

from tkinter import *

def openfile(txt1):
    global file1
    file1= filedialog.askopenfilename(filetypes=(("all files","*.*"),("Text files","*.txt"),("csv file","*.csv")))
    txt1.insert(0,file1)
#    print (file1)

def print_f1():
    print(file1)

def main ():

    # Create Main window 
    window = Tk()
    file1=''
    window.title("WADC FFT trial")

    window.minsize(1000,600)
    input_str=StringVar()
    input_str.set('')
    # Create Frame for buttons, bars and picts 

    mis_frame = Frame(window)
    mis_frame.grid(column=0, row=0)

    #Create a scrolled text box on mis_frame 
    txt=Entry(mis_frame,textvariable=input_str,width=40)
    txt.grid(column=0,row=0)
    #define openfile

    #Create a button on mis_frame, use lambda to avoid direct invoke the function called     
#    btn_path= Button(mis_frame,text="Open File",command=lambda:openfile(txt1))
    #another workaround is to use partial funciton in python, assign a new func with lesser variables. 
    op_func=partial(openfile,txt)
    btn_path=Button(mis_frame,text='Open File',command=op_func)
    btn_path.grid(column =1,row =0)
    script_path=input_str
    print('script path is '+str(script_path))
    btn_run = Button(mis_frame, text='Run',command=print_f1)

    btn_run.grid(column=3,row=0,padx=100)

    window.mainloop()

if __name__=='__main__':
    main()

Second come with the class attribute. this one I only make 1 button which can openfile and get file path. The point is I want to pass this 'filename' to local variable 'a', the thing is like one I run the code, it will pass 'a' the default value 'filename' and not update after I click the 'browse' button.

Thanks for suggestions you provided, it could be helpful


from tkinter import *

import tkinter as tk

class Canvas(tk.Tk): #inherient from Tkinter.tk
    def __init__(self):
        tk.Tk.__init__(self) #inheritate all attributes that tk has 
        self.filename ='' #declare filepath   
        tk.Button(self, text='Browse', command=self.openfile).grid(column=0,row=0)
    def openfile(self):
        self.filename = filedialog.askopenfilename(title="Open file")

def main ():
    b=Canvas()
    b.title("Test")
    b.minsize(600,400)
    a=b.filename
    print(a)
    b.mainloop()
if __name__=='__main__':
    main()
Dummy1
  • 3
  • 4
  • In your example code,they didn't import the another module. – jizhihaoSAMA Apr 23 '20 at 03:40
  • sorry I am not quite clear what you are saying. Which module I need to import? could you elaborate further on this? Thanks – Dummy1 Apr 23 '20 at 04:46
  • You post two examples.Are they in the same `.py` file? – jizhihaoSAMA Apr 23 '20 at 05:27
  • First you have to understand [Event-driven_programming](https://en.m.wikipedia.org/wiki/Event-driven_programming). Read through [`[tkinter] event driven programming`](https://stackoverflow.com/search?q=is%3Aanswer+%5Btkinter%5D+event+driven+programming+entry) and [Why are multiple instances of Tk discouraged?](https://stackoverflow.com/a/48045508/7414759) – stovfl Apr 23 '20 at 16:30

1 Answers1

0

Problems

script_path=input_str 

assigns the StringVar to script_path, not the value of it. To get the value use script_path = input_str.get()


When this line

a = b.filename

is executed, it assigns the default value of filename to a because you didn't call openfile.


Solution

To pass a value to the global scope you need neither classes nor global keywords. Just use a tkinter variable

file1 = StringVar()
def openfile(txt1):
    file1.set(filedialog.askopenfilename(filetypes=( ("all files","*.*"),("Text files","*.txt"),("csv file","*.csv") ) ) )
    txt1.insert(0,file1) 

or make your functions return something.

def openfile(txt1):
    file1 = filedialog.askopenfilename(filetypes=( ("all files","*.*"),("Text files","*.txt"),("csv file","*.csv") ))
    txt1.insert(0,file1) 
    return file1
Banana
  • 2,295
  • 1
  • 8
  • 25