1

I am trying to put a tkinter widget (placed inside canvas) behind a canvas item. I tried tag_raise method but it is not working. Moreover, I want them in the same canvas.

Is there any other possible way?

import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()

canvas_widget = tkinter.Button(canvas, text="Hide this")
canvas_widget.place(x=25,y=30)

canvas_item = canvas.create_oval(10,10, 100,100, fill="blue")
canvas.tag_raise(canvas_item)

root.mainloop()
Akascape
  • 219
  • 2
  • 11

2 Answers2

1

To put a windows widget into a canvas you use the create_window method of the canvas to have the canvas manage a pre-created Tk widget. However, the Tk Canvas man page points out:

Note: due to restrictions in the ways that windows are managed, it is not possible to draw other graphical items (such as lines and images) on top of window items

To put a circle on a button, you can create an image and use that on the button. Just ensure you retain a reference to the image in your application class instance.

patthoyts
  • 32,320
  • 3
  • 62
  • 93
  • I used the `create_window` method to place the widget: ```canvas.create_window(50, 40, window=canvas_widget)```. But it is still placed above the circle object even after using `tag_raise` method. So, I guess there is no way to do this. – Akascape May 23 '23 at 08:50
1

It is possible to place a Canvas Oval object over a Button and have them act as one.

This simple demo uses tags to join canvas window objects together.

Code comments explain how.

Click mouse button 1 NEAR Button to pick and place Button/Oval objects """

import tkinter as tk

M = tk.Tk()
M.columnconfigure(0, weight = 1)
M.rowconfigure(0, weight = 1)
# Make Main Canvas and Button
C = tk.Canvas(M, width = 400, height = 400)
C.grid(sticky = tk.NSEW)
B = tk.Button(C, text = "       Press Me")
B.grid(sticky = tk.NSEW)
# Insert B into window W1
W1 = C.create_window(10, 10, window = B, anchor = tk.NW, tags = "A")

# Make Local Canvas c
c = tk.Canvas(C, width = 16, height = 16)
# Now make Oval
O = c.create_oval(2, 2, 16, 16, fill = "blue")
# Insert O into window W2
W2 = C.create_window(13, 13, window = c, anchor = tk.NW, tags = "A")

# Use tags to move both W1 and W2 as single object
flag = 0

# Demonstration of dual movement using tags
def mover(e):
    global flag, x, y, xx, yy
    x, y = e.x, e.y
    if e.num == 1 and int(e.type) == 4:
        flag = 1 - flag
    if flag:
        C.move("A", x-xx, y-yy)
    xx, yy = x, y

# bind 
C.event_add("<<CC>>", "<Motion>", "<Button-1>")
C.bind("<<CC>>", mover)

M.mainloop()
Derek
  • 1,916
  • 2
  • 5
  • 15
  • I know this method, you created a new canvas for that circle. This will not work in my case. – Akascape Jun 01 '23 at 16:49
  • To my knowledge this is the only way to achieve the effect you describe. The obvious alternative is to put an image of an oval on the button then insert the button into the canvas. – Derek Jun 02 '23 at 01:41