在Tkinter中沿斜线绘制矩形

0 投票
1 回答
51 浏览
提问于 2025-04-14 18:20

我有一个大项目,主要是展示物体的运动。我需要根据不同的形状进行绘制,但这个任务对我来说有点棘手。我花了很多天时间想要实现它,但始终没能正确绘制出来。如果有人能给我一个小示例,我就能自己完成剩下的部分。

我有一条线,两个端点分别是(x1,y1)(x2,y2),这四个参数都是可以动态变化的,但有个条件是y2总是大于y1。换句话说,这条线的端点总是指向下方。我需要在这条线上的某个位置滑动一个给定宽度高度的矩形。滑动的位置由用户指定,我们称之为位置。位置0是矩形的左上角与(x1,y1)接触的地方。上面我画了我所描述的内容,总共有7个参数。

在这里输入图片描述

滑动的矩形必须始终位于绘制的线的右侧。

在这里输入图片描述

总的来说,可能会有3种情况。上面展示了其中的2种,我没有画出垂直线的情况(即x1=x2),因为那种情况很容易想象出来。

如果有人能告诉我如何在Tkinter中实现这个,我将非常感激。

提前谢谢大家!

1 个回答

1

下面的代码块实现了我上面提到的功能。

import tkinter as tk
import math


def draw_line_and_rectangle():
    # Clear the canvas
    canvas.delete("all")

    # Get user inputs for line coordinates
    x1 = float(entry_x1.get())
    y1 = float(entry_y1.get())
    x2 = float(entry_x2.get())
    y2 = float(entry_y2.get())

    # Ensure y2 is greater than y1
    if y2 < y1:
        x1, y1, x2, y2 = x2, y2, x1, y1

    # Draw the line
    canvas.create_line(x1, y1, x2, y2)

    # Get user inputs for rectangle dimensions and position
    width = float(entry_width.get())
    height = float(entry_height.get())
    position = float(entry_position.get())

    # Calculate the angle of the line
    angle_rad = math.atan2(y2 - y1, x2 - x1)

    # Calculate the length of the line
    length = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)

    # Calculate the position of the rectangle's left corner along the line
    dx = position * length

    # Calculate the coordinates of the rectangle's vertices
    rect_angle_rad = angle_rad + math.pi / 2
    rect_top_left_x = x1 - dx * math.cos(angle_rad)
    rect_top_left_y = y1 - dx * math.sin(angle_rad)
    rect_top_right_x = rect_top_left_x + width * math.cos(angle_rad)
    rect_top_right_y = rect_top_left_y + width * math.sin(angle_rad)
    rect_bottom_left_x = rect_top_left_x + height * math.cos(rect_angle_rad)
    rect_bottom_left_y = rect_top_left_y + height * math.sin(rect_angle_rad)
    rect_bottom_right_x = rect_bottom_left_x + width * math.cos(angle_rad)
    rect_bottom_right_y = rect_bottom_left_y + width * math.sin(angle_rad)

    # Calculate the mirrored coordinates of the rectangle
    mirrored_rect_top_left_x = 2 * x1 - rect_top_left_x
    mirrored_rect_top_left_y = 2 * y1 - rect_top_left_y
    mirrored_rect_top_right_x = 2 * x1 - rect_top_right_x
    mirrored_rect_top_right_y = 2 * y1 - rect_top_right_y
    mirrored_rect_bottom_left_x = 2 * x1 - rect_bottom_left_x
    mirrored_rect_bottom_left_y = 2 * y1 - rect_bottom_left_y
    mirrored_rect_bottom_right_x = 2 * x1 - rect_bottom_right_x
    mirrored_rect_bottom_right_y = 2 * y1 - rect_bottom_right_y

    # Draw the mirrored rectangle
    canvas.create_polygon(mirrored_rect_top_left_x, mirrored_rect_top_left_y, mirrored_rect_top_right_x,
                          mirrored_rect_top_right_y,
                          mirrored_rect_bottom_right_x, mirrored_rect_bottom_right_y, mirrored_rect_bottom_left_x,
                          mirrored_rect_bottom_left_y, fill='red')


# Create the main window
root = tk.Tk()
root.geometry("600x600")
root.title("Draw Line and Rectangle")

# Create a canvas
canvas = tk.Canvas(root, width=500, height=500, bg='white')
canvas.grid(row=0, column=0, columnspan=2)

# Entry widgets for line coordinates
label_x1 = tk.Label(root, text="X1:")
label_x1.grid(row=1, column=0)
entry_x1_var = tk.StringVar()
entry_x1_var.set("50")  # Default value
entry_x1 = tk.Entry(root, textvariable=entry_x1_var)
entry_x1.grid(row=1, column=1)

label_y1 = tk.Label(root, text="Y1:")
label_y1.grid(row=2, column=0)
entry_y1_var = tk.StringVar()
entry_y1_var.set("50")  # Default value
entry_y1 = tk.Entry(root, textvariable=entry_y1_var)
entry_y1.grid(row=2, column=1)

label_x2 = tk.Label(root, text="X2:")
label_x2.grid(row=3, column=0)
entry_x2_var = tk.StringVar()
entry_x2_var.set("350")  # Default value
entry_x2 = tk.Entry(root, textvariable=entry_x2_var)
entry_x2.grid(row=3, column=1)

label_y2 = tk.Label(root, text="Y2:")
label_y2.grid(row=4, column=0)
entry_y2_var = tk.StringVar()
entry_y2_var.set("350")  # Default value
entry_y2 = tk.Entry(root, textvariable=entry_y2_var)
entry_y2.grid(row=4, column=1)

# Entry widgets for rectangle dimensions and position
label_width = tk.Label(root, text="Rectangle Width:")
label_width.grid(row=5, column=0)
entry_width_var = tk.StringVar()
entry_width_var.set("60")  # Default value
entry_width = tk.Entry(root, textvariable=entry_width_var)
entry_width.grid(row=5, column=1)

label_height = tk.Label(root, text="Rectangle Height:")
label_height.grid(row=6, column=0)
entry_height_var = tk.StringVar()
entry_height_var.set("30")  # Default value
entry_height = tk.Entry(root, textvariable=entry_height_var)
entry_height.grid(row=6, column=1)

label_position = tk.Label(root, text="Position:")
label_position.grid(row=7, column=0)
entry_position_var = tk.StringVar()
entry_position_var.set("0.3")  # Default value
entry_position = tk.Entry(root, textvariable=entry_position_var)
entry_position.grid(row=7, column=1)

# Button to draw the line and rectangle
button_draw = tk.Button(root, text="Draw Line and Rectangle", command=draw_line_and_rectangle)
button_draw.grid(row=8, column=0, columnspan=2)

root.mainloop()

撰写回答