繁体   English   中英

如何在 Tkinter 比例上绘制矩形?

[英]how to draw rectangle over Tkinter scale?

我有以下 GUI,如下图所示。 我想在覆盖刻度值 1、0 和 -1 的所有刻度上绘制一个透明矩形,而不是黑盒子。

有没有办法让 Tkinter 画布透明? 如果这不是正确的方法,我可以尝试哪些替代方法? 我分享了我使用的示例代码。 这可用于重现此 GUI。

在此处输入图像描述

from tkinter import *
import itertools

root = Tk()
root.geometry('840x420')
root.title('Test Window')

variables = {"var1", "var2", "var3", "var4"}
pair_list = list(itertools.combinations(list(variables), 2))
pair_result_dictionary = dict.fromkeys(pair_list)

my_canvas = Canvas()
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)

my_scrollbar = Scrollbar(root, orient=tk.VERTICAL, command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)

my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))

second_frame = Frame(my_canvas)

my_canvas.create_window((0, 0), window=second_frame, anchor="nw")

i = 0

heading_label = Label(second_frame, text="Test Window", font=('Arial',16))
heading_label.grid(column=0, row=0, sticky=tk.NW, columnspan=2, padx=(52, 0), pady=(20, 10))

for pair in pair_list:
    sample_scale = tk.Scale(second_frame, from_=9, to=-9, length=600, orient=tk.HORIZONTAL, font=('Arial', 15),
                            tickinterval=1,resolution=1)

    label_left = tk.Label(second_frame, text=pair[0], font=('Arial', 15))
    label_left.grid(column=0, row=2 + i, sticky=tk.W, padx=(52, 0), pady=5)

    sample_scale.set(((sample_scale['from'] - sample_scale['to']) / 2) + sample_scale['to'])
    sample_scale.grid(column=1, row=2 + i, sticky=tk.W, padx=(5, 0), pady=5)

    label_right = tk.Label(second_frame, text=pair[1], font=('Arial', 15))
    label_right.grid(column=2, row=2 + i, sticky=tk.W, padx=(5, 5), pady=5)

    i = i + 100

rectangle_holder_canvas = tk.Canvas(second_frame, width=100, height=70, bd=0, background='#000000')
rectangle_holder_canvas.grid(column=1, row=2, sticky=tk.S, padx=(0, 0), pady=0)
rec = rectangle_holder_canvas.create_rectangle(3, 3, 100, 70, outline='blue', fill='')
rectangle_holder_canvas.tag_raise(rec, 'all')

root.mainloop()

如果我使用以下代码行,它会使整个正方形透明,并且会看到主窗口下方的内容,这不是我想要的。

root.wm_attributes("-transparentcolor", 'grey')

rectangle_holder_canvas = tk.Canvas(second_frame, width=100, height=70, bd=0, bg="grey")

感谢您对如何实现这一目标的想法和时间。

我读到, "tag_raise" method does not affect canvas window items. To change a window item's stacking order, use a lower or lift method on the window. "tag_raise" method does not affect canvas window items. To change a window item's stacking order, use a lower or lift method on the window. . 所以我尝试通过设置second_frame.lower()my_canvas上绘制一个矩形,如下代码所示。 然后我只看到矩形,但看不到第二帧上的比例或标签。

my_canvas.create_window((0, 0), window=second_frame.lower(), anchor=CENTER)
rec = my_canvas.create_rectangle(50, 50, 200, 200, outline='blue', fill='blue')

你的问题没有简单的答案。

画布对象的组织分为两组。 矩形、多边形等普通图形对象按其创建顺序堆叠,第一个对象在背景中,最后一个对象在前景中。 此类对象的堆叠顺序可以通过canvas.liftcanvas.lowercanvas.tag_raisecanvas.tag_lower

第二组是画布窗口对象,它们是使用始终位于图形对象之上的固定堆叠顺序创建的。 因此不可能将普通的图形对象放在窗口对象之上。

这似乎使您的目标变得不可能,但是(至少)有一个解决方案。

以下代码通过使用位于画布上方的Toplevel窗口来实现您的目标。 此窗口使用wm_attributes("-transparentcolor", color)overrideredirect(1) ,它还设置wm_attributes("-topmost", True)

然后通过“配置”绑定将主窗口和顶部窗口绑定在一起,以便移动主窗口将自动移动顶部窗口。

这会产生您正在寻找的效果,尽管它可能不适合您的需要。

我使用了放置在画布窗口对象中的一个Scale对象来模拟您的代码片段。

import tkinter as tk

color = "red"

class transParent(tk.Tk):

    def __init__(self):

        super().__init__()
        self.withdraw()
        self.columnconfigure(0, weight = 1)

        wide, high = 606, 106
        self.geometry(f"{wide}x{high}+20+20")
        
        self.canvas = tk.Canvas(
            self, background = color, highlightthickness = 0, borderwidth = 0)
        self.canvas.grid(sticky = tk.NSEW)

        self.s_scale = tk.Scale(
            self.canvas, from_ = 9, to = -9, length = 600,
            orient = tk.HORIZONTAL, font = "Arial 15",
            takefocus = 1, tickinterval = 1, resolution = 1)
        self.s_scale.set(0)
        self.s_scale.grid(
            column = 0, row = 0, sticky = tk.W, padx = 5, pady = 5)

        self.sample_window = self.canvas.create_window(
            0, 0, window = self.s_scale, anchor = tk.NW)

        self.deiconify()
        self.wait_visibility()

        # build transparency toplevel : width, height, borderwidth
        w, h, bw = 100, 100, 4
        self.top = tk.Toplevel(
            self, padx = 0, pady = 0, background = color,
            highlightthickness = 0, relief = "solid", borderwidth = bw)

        self.X, self.Y = self.winfo_x, self.winfo_y
        self.top.geometry(f"{w}x{h}+{self.X()}+{self.Y()}")

        self.top.wm_attributes("-transparentcolor", color)
        self.top.overrideredirect(1)
        self.top.wm_attributes("-topmost", True)
        # estimate top position > trial & error?
        self.xx, self.yy = int(wide / 2 - w / 2.4), int(high / 3.4)
        # primary bindings
        self.bind("<Configure>", self.moveit)
        self.top.event_add(
            "<<HOOD>>", "<Button-1>", "<Button-2>", "<Button-3>")
        self.top.bind("<<HOOD>>", self.focal)
        self.focus_force()


    def moveit(self, ev):
        self.top.geometry(f"+{self.X()+self.xx}+{self.Y()+self.yy}")
        self.top.lift()


    def focal(self, ev):
        self.s_scale.focus_set()


if __name__ == "__main__":

    app = transParent()
    app.mainloop()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM