When running the following Python code, I'm able to change the raster (by drag and dropping a new raster file) and display its name in anew window as many times as I want (without closing the selection window and re-running the code). But as soon as I plot the raster distribution, I cannot change the raster file anymore. Which is what I want.
import os
import tkinter as tk
from tkinterdnd2 import TkinterDnD, DND_FILES
import rasterio
import matplotlib.pyplot as plt
from tkinter import messagebox
class SimpleApp(TkinterDnD.Tk):
def __init__(self):
super().__init__()
self.title("Simple File Selector")
self.geometry("400x400")
self.file_label = tk.Label(self, text="Drop a file here", relief="solid", width=40, height=5)
self.file_label.pack(pady=20)
self.file_label.drop_target_register(DND_FILES)
self.file_label.dnd_bind('<<Drop>>', self.load_file)
self.print_button = tk.Button(self, text="Display Filename", command=self.display_filename)
self.print_button.pack(pady=20)
self.plot_button = tk.Button(self, text="Plot Distribution", command=self.plot_distribution)
self.plot_button.pack(pady=20)
def load_file(self, event):
self.file_path = event.data.strip('{}')
self.file_label.config(text=os.path.basename(self.file_path) if self.file_path else "No file selected")
try:
with rasterio.open(self.file_path) as src:
self.raster_data = src.read(1)
except Exception as e:
messagebox.showerror("Error", f"Failed to read raster file: {e}")
self.file_label.config(text="Drop a file here")
self.raster_data = None
def display_filename(self):
if hasattr(self, 'file_path') and self.file_path:
filename_window = tk.Toplevel(self)
filename_window.title("Selected File")
filename_window.geometry("300x100")
filename_label = tk.Label(filename_window, text=self.file_path, wraplength=280)
filename_label.pack(pady=20)
else:
messagebox.showerror("Error", "No file selected")
def plot_distribution(self):
if hasattr(self, 'raster_data') and self.raster_data is not None:
plt.figure()
plt.hist(self.raster_data.flatten(), bins=50, color='blue', edgecolor='black')
plt.title('Raster Data Distribution')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()
else:
messagebox.showerror("Error", "No raster data to plot")
if __name__ == "__main__":
app = SimpleApp()
app.mainloop()
Inspiring from TheLizzard link, I was able to fix the issue. Thanks to him.
Here is the fixed code:
import os
import tkinter as tk
from tkinterdnd2 import TkinterDnD, DND_FILES
import rasterio
import matplotlib.pyplot as plt
from tkinter import messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
class SimpleApp(TkinterDnD.Tk):
def __init__(self):
super().__init__()
self.title("Simple File Selector")
self.geometry("400x400")
self.file_label = tk.Label(self, text="Drop a file here", relief="solid", width=40, height=5)
self.file_label.pack(pady=20)
self.file_label.drop_target_register(DND_FILES)
self.file_label.dnd_bind('<<Drop>>', self.load_file)
self.print_button = tk.Button(self, text="Display Filename", command=self.display_filename)
self.print_button.pack(pady=20)
self.plot_button = tk.Button(self, text="Plot Distribution", command=self.plot_distribution)
self.plot_button.pack(pady=20)
self.file_path = None
self.raster_data = None
def load_file(self, event):
self.file_path = event.data.strip('{}')
self.file_label.config(text=os.path.basename(self.file_path) if self.file_path else "No file selected")
try:
with rasterio.open(self.file_path) as src:
self.raster_data = src.read(1)
except Exception as e:
messagebox.showerror("Error", f"Failed to read raster file: {e}")
self.file_label.config(text="Drop a file here")
self.raster_data = None
def display_filename(self):
if self.file_path:
filename_window = tk.Toplevel(self)
filename_window.title("Selected File")
filename_window.geometry("300x100")
filename_label = tk.Label(filename_window, text=self.file_path, wraplength=280)
filename_label.pack(pady=20)
else:
messagebox.showerror("Error", "No file selected")
def plot_distribution(self):
if self.raster_data is not None:
plot_window = tk.Toplevel(self)
plot_window.title("Raster Data Distribution")
plot_window.geometry("800x600")
fig = Figure(figsize=(6, 4), dpi=100)
ax = fig.add_subplot(111)
ax.hist(self.raster_data.flatten(), bins=50, color='blue', edgecolor='black')
ax.set_title('Raster Data Distribution')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
canvas = FigureCanvasTkAgg(fig, master=plot_window)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
toolbar_frame = tk.Frame(plot_window)
toolbar_frame.pack(side=tk.BOTTOM, fill=tk.X)
toolbar = NavigationToolbar2Tk(canvas, toolbar_frame)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
else:
messagebox.showerror("Error", "No raster data to plot")
if __name__ == "__main__":
app = SimpleApp()
app.mainloop()