Tkinter remove stored file from memory - python-2.7

from Tkinter import *
import Tkinter as tk
import ttk
import tkFileDialog
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
class Look():
def __init__(self, master):
self.master = master
self.master.title("Demo")
self.master.configure(background = "grey91") #the color will be changed later
self.master.minsize(500, 300) # width + height
self.master.resizable(False, False)
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
ttk.Button(self.top_frame, text = "Load file", command = self.load_file,
style = "TButton").pack()
ttk.Button(self.top_frame, text = "Reset", command = self.clear_file,
style = "TButton").pack()
ttk.Button(self.top_frame, text = "Plot", command = self.plot_file,
style = "TButton").pack()
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.fig = plt.figure(figsize=(12, 5), dpi=100) ##create a figure; modify the size here
self.fig.add_subplot()
plt.title("blah")
self.canvas = FigureCanvasTkAgg(self.fig, master = self.bottom_frame)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def load_file(self):
self.file = tkFileDialog.askopenfilename(defaultextension = ".txt", filetypes = [("Text Documents", "*.txt")])
def clear_file(self):
self.fig.clf()
self.fig.add_subplot()
plt.xticks()
plt.yticks()
self.canvas.draw()
def plot_file(self):
self.r, self.g = np.loadtxt(self.file).transpose()
self.fig.clf()
plt.plot(self.r, self.g)
self.canvas.show()
def main():
root = Tk()
GUI = Look(root)
root.mainloop()
if __name__ == "__main__": main()
The code above creates a program has three buttons. The Load file buttom loads a txt file, Reset button is supposed to clear the plot and delete the file just loaded into the memory. Plot button is to plot the figure onto canvas below.
I have a question about how to write function associated with Reset function, i.e. clear_file function. Currently what it does is just clear the plot from canvas. But it seems the file that has been loaded to plot is stored in memory, since click again Plot, it will display the plot. My goal is to use Reset button to bring it to a fresh start--nothing stored in memory. I know loading a new file will overwrite the previous file. But when there are multiple buttons for loading different files, the situations could become complicated. Therefore I hope Reset can do the job.
If you want to try this little program, you may create a simple txt with two column data to be loaded into the program.
Thanks.

I would make 2 changes. Move the code that sets up your plot into its own method and reset the frame each time the method is called. This can be done with destroying the frame and remaking it. The 2nd change I would change the command on your reset to reference this new method.
Taking your code this is what I would change to be able to reset the plot.
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
class Look():
def __init__(self, master):
self.master = master
self.master.title("Demo")
self.master.configure(background = "grey91") #the color will be changed later
self.master.minsize(500, 300) # width + height
self.master.resizable(False, False)
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
ttk.Button(self.top_frame, text = "Load file", command = self.load_file,style = "TButton").pack()
ttk.Button(self.top_frame, text = "Reset", command = self.new_plot,style = "TButton").pack()
ttk.Button(self.top_frame, text = "Plot", command = self.plot_file,style = "TButton").pack()
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.new_plot()
# this function will reset your plot with a fresh one.
def new_plot(self):
self.bottom_frame.destroy()
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.fig = plt.figure(figsize=(12, 5), dpi=100) ##create a figure; modify the size here
self.fig.add_subplot()
plt.title("blah")
self.canvas = FigureCanvasTkAgg(self.fig, master = self.bottom_frame)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def load_file(self):
self.file = filedialog.askopenfilename(defaultextension = ".txt", filetypes = [("Text Documents", "*.txt")])
def clear_file(self):
self.fig.clf()
self.fig.add_subplot()
plt.xticks()
plt.yticks()
self.canvas.draw()
def plot_file(self):
self.r, self.g = np.loadtxt(self.file).transpose()
self.fig.clf()
plt.plot(self.r, self.g)
self.canvas.show()
if __name__ == "__main__":
root = tk.Tk()
GUI = Look(root)
root.mainloop()

Related

Exception AttributeError: when I try to get Tkinter to refresh image

I'm new to Tkinter, but I want to have my jpg image refreshed every 5 second, I've made this code, but I'm getting an exception attribute error.
can someone guide me ??
I receive this error:
Exception AttributeError: "'PhotoImage' object has no attribute '_PhotoImage__ph
oto'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage object at 0
x754b16f0>> ignored
# -*- coding: utf-8 -*-
from Tkinter import *
from apscheduler.schedulers.background import BackgroundScheduler
from PIL import ImageTk, Image
import time
window = Tk()
scheduler = BackgroundScheduler()
a = 0
def readimage():
global a, img, img1, img2, imglab
a = a +1
img = Image.open("./web1.jpg")
img1 = img.resize((288, 162), Image.ANTIALIAS)
img2 = ImageTk.PhotoImage(img1)
readimage()
window.attributes('-fullscreen', True)
window.configure(background = "black")
endbutton = Button(window, text="exit", command=window.destroy)
endbutton.grid(row=1,column=1, sticky="nw")
alabel = Label(window, text=a)
alabel.grid(row=2, column=2, sticky="w")
imglab = Label(window, image=img2, bg="black",fg="white", font=("Arial", 18))
imglab.place(relx=.6, rely=1.0,anchor="sw")
imglab.lower()
window.update()
scheduler.add_job(readimage, 'interval', seconds=5)
scheduler.start()
while True:
time.sleep(1)
alabel[ "text"]=a
imglab[ "image"]=img2
window.update()
mainloop()

