in tkinter, is there a way to change the draw stack order of overlapping canvases?

  • Last Update :
  • Techknowledgy :

Here's how you do it using the existing function. Be sure to import Misc from tkinter:

from tkinter
import Misc
   ...
   class MyCustomButton(Canvas):
   ...
   def lift(self, aboveThis = None):
   Misc.tkraise(self)

Here's how you directly call the underlying tk interpreter:

class MyCustomButton(Canvas):
   ...
   def lift(self, aboveThis = None):
   self.tk.call('raise', self._w, aboveThis)

With that, you can raise one button over the other by calling the lift method:

def click_handler(self, event):
   event.widget.lift()

Suggestion : 2

With that, you can raise one button over anycodings_tkinter-canvas the other by calling the lift method:,Here's how you directly call the anycodings_tkinter-canvas underlying tk interpreter:,This works for as desired for button3, but anycodings_tkinter-canvas for custom_button1, the exception that is anycodings_tkinter-canvas raised is:,Since you are creating your own class, anycodings_tkinter-canvas you can override the lift method to use anycodings_tkinter-canvas either of these methods.

Here's some basic code that runs and anycodings_tkinter-canvas illustrates my problem. I've included anycodings_tkinter-canvas button3, a regular button that can lift() as anycodings_tkinter-canvas expected. If I click on custom_button1, anycodings_tkinter-canvas however, the click_handler raises an anycodings_tkinter-canvas exception.

from tkinter import Button, Canvas, Frame, Tk
from tkinter.constants import NW

class Example(Frame):

def __init__(self, root):
Frame.__init__(self, root)
self.canvas = Canvas(self, width=200, height=200, background="black")
self.canvas.grid(row=0, column=0, sticky="nsew")

self.button3 = Button(self.canvas, text="button3")
self.custom_button1 = MyCustomButton(self.canvas)
self.custom_button2 = MyCustomButton(self.canvas)

self.canvas.create_window(20, 20, anchor=NW, window=self.button3)
self.canvas.create_window(40, 40, anchor=NW, window=self.custom_button1)
self.canvas.create_window(34, 34, anchor=NW, window=self.custom_button2)

self.button3.bind("<Button-1>", self.click_handler)
   self.custom_button1.bind("<Button-1>", self.click_handler)
      self.custom_button2.bind("<Button-1>", self.click_handler)


         def click_handler(self,event):
         event.widget.lift() #raises exception if event.widget is a MyCustomButton
         #note that Canvas.lift() is deprecated, but documentation
         #says Canvas.tag_raise() doesn't work with window items

         class MyCustomButton(Canvas):
         def __init__(self, master):
         super().__init__(master, width=40, height=25, background='blue')


         if __name__ == "__main__":
         root = Tk()
         Example(root).pack(fill="both", expand=True)
         root.mainloop()

This works for as desired for button3, but anycodings_tkinter-canvas for custom_button1, the exception that is anycodings_tkinter-canvas raised is:

_tkinter.TclError: wrong # args: should be ".!example.!canvas.!mycustombutton2 raise tagOrId ?aboveThis?"

I could manage a bunch of custom widgets on anycodings_tkinter-canvas a canvas by only having one canvas that anycodings_tkinter-canvas handles all drawing and all the mouse events anycodings_tkinter-canvas for all the widgets. I could still have anycodings_tkinter-canvas classes for the widgets, but instead of anycodings_tkinter-canvas inheriting from Canvas, they'd accept Canvas anycodings_tkinter-canvas parameters. So adding would look something anycodings_tkinter-canvas like the code below, and I'd have to write anycodings_tkinter-canvas similar code for lifting, moving, anycodings_tkinter-canvas determining if a click event applied to this anycodings_tkinter-canvas button, changing active state, and so forth.

def add_to_canvas(self, canvas, offset_x = 0, offset_y = 0):

   self.button_border = canvas.create_rectangle(
      offset_x + 0, offset_y + 0,
      offset_x + 40, offset_y + 25
   )

#create additional button features

Here's how you do it using the existing anycodings_tkinter-canvas function. Be sure to import Misc from anycodings_tkinter-canvas tkinter:

from tkinter
import Misc
   ...
   class MyCustomButton(Canvas):
   ...
   def lift(self, aboveThis = None):
   Misc.tkraise(self)

Here's how you directly call the anycodings_tkinter-canvas underlying tk interpreter:

