在 tkinter 中,有没有办法改变重叠画布的绘制堆栈顺序?

2024-01-27

问题

使用 Python 的 tkinter,我尝试通过扩展来创建自定义按钮和其他小部件画布小部件 http://effbot.org/tkinterbook/canvas.htm#when-to-use。当用户与它们交互时,如何更改在顶部绘制哪些自定义画布小部件?

lift() https://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.lift-method适用于常规 tkinter 按钮和其他小部件,但当我尝试使用它来抬起画布时会引发错误,因为Canvas 有自己的 lift() 方法 http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas.lift-method。 Canvas 的 lift() 已被弃用,转而使用 tag_raise()。然而,tag_raise() http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas.tag_raise-method文档说它“不适用于窗口项目”,这符合我的经验,并指示我改用 lift() 。我的大脑一直在追踪这个看似循环的文档,直到它引发了自己的 StackOverflow 异常,这让我不得不问你。

代码说明

这是一些运行并说明我的问题的基本代码。我已经添加了button3,一个可以按预期 lift() 的常规按钮。但是,如果我单击 custom_button1,click_handler 会引发异常。

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()

这适用于button3,但对于custom_button1,引发的异常是:

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

在 Canvas.lift() 和 Canvas.tag_raise() 通常用于通过标签或 id 影响画布上的项目(而不是画布本身)的上下文中,该异常是有意义的。我只是不知道如何更改画布本身的堆栈顺序,以便我可以将其用作自定义小部件。

我考虑过的解决方法

我只需在画布上管理一堆自定义小部件one处理的画布all绘图和all鼠标事件all小部件。我仍然可以拥有小部件的类,但它们不是从 Canvas 继承,而是接受 Canvas 参数。因此,添加看起来类似于下面的代码,我必须编写类似的代码来提升、移动、确定单击事件是否应用于此按钮、更改活动状态等等。

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

不过,这种解决方法似乎违背了 tkinter 中既定的编码范例。此外,我相信这种方法会阻止我在其他窗口对象之上绘制这些自定义按钮。 (根据create_window() 文档 http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas.create_window-method“您不能在小部件之上绘制其他画布项目。”在此解决方法中,所有自定义按钮都将是画布项,因此如果我正确阅读此内容,则无法在其他小部件之上绘制。)更不用说实现时需要的额外代码了。也就是说,我目前不知道如何实现这一点。

预先感谢您的帮助!


不幸的是,您偶然发现了 tkinter 实现中的一个错误。您可以通过多种方式解决这个问题。您可以创建一个方法来执行 tkinter 的操作lift方法就可以,也可以直接调用tkinter中的方法Misc class.

由于您正在创建自己的类,因此您可以覆盖lift方法使用这些方法中的任何一种。

以下是使用现有函数的方法。一定要导入Misc来自 tkinter:

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

以下是直接调用底层 tk 解释器的方法:

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

这样,您可以通过调用lift method:

