Question:
How to make tkinter whiteboard transparent?

Problem:

I made a whiteboard where I can draw lines on it.


Here is My code:

import tkinter as tk

from tkinter import ttk

from ttkbootstrap import Style


class Whiteboard:

    def __init__(self,master):

        self.master = master

        self.master.title('Whiteboard')

        self.master.resizable(True,True)

        self.master.geometry("800x600")

        

        #set ttkbootstrap style

        self.style = Style(theme = 'pulse')

        self.master.configure(bg='white')



        #create canvas

        self.canvas = tk.Canvas(self.master,width=1200,height=600)

        self.canvas.pack(expand=True, fill='both')


        #create buttons

        self.button_frame = ttk.Frame(self.canvas)

        self.button_frame.pack(side='top',pady=10)


        #button configuration

        button_config = {

            'black':('dark.TButton',lambda:self.change_color('black')),

            'red':('danger.TButton',lambda:self.change_color('red')),

            'blue':('info.TButton',lambda:self.change_color('blue')),

            'green':('success.TButton',lambda:self.change_color('green')),

            'yellow':('warning.TButton',lambda:self.change_color('yellow')),

            'clear':('light.TButton',self.clear_canvas),

        }


        #add buttons to the button frame

        for color,(style_name,command) in button_config.items():

            ttk.Button(self.button_frame,text=color.capitalize(),

                       command=command,style=style_name).pack(side='left',anchor='s', fill='y',padx=3,pady=3)

     

        #initialize drawing variables

        self.draw_color = 'black'

        self.line_width = 5

        self.old_x,self.old_y = None, None


        #all event listeners

        self.canvas.bind('<Button-1>',self.start_line)

        self.canvas.bind('<B1-Motion>',self.draw_line)


    #save starting point of line

    def start_line(self,event):

        self.old_x,self.old_y = event.x, event.y

    

    #draw line from starting point to current point and then update starting point

    def draw_line(self,event):

        if self.old_x and self.old_y:

            self.canvas.create_line(self.old_x,self.old_y, event.x, event.y, 

                                    width=self.line_width,fill= self.draw_color,

                                    capstyle=tk.ROUND,smooth=tk.TRUE)

            self.old_x,self.old_y = event.x,event.y


    #update current drawing color 

    def change_color(self,new_color):

        self.draw_color = new_color

    

    #delete all objects on canvas

    def clear_canvas(self):

        self.canvas.delete('all')


if __name__=='__main__':

    root = tk.Tk()

    whiteboard = Whiteboard(root)

    root.mainloop()


However, I want to make the white part transparent.


I tried:

self.master.wm_attributes('-transparentcolor',self.master['bg'])


It does make it transparent but I can no more draw on it. I will select the program behind it if I click on it.


I also tried this below but It seems it doesn't work on Tk().Canvas().

import win32gui

import win32con

import win32api


What can I do to make a transparent paint board?


Solution:

What I can suggest is a kind of trick. First, install the necessary libraries. pip install pywin32, pip install pillow


And load the library.

import tkinter as tk

from tkinter import ttk

from ttkbootstrap import Style

from PIL import ImageGrab, ImageTk

from win32api import GetSystemMetrics


And prepare a full-screen screenshot before the window is created.

    def __init__(self, master):

        self.screen_width = GetSystemMetrics(78)

        self.screen_height = GetSystemMetrics(79)

        self.full_image = ImageGrab.grab(bbox=(0, 0, self.screen_width, self.screen_height), all_screens=True)


Create an empty image object on the canvas.

        # create canvas

        self.canvas = tk.Canvas(self.master)

        self.image_obj = self.canvas.create_image(0, 0, anchor="nw", image=None)

        self.canvas.pack(expand=True, fill='both')


Now let's add an event.

        # all event listeners

        self.canvas.bind('<Button-1>', self.start_line)

        self.canvas.bind('<B1-Motion>', self.draw_line)

        self.master.bind('<Configure>', self.screen_update)


