-1

I have a function inside a method of a class like this:

from tkinter import Frame, Tk, BOTH, Text, Menu, END
from tkinter import filedialog as tkFileDialog 

class Example(Frame):

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

        self.parent = parent        
        self.initUI()
        self.path = None
        print(self.path)
    def initUI(self):

        self.parent.title("File dialog")
        self.pack(fill=BOTH, expand=1)

        menubar = Menu(self.parent)
        self.parent.config(menu=menubar)

        fileMenu = Menu(menubar)
        fileMenu.add_command(label="Open_image", command=self.onOpen1)
        menubar.add_cascade(label="File", menu=fileMenu)        

    def onOpen1(self):

        ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
        dlg = tkFileDialog.Open(self, filetypes = ftypes)
        path = dlg.show()

        if path != '':
            self.path = path
            print(self.path)
            return self.path


def main():

    root = Tk()
    ex = Example(root)
    root.geometry("300x250+300+300")
    root.mainloop()  


if __name__ == '__main__':
    main() 

When I run the code, the self.path variable inside the function changes. But the self.path global variable outside the function does not change.

I would like self.path to be updated outside of the function. In fact, I want to update the self.path variable with the onOpen1 function. This function opens a window which allows you to select an image. Then, I want to recover the path of this image to update self.path.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • In fact, I want to update the self.path variable with the onOpen1 function. This function opens a window which allows you to select an image. Then, I want to recover the path of this image to update self.path. –  Jan 03 '20 at 14:50
  • You are already doing that. @Jena If you want proof of that add a button to your window, and map it to print self.path. Add `Button` to your imports. then add these 2 lines to your initUI method. `button = Button(self.parent, text='test', command=self.test)` `button.pack()` Add a test method that only prints self.path. – Axe319 Jan 03 '20 at 14:51
  • I added this to the code if self.path! = None: print ( 'OK'). But it does not work. –  Jan 03 '20 at 14:56
  • Where did you add the code to? – Axe319 Jan 03 '20 at 14:57
  • I added it to UI, but it doesn't work. I don't understand what the button is supposed to do. –  Jan 03 '20 at 18:22
  • Your code is working exactly as it should - `self.path` _is_ getting updated. Why do you think it's not? – Bryan Oakley Jan 03 '20 at 19:57

1 Answers1

0

The button is just a way to help visualize what is happening. Here is the full code.

from tkinter import Frame, Tk, BOTH, Text, Menu, END, Button
from tkinter import filedialog as tkFileDialog 

class Example(Frame):

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

        self.parent = parent        
        self.initUI()
        self.path = None
        print(self.path)

    def initUI(self):
        self.parent.title("File dialog")
        self.pack(fill=BOTH, expand=1)

        menubar = Menu(self.parent)
        self.parent.config(menu=menubar)

        fileMenu = Menu(menubar)
        fileMenu.add_command(label="Open_image", command=self.onOpen1)
        menubar.add_cascade(label="File", menu=fileMenu) 

        button = Button(self.parent, text='test', command=self.test)  
        button.pack()     

    def test(self):
        print(self.path)

    def onOpen1(self):

        ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
        dlg = tkFileDialog.Open(self, filetypes = ftypes)
        path = dlg.show()

        if path != '':
            self.path = path
            print(self.path)
            return self.path


def main():

    root = Tk()
    ex = Example(root)
    root.geometry("300x250+300+300")
    root.mainloop()  


if __name__ == '__main__':
    main() 

Run it and watch your console where the print will happen. Hit the button. Notice how self.path is None.

Now select an image with your file dialog box.

Hit the button again. Notice how self.path changed to reflect what the path to the image is?

You stated that you want to update self.path to reflect what you selected. Your code does in fact do that. The point of this visualization is to show you that the question you asked may not be the solution to the problem you're having.

Here is an example of what I think you want.

from tkinter import Frame, Tk, BOTH, Text, Menu, END, Button, Label
from tkinter import filedialog as tkFileDialog
import cv2
from PIL import ImageTk, Image

class Example(Frame):

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

        self.parent = parent        
        self.initUI()
        self.path = None
        print(self.path)

    def initUI(self):
        self.parent.title("File dialog")
        self.pack(fill=BOTH, expand=1)

        menubar = Menu(self.parent)
        self.parent.config(menu=menubar)

        fileMenu = Menu(menubar)
        fileMenu.add_command(label="Open_image", command=self.onOpen1)
        menubar.add_cascade(label="File", menu=fileMenu) 

    def test(self):
        print(self.path)

    def onOpen1(self):

        ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
        dlg = tkFileDialog.Open(self, filetypes = ftypes)
        path = dlg.show()

        if path != '':
            self.path = path
            self.add_image()

    def add_image(self):
        img = cv2.imread(self.path)
        img = cv2.resize(img,(224, 224), interpolation = cv2.INTER_AREA)
        image1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        image1 = Image.fromarray(image1)
        image1 = ImageTk.PhotoImage(image1)
        panelA = Label(self, image=image1)
        panelA.image = image1
        panelA.grid(row=0, column=0, sticky='w')

