Как использовать второе окно Tkinter для изменения изображения в первом? - PullRequest
2 голосов
/ 03 августа 2020

Краткое описание: Зеленая кнопка должна изменяться при выборе изображения, но этого не происходит:

введите описание изображения здесь

У меня есть Tkinter window-A с кнопкой, которая при нажатии будет использовать отдельный файл Python для создания нового window-B. Window-B имеет две кнопки: новый снимок экрана или выбор изображения из папки. Метод, используемый для этого, должен затем изменить self.image_selected, чтобы его можно было использовать для обновления кнопки в window-A, чтобы получить это новое изображение.

Я пробовал обе строки кода ниже, и ни один не работает. У меня тоже нет ошибок:

        self.button.configure(image = img.image_selected) # first try
        self.button['image'] = img.image_selected         # second try

Вот мой код (упрощенный для ясности):

import tkinter as tk
import get_image_or_snip

class ButtonImg:
    def __init__(self, master):
        self.newWindow = None
        self.master = master
        self.title = "My Minimum Reproducible Example"
        self.fontA = ("arial", 20, "bold")
        self.canvas = tk.Canvas(height = 5)
        self.canvas.pack()
        self.button = tk.Button(bg="#93d9cc", height = 5, text = "Select Image",
                                font = self.fontA, command = self.changeImage)
        self.button.pack(fill="both")

    def changeImage(self):
        self.newWindow = tk.Toplevel(self.master)
        img = get_image_or_snip.AcquireImage(self.newWindow)
        self.button.configure(image = img.image_selected)
        #self.button['image'] = img.image_selected

root = tk.Tk()
app = ButtonImg(root)
root.mainloop()

Вот вышеупомянутый get_image_or_snip.py код:

import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk, Image
import snipping_tool


class AcquireImage:
    def __init__(self, master):
        self.master = master
        self.fontA = ("arial", 20, "bold")
        self.frame = tk.Frame(master, bg="#1B2631")
        self.frame.pack(fill="both", expand=True)
        self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
                              font = self.fontA, command =lambda: self.show_dialogs(1))
        self.button1.grid(row=0, column=0, sticky="nsew")
        self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
                              font = self.fontA, command=lambda: self.show_dialogs(2))
        self.button2.grid(row=0, column=1, sticky="nsew")
        self.image_selected = None
        self.master.mainloop()

    def show_dialogs(self, method):
        if method == 1:
            ret = filedialog.askopenfilename()
            load_img = Image.open(ret)
            self.image_selected = ImageTk.PhotoImage(load_img)

        if method == 2:
            ret = snipping_tool.get_snip()
            self.image_selected = ret


def main():
    root = tk.Tk()
    AcquireImage(root)
    root.mainloop()


if __name__ == '__main__':
    main()


1 Ответ

2 голосов
/ 04 августа 2020

Если вы добавите print() до и после get_image_or_snip.AcquireImage(self.newWindow) в changeImage(), вы должны увидеть только первый текст, потому что вы запускаете второй mainloop(), и он никогда не заканчивает этот l oop и никогда go не возвращается к changeImage() и никогда не запускается self.button.configure(image=img.image_selected)

Вы должны использовать только один mainloop() и в конечном итоге использовать

root.wait_window(self.newWindow)

, чтобы дождаться, пока вы закроете второе окно, а затем оно запустится self.button.configure(image=img.image_selected)

Но есть и другие проблемы.

Он удаляет изображение из памяти, когда второй windows уничтожается, поэтому вам нужно назначить его переменной в первом окне.

Использование кнопки высота в символах, когда вы отправляете текст, но когда вы назначаете изображение, оно использует высоту в пикселях, и вам нужно изменить ее с 5 на image.height () `

Весь код в одном файле

import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk


class AcquireImage:
    
    def __init__(self, master):
        self.master = master
        self.fontA = ("arial", 20, "bold")
        
        self.frame = tk.Frame(master, bg="#1B2631")
        self.frame.pack(fill="both", expand=True)
        
        self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
                              font=self.fontA, command=lambda:self.show_dialogs(1))
        self.button1.grid(row=0, column=0, sticky="nsew")
        
        self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
                              font=self.fontA, command=lambda:self.show_dialogs(2))
        self.button2.grid(row=0, column=1, sticky="nsew")
        
        self.image_selected = None

    def show_dialogs(self, method):
        
        if method == 1:
            ret = filedialog.askopenfilename(initialdir='/home/user/images/')
            if ret:
                self.image_selected = ImageTk.PhotoImage(file=ret)
                self.master.destroy()
     
        elif method == 2:
            self.image_selected = snipping_tool.get_snip()


class ButtonImg:
    
    def __init__(self, master):
        self.newWindow = None
        self.master = master
        self.title = "My Minimum Reproducible Example"
        self.fontA = ("arial", 20, "bold")
        
        self.canvas = tk.Canvas(height=5)
        self.canvas.pack()
        
        self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
                                font=self.fontA, command=self.changeImage)
        self.button.pack(fill="both")

    def changeImage(self):
        print('open second window')
        self.newWindow = tk.Toplevel(self.master)
        img = AcquireImage(self.newWindow)
        self.master.wait_window(self.newWindow)
        print('close second window')

        if img.image_selected: # check if image was selected
            self.image = img.image_selected
            self.button.configure(image=self.image, height=self.image.height())
        

root = tk.Tk()
app = ButtonImg(root)
root.mainloop()

BTW: Если вы хотите изменить изображение, не закрывая второе окно, вы должны отправить первое окно (или кнопку из первого окна) в качестве аргумента во второе окно и изменить изображение в show_dialogs()

import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk


class AcquireImage:
    
    def __init__(self, master, first_window):
        self.master = master
        self.first_window = first_window
        
        self.fontA = ("arial", 20, "bold")
        
        self.frame = tk.Frame(master, bg="#1B2631")
        self.frame.pack(fill="both", expand=True)
        
        self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
                              font=self.fontA, command=lambda:self.show_dialogs(1))
        self.button1.grid(row=0, column=0, sticky="nsew")
        
        self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
                              font=self.fontA, command=lambda:self.show_dialogs(2))
        self.button2.grid(row=0, column=1, sticky="nsew")
        
        self.image_selected = None

    def show_dialogs(self, method):
        
        if method == 1:
            ret = filedialog.askopenfilename(initialdir='/home/user/images/')
            if ret:
                self.image_selected = ImageTk.PhotoImage(file=ret)
                self.first_window.image = self.image_selected
                self.first_window.button.configure(image=self.first_window.image, height=self.first_window.image.height())

        elif method == 2:
            self.image_selected = snipping_tool.get_snip()


class ButtonImg:
    
    def __init__(self, master):
        self.newWindow = None
        self.master = master
        self.title = "My Minimum Reproducible Example"
        self.fontA = ("arial", 20, "bold")
        
        self.canvas = tk.Canvas(height=5)
        self.canvas.pack()
        
        self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
                                font=self.fontA, command=self.changeImage)
        self.button.pack(fill="both")

    def changeImage(self):
        self.newWindow = tk.Toplevel(self.master)
        img = AcquireImage(self.newWindow, self) # first window as `self` but you can send `self.button`

        

root = tk.Tk()
app = ButtonImg(root)
root.mainloop()

РЕДАКТИРОВАТЬ: Сделать c о создании Диалога Windows

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...