You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求Python实现拖拽填空交互功能的技术支持

用Python实现拖拽填空功能

要实现类似的单词拖拽填空功能,用Python自带的Tkinter库就能搞定,下面是一套可直接运行的实现方案:

核心逻辑

  • 把可选单词做成可拖拽的标签,绑定鼠标按下、拖动、释放事件
  • 填空区域用文本框展示带占位符的内容,当单词拖到填空位置时,替换占位符
  • 通过鼠标坐标判断拖拽释放时是否命中目标填空区域

完整代码实现

import tkinter as tk
from tkinter import ttk

class DragFillApp:
    def __init__(self, root):
        self.root = root
        self.root.title("拖拽填空练习")
        
        # 配置数据:填空文本和可选单词
        self.fill_text = "光合作用是植物利用*___*,将*___*和*___*转化为*___*,并释放*___*的过程。"
        self.words = ["阳光", "二氧化碳", "水", "有机物", "氧气"]
        
        # 初始化拖拽相关变量
        self.dragged_label = None
        self.start_x = 0
        self.start_y = 0
        
        # 创建界面组件
        self.create_widgets()
        
    def create_widgets(self):
        # 可选单词区域
        word_frame = ttk.Frame(self.root, padding="10")
        word_frame.pack(fill=tk.X, pady=5)
        
        for word in self.words:
            word_label = ttk.Label(word_frame, text=word, background="#e0f7fa", padding=(8,4), relief=tk.RAISED)
            word_label.pack(side=tk.LEFT, padx=5)
            # 绑定拖拽事件
            word_label.bind("<ButtonPress-1>", self.on_drag_start)
            word_label.bind("<B1-Motion>", self.on_drag_motion)
            word_label.bind("<ButtonRelease-1>", self.on_drag_release)
        
        # 填空文本区域
        self.text_box = tk.Text(self.root, width=60, height=5, font=("Arial", 12))
        self.text_box.pack(pady=10, padx=10)
        self.text_box.insert(tk.END, self.fill_text)
        self.text_box.config(state=tk.DISABLED)  # 设置为只读,防止手动修改
        
    def on_drag_start(self, event):
        # 记录被拖拽的标签和起始坐标
        self.dragged_label = event.widget
        self.start_x = event.x
        self.start_y = event.y
        
    def on_drag_motion(self, event):
        # 拖动时更新标签位置
        if self.dragged_label:
            x = self.dragged_label.winfo_x() + event.x - self.start_x
            y = self.dragged_label.winfo_y() + event.y - self.start_y
            self.dragged_label.place(x=x, y=y)
            
    def on_drag_release(self, event):
        if not self.dragged_label:
            return
        
        # 获取填空文本框的坐标范围
        text_box_x1 = self.text_box.winfo_rootx()
        text_box_y1 = self.text_box.winfo_rooty()
        text_box_x2 = text_box_x1 + self.text_box.winfo_width()
        text_box_y2 = text_box_y1 + self.text_box.winfo_height()
        
        # 获取释放时鼠标的屏幕坐标
        mouse_x = event.x_root
        mouse_y = event.y_root
        
        # 判断是否释放到文本框内
        if text_box_x1 <= mouse_x <= text_box_x2 and text_box_y1 <= mouse_y <= text_box_y2:
            # 转换为文本框内的坐标,找到光标位置
            rel_x = mouse_x - text_box_x1
            rel_y = mouse_y - text_box_y1
            index = self.text_box.index(f"@{rel_x},{rel_y}")
            
            # 找到最近的___占位符并替换
            self.text_box.config(state=tk.NORMAL)
            # 向前查找最近的___
            start_index = self.text_box.search("___", index, backwards=True)
            if start_index:
                end_index = f"{start_index}+3c"  # ___占3个字符
                self.text_box.delete(start_index, end_index)
                self.text_box.insert(start_index, self.dragged_label["text"])
            self.text_box.config(state=tk.DISABLED)
            
        # 把拖拽的标签放回原位置
        self.dragged_label.place_forget()
        self.dragged_label.pack(side=tk.LEFT, padx=5)
        self.dragged_label = None

if __name__ == "__main__":
    root = tk.Tk()
    app = DragFillApp(root)
    root.mainloop()

关键说明

  • 拖拽逻辑:通过ButtonPress-1记录起始状态,B1-Motion实时更新标签位置,ButtonRelease-1处理释放后的判断和替换
  • 填空替换:释放到文本框区域时,通过鼠标坐标找到对应位置,自动查找最近的___占位符并替换成拖拽的单词
  • 界面还原:拖拽结束后,不管是否命中填空区域,都会把单词标签放回原位置

内容的提问来源于stack exchange,提问作者user2345694

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:07:36