Unable to display panel at the desired position

I created a Panel in a wxFrame and then created a FigureCanvas. I would like to fit the FigureCanvas into the panel completely, but somehow the FigureCanvas does not go into the panel2_2, but exactly on just the opposite side.
Following is my code.
import wx
from numpy import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class Frame1(wx.Frame):
def __init__(self, prnt):
wx.Frame.__init__(self, parent=prnt,
pos=wx.Point(0, 0), size=wx.Size(1340, 720),
style=wx.DEFAULT_FRAME_STYLE)
self.panel2_2 = wx.Panel(parent=self,
pos=wx.Point(940, 30), size=wx.Size(400, 690),
style=wx.TAB_TRAVERSAL)
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self.panel2_2, -1, self.figure)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.canvas, 0, wx.EXPAND)
self.panel2_2.SetSizer(sizer)
self.panel2_2.Fit()
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
#Every wxWidgets application must have a class derived from wxApp
class MyApp(wx.App):
# wxWidgets calls this method to initialize the application
def OnInit(self):
# Create an instance of our customized Frame class
self.frame = Frame1(None)
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == '__main__':
application = MyApp(0)
application.MainLoop()
and the result
I would like to have the image on the panel2_2 ( that is on the right hand side ) and not on the left hand side
I think the canvas is indeed going to panel2_2. The problem in your MWE is that you do not define a sizer for panel2_2. Therefore, panel2_2 is rendered from the upper left corner of the frame. This results in panel2_2 plus the canvas showing in the left of the frame. What you see to the right of the canvas is not panel2_2 but the rest of the frame since the size of the frame is larger than the size of panel2_2. If you add a blue panel1_1 and assign another wx.BoxSizer to the frame you get the canvas showing to the right.
import wx
from numpy import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class Frame1(wx.Frame):
def __init__(self, prnt):
wx.Frame.__init__(self, parent=prnt,
pos=wx.Point(0, 0), size=wx.Size(1340, 720),
style=wx.DEFAULT_FRAME_STYLE)
self.panel1_1 = wx.Panel(parent=self, size=(400, 690))
self.panel1_1.SetBackgroundColour('blue')
self.panel2_2 = wx.Panel(parent=self,
pos=wx.Point(940, 30), size=wx.Size(400, 690),
style=wx.TAB_TRAVERSAL)
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self.panel2_2, -1, self.figure)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.canvas, 0, wx.EXPAND)
self.panel2_2.SetSizer(sizer)
self.panel2_2.Fit()
sizerPanels = wx.BoxSizer(wx.HORIZONTAL)
sizerPanels.Add(self.panel1_1)
sizerPanels.Add(self.panel2_2)
sizerPanels.Fit(self)
self.SetSizer(sizerPanels)
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
self.Center()
#Every wxWidgets application must have a class derived from wxApp
class MyApp(wx.App):
# wxWidgets calls this method to initialize the application
def OnInit(self):
# Create an instance of our customized Frame class
self.frame = Frame1(None)
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == '__main__':
application = MyApp(0)
application.MainLoop()

how to insert buttons on the west side an Image file on the East Side or simply as a background using Tk

Here is my script
# Python 2.7.14 version
from Tkinter import *
import Tkinter
import tkMessageBox
from urllib2 import urlopen
import PIL
from PIL import ImageTk
import ImageTk
FILENAME = 'Fleur_de_lys.jpg'
root = Tk()
background = Canvas(root, width=250, height=250)##AttributeError: class Tk has no attribute 'Canvas'
canvas.pack()
tk_img = ImageTk.PhotoImage( file = FILENAME)
canvas.create_image(125, 125, image=tk_img)
quit_button = tk.Button(root, text = "Quit", command = root.quit, anchor = 'w',
width = 10, activebackground = "#33B5E5")
quit_button_window = canvas.create_window(10, 10, anchor='nw', window=quit_button)
root.mainloop()
No matter what attempt I do I keep getting AttributeError: class Tk has no attribute 'Canvas' where is my error if I just create button I have no issue what so ever all work but when I attempt to have a background image everything does not work
The problem appears to be that you're creating a canvas, and storing it in a variable named background, yet the very next line you are trying to call something called 'canvas', which you've never created.
Change this:
background = Canvas(root, width=250, height=250)
canvas.pack()
...
canvas.create_image(125, 125, image=tk_img)
to this:
background = Canvas(root, width=250, height=250)
background.pack()
...
background.create_image(125, 125, image=tk_img)
I fixed the issue jpg image was not being accepted I made it with a gif. Also found how to correct the buttons location and posn.
Here is the example without all the program
canvas = Canvas(root, width = 500, height = 500, bg='black')
canvas.pack(expand=YES, fill=BOTH)
my_image = PhotoImage(file='C:\\MOTD\\fleur_de_lys.gif')
canvas.create_image(0, 0, anchor = NW, image=my_image)
b1 = Button(root, text="From the Commander", command=callback,anchor = 'w',
width = 18, activebackground = "#33B5E5")
button_window1 = canvas.create_window(10, 10, anchor='nw', window=b1)

