首页 > 解决方案 > 更新函数内的全局 python 变量

问题描述

我在这样的类的方法中有一个函数:

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() 

当我运行代码时,函数内部的 self.path 变量会发生变化。但是函数外的 self.path 全局变量并没有改变。

我希望 self.path 在函数之外进行更新。事实上,我想用 onOpen1 函数更新 self.path 变量。此功能打开一个窗口,允许您选择图像。然后,我想恢复这个图像的路径来更新 self.path。

标签: pythonpython-3.xfunctiontkinterglobal-variables

解决方案


该按钮只是帮助可视化正在发生的事情的一种方式。这是完整的代码。

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() 

运行它并观察你的控制台打印将在哪里发生。按下按钮。注意 self.path 是 None 的。

现在使用您的文件对话框选择一个图像。

再次按下按钮。注意 self.path 是如何改变以反映图像的路径是什么?

您声明要更新 self.path 以反映您选择的内容。您的代码实际上确实做到了这一点。这种可视化的目的是向您展示您提出的问题可能不是您遇到的问题的解决方案。

这是我认为你想要的一个例子。

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() 

这是 2 帧的一些示例代码。

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()

推荐阅读