Python Forum
Tkinter & Canvas - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Tkinter & Canvas (/thread-41821.html)



Tkinter & Canvas - Peter_Emp1 - Mar-23-2024

Hello, everyone!

I'm trying to create several tk.Canvas() for each ttk.Frame() to display different figures and images on my TabWidget (ttk.Notebook).
But When i try to create two instance of tk.Canvas() on two different ttk.Frame(), NOTHING displays at all!!!

You can use any png. They don't displays!

I tried it to do smth like this:

import tkinter as tk
from tkinter import ttk

class Guess():
    def __init__(self, parent, canvas):
        # Creating Frame
        # super().__init__(parent)
        self.window = parent

        # Creating Canvas for frame Guess:
        # self.canvas = tk.Canvas(self.window, width=1600, height=1000)
        self.canvas = canvas
        self.canvas.pack()

        ###-------------------- Using canvas here.......
        # Add image file
        bg = tk.PhotoImage(file="background1.png")
        # Display image
        self.canvas.create_image(0, 0, image=bg, anchor="nw")


class Full():
    def __init__(self, parent, canvas):
        # Creating Frame
        # super().__init__(parent)
        self.window = parent

        # Creating Canvas for frame Full:
        # self.canvas = tk.Canvas(self.window, width=1600, height=1000)
        self.canvas = canvas
        self.canvas.pack()

        ###-------------------- Using canvas here.......
        # Add image file
        bg = tk.PhotoImage(file="background2.png")
        # Display image
        self.canvas.create_image(0, 0, image=bg, anchor="nw")


class Main:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Analysis")
        self.window.geometry('1600x1000')

        # create a notebook
        notebook = ttk.Notebook(self.window)

        # Create and add tabs
        frame_guess = ttk.Frame(notebook, width=1600, height=1000)
        frame_note_full = ttk.Frame(notebook, width=1600, height=1000)
        frame_note_shorted = ttk.Frame(notebook, width=1600, height=1000)

        # Create Canvas for frames
        frame_guess_canvas = tk.Canvas(frame_guess, width=1600, height=1000)
        frame_note_canvas = tk.Canvas(frame_note_full, width=1600, height=1000)

        # Add ttk.Frame to ttk.Notebook
        notebook.add(frame_guess, text="Guess")
        notebook.add(frame_note_full, text="Note_Full")
        notebook.add(frame_note_shorted, text="Note_Shorted")

        Guess(frame_guess, frame_guess_canvas)
        Full(frame_note_full, frame_note_canvas)

        notebook.pack(padx=5, pady=5, fill="both", expand=True)

        # frame_guess.pack(fill="both", expand=True)
        # frame_note_full.pack(fill="both", expand=True)
        # frame_note_shorted.pack(fill="both", expand=True)
        # tab1 = ttk.Frame(notebook, width=1600, height=800)

        # Connecting Destructor
        self.window.protocol('WM_DELETE_WINDOW', self.__dell__)

        # Add image file
        # bg = tk.PhotoImage(file="background.png")
        # Display image
        # self.canvas.create_image(0, 0, image=bg, anchor="nw")

        # Launch mainwindow
        self.window.mainloop()

    def __dell__(self):
        # Destroy mainwindow
        self.window.destroy()


Main()



RE: Tkinter & Canvas - menator01 - Mar-23-2024

Are you trying to do something like this?
import tkinter as tk 
from tkinter import ttk 


class Container(tk.Canvas):
    ''' Container creates an image on a canvas '''
    def __init__(self, parent, img, x, y, *args, side='left', **kwargs):
        super().__init__()

        # Create the canvas
        self.canvas = tk.Canvas(parent, width=100, height=100)
        self.canvas.pack(side=side, fill='x')

        # Create the image
        bg = tk.PhotoImage(file=img)
        bg.bak = bg 
        self.canvas.create_image(x, y, image=bg)