class MyCustomButton(Canvas):
   ...
   def lift(self, aboveThis = None):
   self.tk.call('raise', self._w, aboveThis)

With that, you can raise one button over anycodings_tkinter-canvas the other by calling the lift method:

def click_handler(self, event):
   event.widget.lift()

Suggestion : 3

All items are ordered from top to bottom in what's called the stacking order. If an item later in the stacking order overlaps the coordinates of an item below it, the item on top will be drawn on top of the lower item. The "raise" and "lower" methods allow you to adjust an item's position in the stacking order. ,Besides lines and rectangles, there are a number of different types of items that canvas widgets support. Remember that each one has its own set of item configuration options, detailed in the reference manual. , As you can see, things like "withtag" will take either an individual item or a tag; in the latter case, they will apply to all items having that tag (which could be none). The "addtag" and "find" have many other options, allowing you to specify items near a point, overlapping a particular area, and more. ,You've seen how you can modify the configuration options on an item — its color, width and so on. There are a number of other things you can do items.

Canvas widgets are created using the Canvas function:

canvas = Canvas(parent)

To create a line, the one piece of information you'll need to specify is where the line should be. This is done by using the coordinates of the starting and ending point, expressed as a list of the form x0 y0 x1 y1. The origin (0,0) is at the top left corner of the canvas, with the x value increasing as you move to the right, and the y value increasing as you move down. So to create a line from (10,10) to (200,50), we'd use this code:

canvas.create_line(10, 10, 200, 50)

Let's start our simple sketchpad example. For now, we'll want to be able to draw freehand on the canvas by dragging the mouse on it. We'll create a canvas widget, and then attach event bindings to it to capture mouse clicks and drags. When we first click the mouse, we'll remember that location as our "start" position. Every time the mouse is moved with the mouse button still held down, we'll create a line item going from this "start" position to the current mouse position. The current position will then be the "start" position for the next line segment.

#For Python 2.6
from Tkinter import *

#Globals
lastx, lasty = 0, 0

#Definitions
def xy(event):
global lastx, lasty
lastx, lasty = event.x, event.y

def addLine(event):
global lastx, lasty
canvas.create_line((lastx, lasty, event.x, event.y))
lastx, lasty = event.x, event.y

#Root Create + Setup
root = Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

#Canvas Create + Setup
canvas = Canvas(root)
canvas.grid(column=0, row=0, sticky=(N, W, E, S))
canvas.bind("<Button-1>", xy)
   canvas.bind("<B1-Motion>", addLine)

      #Main Loop
      root.mainloop()

Like with Tk widgets, changing attributes for canvas items after you've already created them can also be done.

id = canvas.create_line(0, 0, 10, 10, -fill red)
   ...
   canvas.itemconfigure(id, fill = 'blue', width = 2)

To capture these events, you use a bind command built into the canvas. It works exactly like the regular bind command, taking an event pattern and a callback. The only difference is you specify the canvas item this binding applies to.

canvas.tag_bind(id, '<1>', …)

Suggestion : 4

All items are ordered from top to bottom in what's called the stacking order. If an item later in the stacking order overlaps an item below it, the first item will be drawn on top of the second. The raise (lift in Tkinter) and lower methods allow you to adjust an item's position in the stacking order.,Image items can display arbitrary images. By default, the item is centered at the coordinates you specify, but this can be changed with the anchor option, e.g., nw means the coordinates are where to put the top-left of the image.,This command returns an item object representing the line. We'll see how it can be used shortly. Often, we don't need to refer to the item later, and can ignore the returned item object.,Rectangles are specified by the coordinates of opposing corners, e.g., top-left and bottom-right. They can be filled in (via fill) with one color, and the outline given a different color.

Canvas widgets are created using the Canvas class:

canvas = Canvas(parent, width = 500, height = 400, background = 'gray75')

Canvas widgets are created using the tk::canvas command:

tk::canvas.canvas - width 500 - height 400 - background gray75

Canvas widgets are created using the TkCanvas class:

canvas = TkCanvas.new(parent) {
   width 500;
   height 400;
   background 'gray75'
}

Canvas widgets are created using the new_tk__canvas method, a.k.a. Tkx::tk__canvas:

$canvas = $parent - > new_tk__canvas(-width => 500, -height => 400, -background => 'gray75');
canvas.create_line(10, 5, 200, 50)
.canvas create line 10 5 200 50

