Python tkinter Canvas 透明

标签 python python-3.x canvas tkinter tkinter-canvas

我希望使 tkinter Canvas 的背景透明,但仍然有 Canvas 的鼠标事件,这是我的代码,我使用的是 Windows 10,Python 3.6:

from tkinter import *
import time

WIDTH = 500
HEIGHT = 500
LINEWIDTH = 1
TRANSCOLOUR = 'gray'
global old
old = ()

tk = Tk()
tk.title('Virtual whiteboard')
tk.wm_attributes('-transparentcolor', TRANSCOLOUR)
canvas = Canvas(tk, width=WIDTH, height=HEIGHT)
canvas.pack()
canvas.config(cursor='tcross')
canvas.create_rectangle(0, 0, WIDTH, HEIGHT, fill=TRANSCOLOUR, outline=TRANSCOLOUR)
def buttonmotion(evt):
    global old
    if old == ():
        old = (evt.x, evt.y)
        return
    else:
       canvas.create_line(old[0], old[1], evt.x, evt.y, width=LINEWIDTH)
        old = (evt.x, evt.y)
def buttonclick(evt):
    global old
    canvas.create_line(evt.x-1, evt.y-1, evt.x, evt.y, width=LINEWIDTH)
    old = (evt.x, evt.y)
canvas.bind('<Button-1>', buttonmotion)
canvas.bind('<B1-Motion>', buttonclick)
while True:
    tk.update()
    time.sleep(0.01)

运行代码时,它会生成透明背景,但我选择下面的内容,而不是 Canvas 。

最佳答案

我在 win api 的帮助下构建了一些解决方法,这是我的建议:

from tkinter import *
import time
import win32gui
import win32api

WIDTH = 500
HEIGHT = 500
LINEWIDTH = 1
TRANSCOLOUR = 'gray'
title = 'Virtual whiteboard'
global old
old = ()
global HWND_t
HWND_t = 0

tk = Tk()
tk.title(title)
tk.lift()
tk.wm_attributes("-topmost", True)
tk.wm_attributes("-transparentcolor", TRANSCOLOUR)

state_left = win32api.GetKeyState(0x01)  # Left button down = 0 or 1. Button up = -127 or -128

canvas = Canvas(tk, width=WIDTH, height=HEIGHT)
canvas.pack()
canvas.config(cursor='tcross')
canvas.create_rectangle(0, 0, WIDTH, HEIGHT, fill=TRANSCOLOUR, outline=TRANSCOLOUR)

def putOnTop(event):
    event.widget.unbind('<Visibility>')
    event.widget.update()
    event.widget.lift()
    event.widget.bind('<Visibility>', putOnTop)
def drawline(data):
    global old
    if old !=():
        canvas.create_line(old[0], old[1], data[0], data[1], width=LINEWIDTH)
    old = (data[0], data[1])

def enumHandler(hwnd, lParam):
    global HWND_t
    if win32gui.IsWindowVisible(hwnd):
        if title in win32gui.GetWindowText(hwnd):
            HWND_t = hwnd

win32gui.EnumWindows(enumHandler, None)

tk.bind('<Visibility>', putOnTop)
tk.focus()

running = 1
while running == 1:
    try:
        tk.update()
        time.sleep(0.01)
        if HWND_t != 0:
            windowborder = win32gui.GetWindowRect(HWND_t)
            cur_pos = win32api.GetCursorPos()
            state_left_new = win32api.GetKeyState(0x01)
            if state_left_new != state_left:
                if windowborder[0] < cur_pos[0] and windowborder[2] > cur_pos[0] and windowborder[1] < cur_pos[1] and windowborder[3] > cur_pos[1]:
                drawline((cur_pos[0] - windowborder[0] - 5, cur_pos[1] - windowborder[1] - 30))
            else:
                old = ()
    except Exception as e:
        running = 0
        print("error %r" % (e))

新代码位的镜头说明:

tk.lift()
tk.wm_attributes("-topmost", True)

...

def putOnTop(event):
event.widget.unbind('<Visibility>')
event.widget.update()
event.widget.lift()
event.widget.bind('<Visibility>', putOnTop)

...

tk.bind('<Visibility>', putOnTop)
tk.focus()

这些行确保该窗口始终位于所有其他窗口之上。

global HWND_t
HWND_t = 0

...

def enumHandler(hwnd, lParam):
    global HWND_t
    if win32gui.IsWindowVisible(hwnd):
        if title in win32gui.GetWindowText(hwnd):
            HWND_t = hwnd

win32gui.EnumWindows(enumHandler, None)

此代码位将遍历当前显示的所有窗口并捕获白板窗口的句柄(确保标题是唯一的,否则可能会捕获错误的句柄)。

state_left = win32api.GetKeyState(0x01)

...

if HWND_t != 0:
    windowborder = win32gui.GetWindowRect(HWND_t)
    cur_pos = win32api.GetCursorPos()
    state_left_new = win32api.GetKeyState(0x01)
    if state_left_new != state_left:
        if windowborder[0] < cur_pos[0] and windowborder[2] > cur_pos[0] and windowborder[1] < cur_pos[1] and windowborder[3] > cur_pos[1]:
                drawline((cur_pos[0] - windowborder[0] - 5, cur_pos[1] - windowborder[1] - 30))
    else:
        old = ()

这个

  1. 检查是否找到句柄
  2. 检查鼠标按钮 1 是否被单击
  3. 检查鼠标是否在窗口内

如果全部为真,它将获取鼠标数据并绘制线条

当前模式是,在单击按钮之前不会绘制任何内容,然后在再次单击按钮之前绘制。

关于Python tkinter Canvas 透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42869590/

相关文章:

python - 将一个列表中的当前元素与另一个列表中的下一个元素进行比较

python-3.x - 导入错误: No module named numpy in Debian OS

python - 日期转换器

mysql - python3计算自上次mysql数据输入以来的分钟数

javascript - HTML5 Canvas ctx.fill() 填充描边区域外

python - 将列表项替换为存储在 python 字典中的项的值

python - 解析 json 数据时仅检索前 2 个值

javascript - 将列表变成可缩放的多边形

python 以数组格式打印字符串

android - 创建位图之前计算文本大小