9

I am making a chess program and I want to be able to drag the pieces. In order to do this, I put the image of the piece on a Canvas so it can be dragged (I can also use a Label if I want). However, when I drag the piece there is a white square that surrounds the image of the piece.

enter image description here

When I researched the problem, many people gave this solution:

drag_canvas = Canvas(self, height=80, width=80, bg="yellow")
root.wm_attributes("-transparentcolor", "yellow")

This caused the background to be transparent but it was not the chessboard that was visible, it was the program behind the GUI

enter image description here.

Is there any way I can have the background be transparent and show the chessboard behind rather than the program behind the tkinter window?

Note: I do not mind using any other widget (e.g. a Label) but they must use modules that come default with Python (so no PIL) as this program needs to be used in an environment where I cannot download other modules.

Anonymous Coder
  • 442
  • 1
  • 5
  • 19
  • Read this [updating-tkinter-label-with-an-image](https://stackoverflow.com/questions/28798496/updating-tkinter-label-with-an-image) – stovfl Oct 27 '18 at 17:09
  • @stovfl That uses PIL – Anonymous Coder Oct 28 '18 at 23:39
  • Your pices are allready *transparent*, why do you want to use a `.Canvas(...`? [Edit] your Question and add info about the image format. – stovfl Oct 29 '18 at 07:14
  • @stovfl Yes, they are transparent but in order to be dragged around the board, I need to put them on some sort of widget. This widget has a background which is not transparent so I needed to make the background transparent. I just used a `Canvas` because I thought that this would be the best way judging by similar posts on stackoverflow. So, if there is a way to accomplish this without a `Canvas` then I am more than happy to use it. – Anonymous Coder Oct 29 '18 at 10:55

2 Answers2

7

Question: How to make a tkinter canvas background transparent?

The only possible config(... option, to set the background to nothing

c.config(bg='')

results with: _tkinter.TclError: unknown color name ""


To get this result:

enter image description here

you have to hold the chess board and figures within the same .Canvas(....

    self.canvas = Canvas(self, width=500, height=200, bd=0, highlightthickness=0)
    self.canvas.create_rectangle(245,50,345,150, fill='white')

    self.image = tk.PhotoImage(file='chess.png')
    self.image_id = self.canvas.create_image(50,50, image=self.image)

    self.canvas.move(self.image_id, 245, 100)

Tested with Python: 3.5 - TkVersion: 8.6

stovfl
  • 14,172
  • 7
  • 20
  • 46
  • 4
    Sorry, but the question is how to get a transparent canvas. You gave a work around, telling to put the image on the same canvas. How does this answer the question? In my case, I need to put my image and background on different canvases. – 10 Rep Dec 06 '20 at 01:59
  • The questioner said "I do not mind using any other widget" and a tk PhotoImage should be close enough for pieces on a chestboard. Pillow can be used to get a transparent background – Terry Jan Reedy Feb 12 '22 at 00:57
1

A windows only solution is to use the pywin32 module that can be installed with:

pip install pywin32

With pywin32 you can alter the window exstyle and set the canvas to a layered window. A layered window can have a transparent colorkey and is done in the example below:

import tkinter as tk
import win32gui
import win32con
import win32api
        

root = tk.Tk()
root.configure(bg='yellow')
canvas = tk.Canvas(root,bg='#000000')#full black
hwnd = canvas.winfo_id()
colorkey = win32api.RGB(0,0,0) #full black in COLORREF structure
wnd_exstyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
new_exstyle = wnd_exstyle | win32con.WS_EX_LAYERED
win32gui.SetWindowLong(hwnd,win32con.GWL_EXSTYLE,new_exstyle)
win32gui.SetLayeredWindowAttributes(hwnd,colorkey,255,win32con.LWA_COLORKEY)
canvas.create_rectangle(50,50,100,100,fill='blue')
canvas.pack()

Explaination:

First we need the handle of the window which is called hwnd and we can get it in tkinter by .winfo_id().

Next we get the actual extended window style by GetWindowLong and ask specific for extended style information with win32con.GWL_EXSTYLE.

After that we do a bitwise operation in hexadezimal to alter the style with wnd_exstyle | win32con.WS_EX_LAYERED the result is our new_style.

Now we can set the extended style to the window with SetWindowLong. Finally we have our LayeredWindow which has additional Attributes we can work with. A transparent ColorKey can be set with SetLayeredWindowAttributes while we just use LWA_COLORKEY the alpha parameter has no use to us.

Important note: After defining a transparent colorkey, everything in that canvas with that color will be transparent.

enter image description here

Thingamabobs
  • 4,666
  • 3
  • 8
  • 33