Suggestion : 5

Window items are an exception to the above rules. The underlying window systems require them always to be drawn on top of other items. In addition, the stacking order of window items is not affected by any of the canvas widget commands; you must use the raise and lower Tk commands instead. , 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. A window item always obscures any graphics that overlap it, regardless of their order in the display list. , The tag all is implicitly associated with every item in the canvas; it may be used to invoke operations on all the items in the canvas. ,If bindings have been created for a canvas window using the bind command, then they are invoked in addition to bindings created for the canvas's items using the bind widget command. The bindings for items will be invoked before any of the bindings for the window as a whole.

tagOrId may contain a logical expressions of tags by using operators: '&&', '||', '^' '!', and parenthesized subexpressions. For example:

.c find withtag {
   (a && !b) || (!a && b)
}
.c find withtag {(a&&!b)||(!a&&b)}
.c find withtag {
   a ^ b
}
pathName
pathName option ? arg arg... ?

-dash
   -
   activedash -
   disableddash -
   dashoffset -
   fill -
   activefill -
   disabledfill -
   offset -
   outline -
   activeoutline -
   disabledoutline -
   outlinestipple -
   activeoutlinestipple -
   disabledoutlinestipple -
   stipple -
   activestipple -
   disabledstipple -
   state -
   tags -
   width -
   activewidth -
   disabledwidth
bitmap
pathName create bitmap x y ? option value option value... ?
   pathName create bitmap coordList ? option value option value... ?

Suggestion : 6

The window stack order refers to the order of windows placed on the screen from bottom to top. The closer window is on the top of the stack and it overlaps the one lower.,The following example places the root window on top of all other windows. In other words, the root window is always on top:,The following example changes the size of the window to 600x400 and the position of the window to 50 pixels from the top and left of the screen:,The y is the window’s vertical position. For example, +50 means the top edge of the window should be 50 pixels below the top of the screen. And -50 means the bottom edge of the window should be 50 pixels above the bottom of the screen.

Let’s start with a simple program that consists of a window:

.wp - block - code {
      border: 0;
      padding: 0;
   }

   .wp - block - code > div {
      overflow: auto;
   }

   .shcb - language {
      border: 0;
      clip: rect(1 px, 1 px, 1 px, 1 px); -
      webkit - clip - path: inset(50 % );
      clip - path: inset(50 % );
      height: 1 px;
      margin: -1 px;
      overflow: hidden;
      padding: 0;
      position: absolute;
      width: 1 px;
      word - wrap: normal;
      word - break: normal;
   }

   .hljs {
      box - sizing: border - box;
   }

   .hljs.shcb - code - table {
      display: table;
      width: 100 % ;
   }

   .hljs.shcb - code - table > .shcb - loc {
      color: inherit;
      display: table - row;
      width: 100 % ;
   }

   .hljs.shcb - code - table.shcb - loc > span {
      display: table - cell;
   }

   .wp - block - code code.hljs: not(.shcb - wrap - lines) {
      white - space: pre;
   }

   .wp - block - code code.hljs.shcb - wrap - lines {
      white - space: pre - wrap;
   }

   .hljs.shcb - line - numbers {
      border - spacing: 0;
      counter - reset: line;
   }

   .hljs.shcb - line - numbers > .shcb - loc {
      counter - increment: line;
   }

   .hljs.shcb - line - numbers.shcb - loc > span {
      padding - left: 0.75 em;
   }

   .hljs.shcb - line - numbers.shcb - loc::before {
      border - right: 1 px solid #ddd;
      content: counter(line);
      display: table - cell;
      padding: 0 0.75 em;
      text - align: right; -
      webkit - user - select: none; -
      moz - user - select: none; -
      ms - user - select: none;
      user - select: none;
      white - space: nowrap;
      width: 1 % ;
   }
import tkinter as tk

root = tk.Tk()
root.mainloop() Code language: Python(python)

To change the window’s title, you use the title() method like this:

window.title(new_title) Code language: Python(python)

For example, the following changes the title of the root window to 'Tkinter Window Demo':

import tkinter as tk

root = tk.Tk()
root.title('Tkinter Window Demo')

root.mainloop() Code language: Python(python)

The following shows the geometry specification:

widthxheight± x± yCode language: Python(python)

To change the size and position of a window, you use the geometry() method:

window.geometry(new_geometry) Code language: Python(python)