Image does not display in tkinter Canvas

I am trying to create a new class of Canvas that will be able to display and resize images. However The image does not display. I searched for similar questions and all the answers said to keep a reference of the PhotoImage in the class.( This answer for example). I tried doing that in a number of ways and none worked. In this example I tried saving a reference in a dictionary. I also tried self.tkimage = ImageTk.PhotoImage(image=img) which didn't work. And also tried using globals. I assume it has something to do with the garbage collector, but don't know how to solve.
Please assist.
import Tkinter as tk
from PIL import ImageTk, Image
import numpy as np
# a subclass of Canvas
class MyCanvas(tk.Canvas):
def __init__(self,parent,**kwargs):
tk.Canvas.__init__(self,parent,**kwargs)
self.tkimg = {}
self.images = []
self.image_on_canvas = []
def my_create_image(self, *args, **kw):
img = kw['image']
self.images.append(img)
self.tkimg[img] = ImageTk.PhotoImage(image=img)
kw['image'] = self.tkimg[img]
item = self.create_image(*args, **kw)
self.image_on_canvas.append(item)
def main():
root = tk.Tk()
myframe = tk.Frame(root)
myframe.pack(fill=tk.BOTH, expand=tk.YES)
mycanvas1 = MyCanvas(myframe, width=850, height=400, bg="red", highlightthickness=0)
mycanvas2 = MyCanvas(myframe, width=850, height=400, bg="green", highlightthickness=0)
mycanvas1.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.YES)
mycanvas2.pack(side=tk.RIGHT, fill=tk.BOTH, expand=tk.YES)
# add some widgets to the canvas
mycanvas2.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
mycanvas2.create_rectangle(50, 25, 150, 75, fill="blue")
arr1 = np.random.random([256,256])*255
img1 = Image.fromarray(arr1)
mycanvas1.my_create_image(0, 0, image=img1, anchor=tk.NW)
root.mainloop()
if __name__ == "__main__":
main()

Tkinter cell location (x,y)?

Is there a way to get the cell size and x,y location of a cell's corner?I have radio buttons on the left side of my frame and I would like to resize an image based on the size of the frame.
What I'm going to end up doing is creating a block that takes up a large group of cells that will allow me to zoom in on my .tif and scroll left/right and up/down. Does this type of widget already exist?
Here's a very rough outline of what I currently have
from tkinter import *
from PIL import Image,ImageTk
import os
file_path = "C:/Users/..."
dirs = os.listdir(file_path)
root = Tk()
# Set window size slightly below screen size
width = int(root.winfo_screenwidth() - root.winfo_screenwidth()/9)
height = int(root.winfo_screenheight() - root.winfo_screenheight()/9)
root.geometry(str(width)+"x"+str(height))
class Application(Frame):
def __init__(self,master):
Frame.__init__(self,master)
os.chdir(file_path)
self.grid()
self.create_widgets()
def create_widgets(self):
Label(self,
text = "Available Files"
).grid(row=0,column=0,sticky=W)
Label(self,
text = "Select one:"
).grid(row=1,column=0,sticky=W)
self.filelist = StringVar()
self.filelist.set(0)
# Radio buttons of files in directory
i = 1
for files in dirs:
if os.path.isfile(os.path.join(file_path, files)):
i += 1
Radiobutton(self,
text=files,
variable=self.filelist,
value=files,
command=self.update_text
).grid(row=i,column=0,sticky=W)
# Message box
self.result = Text(self, width=40, height=5, wrap=WORD)
self.result.grid(row=i, column=0, columnspan=3)
def update_text(self):
message = "File selected is "
message += self.filelist.get()
self.display_image()
self.result.delete(0.0, END)
self.result.insert(0.0, message)
def display_image(self):
try:
self.image = Image.open(self.filelist.get())
except:
message += self.filelist.get() + " doesn't exist. This is awkward..."
img_width,img_height = self.image.size
self.preview_image = ImageTk.PhotoImage(self.image)
self.preview = Label(self, image=self.preview_image)
self.preview.grid(row=0, column=3, rowspan=20)
app = Application(root)
root.mainloop()