And add a function.

    def screen_update(self, event):

        self.img = self.full_image.crop((self.canvas.winfo_rootx(),

                                        self.canvas.winfo_rooty(),

                                        self.canvas.winfo_rootx() + 800, # your master geometry x

                                        self.canvas.winfo_rooty() + 600)) # your master geometry y

        self.imgtk = ImageTk.PhotoImage(image=self.img, master=self.master)

        self.canvas.itemconfig(self.image_obj, image=self.imgtk)


So the full code is

import tkinter as tk

from tkinter import ttk

from ttkbootstrap import Style

from PIL import ImageGrab, ImageTk

from win32api import GetSystemMetrics


class Whiteboard:

    def __init__(self, master):

        self.screen_width = GetSystemMetrics(78)

        self.screen_height = GetSystemMetrics(79)

        self.full_image = ImageGrab.grab(bbox=(0, 0, self.screen_width, self.screen_height), all_screens=True)

        self.master = master

        self.master.title('Whiteboard')

        self.master.resizable(True, True)

        self.master.geometry("800x600")


        # set ttkbootstrap style

        self.style = Style(theme='pulse')

        self.master.configure(bg='white')


        # create canvas

        self.canvas = tk.Canvas(self.master)

        self.image_obj = self.canvas.create_image(0, 0, anchor="nw", image=None)

        self.canvas.pack(expand=True, fill='both')


        # create buttons

        self.button_frame = ttk.Frame(self.canvas)

        self.button_frame.pack(side='top', pady=10)


        # button configuration

        button_config = {

            'black': ('dark.TButton', lambda: self.change_color('black')),

            'red': ('danger.TButton', lambda: self.change_color('red')),

            'blue': ('info.TButton', lambda: self.change_color('blue')),

            'green': ('success.TButton', lambda: self.change_color('green')),

            'yellow': ('warning.TButton', lambda: self.change_color('yellow')),

            'clear': ('light.TButton', self.clear_canvas),

        }


        # add buttons to the button frame

        for color, (style_name, command) in button_config.items():

            ttk.Button(self.button_frame, text=color.capitalize(),

                       command=command, style=style_name).pack(side='left', anchor='s', fill='y', padx=3, pady=3)


        # initialize drawing variables

        self.draw_color = 'black'

        self.line_width = 5

        self.old_x, self.old_y = None, None


        # all event listeners

        self.canvas.bind('<Button-1>', self.start_line)

        self.canvas.bind('<B1-Motion>', self.draw_line)

        self.master.bind('<Configure>', self.screen_update)



    def screen_update(self, event):

        self.img = self.full_image.crop((self.canvas.winfo_rootx(),

                                        self.canvas.winfo_rooty(),

                                        self.canvas.winfo_rootx() + 800, # your master geometry x

                                        self.canvas.winfo_rooty() + 600)) # your master geometry y

        self.imgtk = ImageTk.PhotoImage(image=self.img, master=self.master)

        self.canvas.itemconfig(self.image_obj, image=self.imgtk)


    # save starting point of line

    def start_line(self, event):

        self.old_x, self.old_y = event.x, event.y


    # draw line from starting point to current point and then update starting point

    def draw_line(self, event):

        if self.old_x and self.old_y:

            self.canvas.create_line(self.old_x, self.old_y, event.x, event.y,

                                    width=self.line_width, fill=self.draw_color,

                                    capstyle=tk.ROUND, smooth=tk.TRUE)

            self.old_x, self.old_y = event.x, event.y


    # update current drawing color

    def change_color(self, new_color):

        self.draw_color = new_color


    # delete all objects on canvas

    def clear_canvas(self):

        self.canvas.delete('all')



if __name__ == '__main__':

    root = tk.Tk()

    whiteboard = Whiteboard(root)

    root.mainloop()


I hope it will be of help.


Suggested blogs:

>Invoking Python script from scons and pass ARGLIST

>Plugins and Presets for Vuejs project

>Python Error Solved: load_associated_files do not load a txt file

>PHP cURL to upload video to azure blob storage

>PHP Error Solved: htaccess problem with an empty string in URL

>Python Error Solved: pg_config executable not found

>Set up Node.js & connect to a MongoDB Database Using Node.js

>Setting up a Cloud Composer environment: Step-by-step guide>Migrate From Haruko To AWS App: 5 Simple Steps


Ritu Singh

Ritu Singh

Submit
0 Answers