def main():

    root = Tk()
    ex = Example(root)
    root.geometry("300x250+300+300")
    root.mainloop()  


if __name__ == '__main__':
    main() 

Here's some sample code for 2 frames.

from tkinter import Frame, Tk, BOTH, Text, Menu, END, Button, Label
from tkinter import filedialog as tkFileDialog
import cv2
from PIL import ImageTk, Image

class Example(Frame):

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

        self.parent = parent
        self.initUI()
        self.current_window = 0
        self.path = None
        self.panelA = None
        self.panelB = None
        print(self.path)

    def initUI(self):
        self.parent.title("File dialog")
        #self.pack(fill=BOTH, expand=1)

        menubar = Menu(self.parent)
        self.parent.config(menu=menubar)

        fileMenu = Menu(menubar)
        fileMenu.add_command(label="Open Image 1", command=lambda: self.onOpen1(1))
        fileMenu.add_command(label="Open Image 2", command=lambda: self.onOpen1(2))
        menubar.add_cascade(label="File", menu=fileMenu)

        self.button_1 = Button(self.parent, text='Window 1', command=lambda: self.switch_window(1))
        self.button_2 = Button(self.parent, text='Window 2', command=lambda: self.switch_window(2))
        self.back_button = Button(self.parent, text='Back', command=lambda: self.switch_window(0))

        self.button_1.grid(sticky='w')
        self.button_2.grid(sticky='w')

    def switch_window(self, window):
        self.current_window = window
        if window == 0:
            self.back_button.grid_forget()
            self.button_1.grid(sticky='w')
            self.button_2.grid(sticky='w')
        else:
            self.button_1.grid_forget()
            self.button_2.grid_forget()
            self.back_button.grid(row=1, sticky='w')

        self.repopulate_windows()

    def onOpen1(self, image_selection):
        ftypes = [('jpg files','.jpg'),('png files','.png'),('all files','.*')]
        dlg = tkFileDialog.Open(self, filetypes = ftypes)
        path = dlg.show()

        if path != '':
            self.path = path
            self.add_image(image_selection)

    def add_image(self, image_selection):
        img = cv2.imread(self.path)
        img = cv2.resize(img,(224, 224), interpolation = cv2.INTER_AREA)
        image1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        image1 = Image.fromarray(image1)
        image1 = ImageTk.PhotoImage(image1)

        if image_selection == 1:
            self.panelA = Label(self.parent, image=image1)
            self.panelA.image = image1
        else:
            self.panelB = Label(self.parent, image=image1)
            self.panelB.image = image1

        if self.current_window != 0:
            self.repopulate_windows()

    def repopulate_windows(self):
        if self.current_window == 1:
            if self.panelB is not None:
                self.panelB.grid_forget()
            if self.panelA is not None:
                self.panelA.grid(row=0, column=0, sticky='w')
        elif self.current_window == 2:
            if self.panelA is not None:
                self.panelA.grid_forget()
            if self.panelB is not None:
                self.panelB.grid(row=0, column=0, sticky='w')
        else:
            if self.panelA is not None:
                self.panelA.grid_forget()
            if self.panelB is not None:
                self.panelB.grid_forget()

def main():

    root = Tk()
    ex = Example(root)
    root.geometry("300x250+300+300")
    root.mainloop()


if __name__ == '__main__':
    main()
Axe319
  • 4,255
  • 3
  • 15
  • 31
  • Yes, it seems to work. But what I want to do is in the second answer. But the problem in this answer is that the window opens automatically at launch. And when we change the image, the path does not change. –  Jan 03 '20 at 18:51
  • @Jena I edited my answer with the behavior that I think you're looking for. – Axe319 Jan 03 '20 at 19:44
  • I have one last question for you. If you can do that, you're going to make my job easier. –  Jan 03 '20 at 20:59
  • When you have two frames like here https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter/7557028#7557028, and you want to use the menu path to display the same image in the two frames, do you have a sample code? –  Jan 03 '20 at 21:00
  • @Jena I added another sample. – Axe319 Jan 04 '20 at 02:45
  • In fact, what I want is to keep the class structure class StartPage(tk.Frame): and add the images. Is that possible ? –  Jan 04 '20 at 10:01
  • Hi @Axe319 Have you had time to watch? I still haven't succeeded –  Mar 16 '20 at 13:46