如何在矩形上方而不是下方写入文本?

How to write text on top of rectangle instead of below?

我正在尝试创建一个顶部带有文本的矩形,但文本显示在矩形下方。

如何让文字到最前层?

到目前为止我的代码:

from turtle import Turtle


class Rectangle(Turtle):
    def __init__(self, x, y, width, height, color='white'):
        super().__init__()
        self.penup()
        self.goto(x, y)
        self.color(color)
        self.shape('square')
        self.shapesize(stretch_wid=(height / 20), stretch_len=(width / 20))

class Writer(Turtle):
    def __init__(self, x, y):
        super().__init__()
        self.penup()
        self.goto(x, y)
        self.hideturtle()

    def writetext(self, text, font="Arial", size=8, textType="normal", color="black", x=None, y=None):
        if x is None:
            x = self.xcor()
        if y is None:
            y = self.ycor()
        self.goto(x, y)
        self.color(color)
        self.write(text, move=False, align="center", font=(font, size, textType))

class Button(Rectangle):
    def __init__(self, position, width, height, text, onclick, color="gray"):
        position = list(position)
        super().__init__(position[0], position[1], width, height, color)
        writer = Writer(position[0], position[1])
        writer.writetext(text, color="white")
        self.goto(position[0], position[1])
        self.color(color)
        self.onclick(onclick)


def start_game(_arg1=None, _arg2=None):  # requires arguments since Python turtle module passes two in when calling it using onclick
    print('game started')

Button((0, 0), 50, 20, 'click me to start the game', start_game)

我已经在 google 上搜索了半个多小时,但找不到任何内容

我认为该设计存在一些根本性缺陷,原因是 subclassing Turtle

问题是 Button 绘图发生在写入文本的构造函数之外。绘图函数由海龟库自动调用。无论您是否挂钩到 Turtle 的 classes 中,由于这个原因,构造函数通常不是绘制内容的理想场所。我没有看到用 subclassing.

从两个单独的海龟中制作 Button 的干净方法

一个快速(但很差)的修复方法是覆盖 turtle 调用以更新对象的内部方法,这样您的按钮就可以在 after super() 调用后注入文本绘制矩形(您也可以尝试使用 _drawturtle 连接到绘图中):

class Button(Rectangle):
    # ....

    def _update(self):
        super()._update()
        Writer(*self.position()).writetext("foobar", color="white")

但是由于前导 _ 表示一个私有的内部方法,这是在绕过 turtle API -- 不是一个好主意。

第二次尝试是使用 turtle.tracer(0)take control of the update loop manually 禁用内部更新循环,但这似乎违背了 subclassing Turtle 的目的,这就是您希望事情自动“正常工作”。

不过,这里还有一个更深层次的问题,那就是,一旦您在解决方法中将文本置于按钮顶部(如上所示),文本块下方的矩形将无法检测到点击。

在反复尝试之后,我想出的最佳替代方案是创建一个带有文本 pre-rendered 的图像,或者使用全局点击侦听器并使用坐标来确定是否单击发生在按钮上。以下代码不可重用,但它是一个概念证明,您可以通过参数化所有内容抽象为函数或 class:

import turtle
from turtle import Turtle


def handle_btn_click(x, y):
    if (x > -btn_size and y > -btn_size / 2 and 
            x < btn_size and y < btn_size / 2):
        print("game started")
        turtle.tracer(1)
        turtle.clearscreen()
        turtle.bye()

turtle.tracer(0)
r = Turtle(shape="square")
btn_size = 80
r.shapesize(btn_size // 20, btn_size // 10)
r.color("black")
turtle.update()
t = Turtle()
t.color("white")
t.ht()
text = "click me to start the game"
t.write(text, move=False, align="center", font=("Arial", 8, "normal"))
turtle.Screen().onclick(handle_btn_click)
turtle.mainloop()

最后一点,如果您只添加一个按钮,我建议保持简单和必要。 class 结构对于大多数 turtle 应用程序来说通常是过大的,而且大型参数列表对于仅处理单个实例来说是一种痛苦。

按钮下方显示的文本似乎是在您编写文本后调用 Button class 的任何方法时发生的。 试试下面的代码:

class Button(Rectangle):
    def __init__(self, position, width, height, text, onclick, color="gray"):
        #...
        writer.writetext(text, color="red")
        self.goto(position[0], position[1])
        self.color(color)
        self.onclick(onclick)
        writer.writetext("abc", color="blue")

如果稍微延迟设置 turtle.tracer,您实际上可以看到先创建灰色按钮,然后是灰色按钮上的红色文本,然后灰色按钮由三个 self. 方法,然后在所有内容之上写上蓝色文本“abc”。

仍然,如 , the text will block the button from being clicked. Please refer to 中提到的替代解决方案。