Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tkinter & Canvas
#1
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()
Gribouillis write Mar-23-2024, 12:24 PM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Reply
#2
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.

Attached Files

Thumbnail(s)
       
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#3
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?
Peter_Emp1 likes this post
Reply
#4
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"
Reply
#5
Thanks you helped me a lot! But why I should save image into self.image? I can't understand this...
Reply
#6
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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to positon a tkinter canvas Tyrel 3 1,929 Dec-11-2020, 03:05 PM
Last Post: deanhystad
  use classes in tkinter canvas fardin 2 2,637 Jan-06-2019, 04:23 AM
Last Post: fardin

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020