def click_handler(self,event):
    event.widget.lift()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 tkinter 中,有没有办法改变重叠画布的绘制堆栈顺序? 的相关文章

  • PyList_SetItem 与 PyList_SETITEM

    据我所知 PyList SetItem 和 PyList SETITEM 之间的区别在于 PyList SetItem 会降低它覆盖的列表项的引用计数 而 PyList SETITEM 不会 我有什么理由不应该一直使用 PyList Set
  • 具有多处理功能的 Python 代码无法在 Windows 上运行

    以下简单的绝对初学者代码在 Ubuntu 14 04 Python 2 7 6 和 Cygwin Python 2 7 8 上运行 100 但在 Windows 64 位 Python 2 7 8 上挂起 我使用另一个片段观察到了同样的情况
  • Python Nose 导入错误

    我似乎无法理解鼻子测试框架 https nose readthedocs org en latest 识别文件结构中测试脚本下方的模块 我已经设置了演示该问题的最简单的示例 下面我会解释一下 这是包文件结构 init py foo py t
  • Spark MLlib - 训练隐式警告

    我在使用时不断看到这些警告trainImplicit WARN TaskSetManager Stage 246 contains a task of very large size 208 KB The maximum recommend
  • 为什么导入 pdb 时出现此错误? “模块”对象没有属性“ascii_letters”

    尝试调试我的代码 我正在导入库pdb import sys from subprocess import check call import pdb functions if name main Code 我收到此错误 File reg p
  • html 解析器 python

    我正在尝试解析一个网站 我正在使用 HTMLParser 模块 问题是我想解析第一个 a href 评论后 但我真的不知道该怎么做 所以我在文档中发现有一个函数叫做handle comment 但我还没有找到如何正确使用它 我有以下内容 i
  • Django 的 URL 覆盖率测试为 0%,为什么?

    使用姜戈鼻子 我对 URL 进行了测试 但 URL 覆盖率仍然为 0 为什么 python manage py 测试配置文件 这是我的报道 Name Stmts Miss Cover Missing profiles 0 0 100 pro
  • 为 Networkx 图添加标题?

    我希望我的代码创建一个带有标题的图 使用下面的代码 可以创建绘图 但没有标题 有人可以告诉我我做错了什么吗 import pandas as pd import networkx as nx from networkx algorithms
  • 用Python中的嵌套for循环替换重复的if语句?

    在我编写的下面的代码中 n 4 所以有五个 if 语句 所以如果我想将 n 增加到 比如说 10 那么就会有很多 if 语句 因此我的问题是 如何用更优雅的东西替换所有 if 语句 n p 4 5 number of trials prob
  • 杂乱的扭曲连接在不干净的时尚中消失了。没有代理。已经尝试过标题

    我正在尝试抓取这个网站 https www5 apply2jobs com jupitermed ProfExt index cfm fuseaction mExternal searchJobs https www5 apply2jobs
  • 在 matplotlib 中使用 yscale('log') 时缺少误差线

    在某些情况下 当使用对数刻度时 matplotlib 会错误地显示带有误差条的图 假设这些数据 例如在 pylab 内 s 19 0 20 0 21 0 22 0 24 0 v 36 5 66 814250000000001 130 177
  • pip 安装软件包两次

    不幸的是我无法重现它 但我们已经见过几次了 pip 将一个软件包安装两次 如果卸载第一个 第二个就会可见并且也可以被卸载 我的问题 如果一个包安装了两次 如何用 python 检查 背景 我想编写一个测试来检查这一点 devOp Updat
  • 从 IMDbPy 结果中的片目中获取电影 ID

    我正在尝试创建一个数据集 允许我根据 Python IMDb API 中的演员 ID 和电影 ID 加入演员和电影 现在 我正在尝试从演员的电影作品中提取电影 ID 列表 但无法做到 例如 我知道 Rodney Dangerfield 在
  • Django 接受 AM/PM 作为表单输入

    我试图弄清楚如何使用 DateTime 字段在 Django 中接受 am pm 作为时间格式 但我遇到了一些麻烦 我尝试在 forms py 文件中这样设置 pickup date time from DateTimeField inpu
  • 为什么 bot.get_channel() 会产生 NoneType?

    我正在制作一个 Discord 机器人来处理公告命令 当使用该命令时 我希望机器人在特定通道中发送一条消息 并向用户发送一条消息以表明该命令已发送 但是 我无法将消息发送到频道 我尝试了这段代码 import discord import
  • 从另一个 python 脚本获取返回信息

    我在 Linux 上 我有一个 python 脚本 我想从另一个 python 脚本调用它 我不想将其作为模块导入 为了一层安全性 现在为了学术练习 因为我想弄清楚这一点 我实际上想让一个脚本使用 os system 或另一个类似的函数 并
  • 在 Python 的 Textmate 中突出显示尾随空格?

    我想做类似的事情this http remysharp com 2008 03 30 trailing white space in textmate Textmate 提示 这样当我在 Python 中编写代码时 尾随空白总是以某种方式突
  • 如何使用Featuretools按列值从单个数据框中的多个列创建特征?

    我正在尝试根据之前的结果来预测足球比赛的结果 我在 Windows 上运行 Python 3 6 并使用 Featuretools 0 4 1 假设我有以下代表结果历史记录的数据框 原始数据框 https i stack imgur com
  • 在Python中从日期时间中减去秒

    我有一个 int 变量 它实际上是秒 让我们调用这个秒数X 我需要得到当前日期和时间 以日期时间格式 减去的结果X秒 Example If X是 65 当前日期是2014 06 03 15 45 00 那么我需要得到结果2014 06 03
  • 在游戏中实现功能

    我在完成这部分作业时遇到了麻烦 我必须宣布游戏的获胜者 然后输入到函数中 输入所有 if 语句后 我必须创建一个函数def playGame 这必须包括 showRules user getUserChoice computer getCo

