user3474688
user3474688

Reputation: 223

Python Tkinter canvas inside canvas

The docs suggest I should be able to position a Frame object inside a Canvas, and that that Frame object could itself contain a Canvas. I'm wondering why the following toy code does not work. I don't see the the string "hello" anywhere, just the blue "outercanvas". What am I doing wrong?

from tkinter import *
class MainWindow(Frame):
def __init__(self):
    super().__init__()
    self.pack(fill=Y, side = LEFT)
    inframe = Frame(self)
    innercanvas = Canvas(inframe, width=20, height=20)
    innercanvas.create_text(10, 10, anchor=NW, text="Hello")

    outercanvas = Canvas(self, width=100, height=100, bg='#00ffff')
    outercanvas.create_window(0, 0, anchor=NW, window=inframe)
    outercanvas.pack(side=LEFT)

root = MainWindow()
root.mainloop()

Upvotes: 1

Views: 7193

Answers (2)

warrens
warrens

Reputation: 2145

from tkinter import *

class MainWindow(Frame):
    def __init__(self):
        super().__init__()
        self.pack(expand=Y,fill=BOTH)

        outercanvas = Canvas(self, width=200, height=100, bg='#00ffff')
        outercanvas.pack(expand=Y,fill=BOTH)

        innercanvas = Canvas(outercanvas, width=100, height=50)
        outercanvas.create_window(50, 25, anchor=NW, window=innercanvas)

        innercanvas.create_text(10, 10, anchor=NW, text="Hello")

root = MainWindow()
root.mainloop()

This canvas inside canvas works for me!

Upvotes: 2

jasonharper
jasonharper

Reputation: 9621

The primary reason why you're not seeing innercanvas is that you never called .pack() (or another geometry manager) on it, so the containing inframe doesn't know to display it.

Fixing that didn't actually make the code work, and I found this rather surprising - apparently, since you created inframe earlier than outercanvas, as children of the same Frame, inframe remained layered underneath the canvas and was therefore not visible. (This was with Python 2.7, perhaps it's been fixed in the version you're using.) Moving the creation of outercanvas up a few lines fixes this; you might perhaps want to make inframe a child of outercanvas instead of a sibling, to better reflect the hierarchical structure of your widgets.

Note that inframe is not actually needed at all - you could have used create_window() to directly add innercanvas to outercanvas.

Upvotes: 3

Related Questions