class Window:
    def __init__(self, parent):

        # Create the notebook
        notebook = ttk.Notebook(parent)
        notebook.pack(expand=True, fill='both')

        # Create three frames
        frame1 = ttk.Frame(notebook, width=400, height=400)
        frame1.pack()

        frame2 = ttk.Frame(notebook, width=400, height=400)
        frame2.pack()

        frame3 = ttk.Frame(notebook, width=400, height=400)
        frame3.pack()

        # Create the image instances using the Container class
        img1 = Container(frame1, 'On Off/green.png', 50, 50, side='top')
        img2 = Container(frame2, 'On Off/red.png', 50, 50, side='top')

        img4 = Container(frame3, 'On Off/green.png', 50, 50, side='top')
        img5 = Container(frame3, 'On Off/red.png', 50, 50, side='top')

        # Add tabs to notebook
        notebook.add(frame1, text='Frame 1')
        notebook.add(frame2, text='Frame 2')
        notebook.add(frame3, text='Frame 3')


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('1600x1000+400+200')
    Window(root)
    root.mainloop()
I would probably use labels for the image unless, there was a need for the canvas.


RE: Tkinter & Canvas - deanhystad - Mar-24-2024

The code commented out in the OP is pretty good. The notebook pages should subclass tk.Frame or ttk.Frame. The pages should make the canvas. The main window should know as little as possible about the notebook or the notebook pages.
import tkinter as tk
import tkinter.ttk as ttk


class Guess(ttk.Frame):
    def __init__(self, *args, width=100, height=100, **kwargs):
        super().__init__(*args, **kwargs)
        self.canvas = tk.Canvas(self, width=width, height=height)
        self.canvas.pack()
        self.image = tk.PhotoImage(file="background1.png")
        self.canvas.create_image(0, 0, image=self.image, anchor="nw")
 

class Full(ttk.Frame):
    def __init__(self, *args, width=100, height=100, **kwargs):
        super().__init__(*args, **kwargs)
        self.canvas = tk.Canvas(self, width=width, height=height)
        self.canvas.pack()
        image = tk.PhotoImage(file="background1.png")
        self.canvas.create_image(0, 0, image=image, anchor="nw")


class Main(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        notebook = ttk.Notebook(self)
        notebook.pack(padx=5, pady=5, fill="both", expand=True)
        notebook.add(Guess(self), text="Guess")
        notebook.add(Full(self), text="Note_Full")


Main().mainloop()
But the reason you cannot see the images has nothing to do with that. You cannot see the images because there are no images. Run the code above and notice that Guess displays an image but Full does not. There is only one difference between the two classes. Can you spot it?


RE: Tkinter & Canvas - Pedroski55 - Mar-24-2024

Not an answer, but a problem:

I was interested, so I set:

img = '/home/pedro/Pictures/aphrodite.jpg'

Trying out the code, I am getting:

Quote:Main().mainloop()
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#20>", line 1, in <module>
File "<pyshell#8>", line 6, in __init__
File "<pyshell#17>", line 6, in __init__
File "/usr/lib/python3.10/tkinter/__init__.py", line 4103, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/usr/lib/python3.10/tkinter/__init__.py", line 4048, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "/home/pedro/Pictures/aphrodite.jpg"

Maybe 1 image could be corrupt, so I tried 2 other images, no joy!

This works:

from PIL import Image
im = Image.open(img)
im.show()
Any ideas what may be the problem?

Quote:bg = tk.PhotoImage(file=img)
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#28>", line 1, in <module>
File "/usr/lib/python3.10/tkinter/__init__.py", line 4103, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/usr/lib/python3.10/tkinter/__init__.py", line 4048, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "/home/pedro/Downloads/aphrodite.jpg"



RE: Tkinter & Canvas - Peter_Emp1 - Mar-24-2024

Thanks you helped me a lot! But why I should save image into self.image? I can't understand this...


RE: Tkinter & Canvas - deanhystad - Mar-24-2024

CPython uses a reference count to determine when objects are no longer used, and their memory can be recycled. If nothing references an object. there is nothing you can do with the object, so it must be unused.

In your program you used a local variable to reference the image returned by tkinter.PhotoImage(). When you left the function (Guess.__init__() for example) all the local variables cease to exist. There is nothing left to reference the image, so the image is deleted and the memory recycled. By changing image from a local function variable to an instance variable your program keeps a reference to the image.