随机推荐

  • 从 jQuery 调用 PHP 函数?

    我的网站上有一个 PHP 函数 需要几秒钟才能完成 这会保留整个页面 这是我不想要的 页面加载后是否可以使用 jquery 调用此 PHP 函数并将结果显示在 div 中 还要显示 ajax 加载器图像直到 PHP 函数完成 我一直在查看
  • hubris 无法安装:缺少 C 库:ruby、ruby、ruby

    我拼命尝试安装 Hubris 但每当我运行 cabal install 时安装就会失败 哈比斯链接 https github com mwotton Hubris tree master Haskell https github com m
  • Air for Android:设备警报后黑屏

    我确实有一个问题 而且没什么可继续的 我即将在三星应用商店上发布一个应用程序 使用 Air for Android As3 创建 并且刚刚得到了一份问题列表 在该应用程序经过三星工作人员测试后 才能发布该应用程序 我确实解决了几乎所有问题
  • Map和Reduce之间的主要区别

    我使用了这两种方法 但我对这两种方法的用法感到很困惑 有什么吗map可以做但是reduce不可以 反之亦然 注意 我知道如何使用这两种方法 我想知道这些方法之间的主要区别以及我们何时需要使用 Source http www globalne
  • OpenJDK 11:在 Linux 上获取 ClassNotFound,在 Windows 上运行良好

    我们有一个基于桌面的 swing 应用程序 可以在 Oracle JDK 1 8 上正常运行 迁移到 OpenJDK 11 后 我们遇到了一些未找到的类异常com sun java swing Painter 我们通过生成一个包含一些类的捆
  • 有没有办法在redis中获取客户端IP?

    我进行了网络搜索 但没有找到任何相关内容 我正在集群上运行redis 并且想找出哪台机器正在连接到redis 特别是当没有机器应该连接 但redis仍然说某些机器已连接时 提前致谢 使用 MONITOR 只会显示实际向 Redis 发送流量
  • mysql 小数点四舍五入

    我是 mysql 的新手 需要一些基本的东西 我需要像这样四舍五入小数 21 4758 应该是 21 48 0 2250 应为 0 22 23 0850 应为 23 08 22 9950 应该是 22 99 我尝试了很多事情但没能成功 Th
  • 在Python中处理从源目录到目标目录的一组文件

    Being 全新的在 python 中 我试图对 python 中的一组文件运行命令 该命令需要源文件和目标文件 我实际上使用的是 imagemagickconvert如下例所示 我可以提供源目录和目标目录 但是我不知道如何轻松保留从源目录
  • 为什么允许使用子类的构造函数实例化父类对象?

    考虑以下 public class parent int x parent x 5 public class child extends parent int y child super y 10 public static void ma
  • Android Rss 图片问题

    大家好 我对 Android 开发比较陌生 正在为新闻网站创建 RSS 阅读器 我遇到的问题是我想要获取图像的 rss feed 的网站的类型为 我为 android 上的代码所做的是 2 个类 RssItem 和 RssItem Disp
  • 浏览器选项卡之间的通信

    我有一个 HTML 页面 文件主要 html 使用 JavaScript 在同一域中打开一个新选项卡window open 新标签页 html method 在新选项卡中 用户可以通过单击按钮来结束其活动 此时 我想向开启者窗口发送一条消息
  • php/mysql账户激活

    我的新网站中的所有内容都工作正常 除了我无法让这段代码工作 query mysql query SELECT FROM members WHERE useremail useremail row mysql fetch assoc quer
  • 将二进制编码为音频 python 或 C

    使用C或Python 首选Python 我如何将二进制文件编码为音频 然后通过耳机插孔输出 以及如何使用麦克风插孔的输入将音频解码回二进制 到目前为止我已经学会了如何使用 python 将文本文件转换为二进制文件 这与 RTTY 通信类似
  • 在 WinCrypt 中使用 CertCreateCertificateContext 时遇到 ASN1 错误标记值

    我在这里做错了什么 创建证书上下文时 我不断收到错误 0x8009310b 满足 ASN1 错误标记值 我知道我正在测试的证书很好 我使用 DER Base 64 和 P7B 格式从中间存储中导出它 三种情况都失败 int tmain in
  • 在 UIImageView 中对 UIImage 进行向上和向下动画(就像悬停一样)循环

    您好 我有一个图像 我想上下移动 向上 10 像素和向下 10 像素 以便我的图像看起来悬停 我怎样才能用简单的动画来做到这一点非常感谢 您可以使用核心动画来对视图层的位置进行动画处理 如果您将动画配置为additive您不必费心计算新的绝
  • 如何将开发人员工具窗口恢复到正常配置?

    我有 Edge 95 0 1020 53 在 Win 10 Pro 21H1 中 我不是技术人员 没有什么具体原因 我打开了开发者工具 大约有 10 年没有打开过 打开后 我看到了我见过很多次的配置 使用整个窗口四分之三的父网页位于左侧 这
  • 在 Swashbuckle 中启用 Oauth2 客户端凭据流

    我使用 IdentityServer3 通过客户端凭据授予来保护 Web API 对于文档 我使用 Swashbuckle 但无法弄清楚如何在 SwaggerConfig 中为客户端凭据 应用程序 流程启用 Oauth2 任何帮助 将不胜感
  • Winforms/C#:在两次运行之间存储/检索(保留)文本框的内容

    有没有一种最简单的方法来简单地告诉 Winforms 主要是 TextBoxes 保留其所有内容G 到一个文件 而无需我循环遍历所有控件 我在 WPF 应用程序中看到了这一点 但我不知道 而且 Google 没有发现任何内容 是否有开箱即用
  • 检查python中目录的权限

    我想要一个给定目录的python程序 它将返回该目录中具有775的所有目录 rwxrwxr x 权限 thanks 这两个答案都不会重复 尽管尚不完全清楚这就是OP想要的 这是一种递归方法 未经测试 但您明白了 import os impo
  • 在 tkinter 中,有没有办法改变重叠画布的绘制堆栈顺序?

    问题 使用 Python 的 tkinter 我尝试通过扩展来创建自定义按钮和其他小部件画布小部件 http effbot org tkinterbook canvas htm when to use 当用户与它们交互时 如何更改在顶部绘制