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

如何修复Flet中使用GestureDetector时的「控件需先添加到页面」错误

Flet开发将棋游戏拖拽触发AssertionError问题

我用Flet开发将棋(象棋变体)游戏,为实现棋子拖拽功能参考了Flet文档中的Solitaire教程。添加move_on_top函数后,原本正常的拖拽操作开始随机触发AssertionError,错误信息为**"Control must be added to the page first."**,拖拽功能随之失效。

我推测问题出在move_on_top函数移除并重新添加控件后的更新操作,但无法理解为何重新添加控件后仍会报错。以下是报错堆栈信息:

Future exception was never retrieved
future: <Future finished exception=AssertionError('Control must be added to the page first.')>
Traceback (most recent call last):
  File "C:\Users\andyp\AppData\Local\Programs\Python\Python312\Lib\concurrent\futures\thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andyp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flet_core\page.py", line 950, in wrapper
    handler(*args)
  File "c:\limbaksa\janggi-v2\janggiBoard.py", line 22, in drag
    e.control.update()
  File "C:\Users\andyp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flet_core\control.py", line 314, in update
    assert self.__page, "Control must be added to the page first."
           ^^^^^^^^^^^
AssertionError: Control must be added to the page first.

以下是简化后的代码:

import flet as ft
import janggibase

def move_on_top(piece,controls):
    controls.remove(piece)
    controls.append(piece)
    piece.board.update()

def start_drag(e:ft.DragStartEvent):
    move_on_top(e.control,e.control.board.controls)
    e.control.board.move_start_top=e.control.top
    e.control.board.move_start_left=e.control.left

def bounce_back(board,piece):
    piece.top=board.move_start_top
    piece.left=board.move_start_left
    board.update()

def drag(e: ft.DragUpdateEvent):
   e.control.top = max(0, e.control.top + e.delta_y)
   e.control.left = max(0, e.control.left + e.delta_x)
   e.control.update()

def drop(e:ft.DragEndEvent):
    for slot in e.control.board.slots:
        if (
            abs(e.control.top - slot.top) < 20
            and abs(e.control.left - slot.left) < 20
        ):
            place(e.control, slot)
            break
    else:
        bounce_back(e.control.board,e.control)
    e.control.update()

def place(piece,slot):
        piece.top=slot.top
        piece.left=slot.left
        piece.board.update()


class janggiPiece(ft.GestureDetector):
    def __init__(self, piece: janggibase.Piece, board: "janggiBoard"):
        super().__init__()
        self.piece=piece
        self.board=board
        self.mouse_cursor=ft.MouseCursor.MOVE
        self.drag_interval=5
        self.on_pan_start=start_drag
        self.on_pan_update=drag
        self.on_pan_end=drop
        self.left = 60 * (piece.location // 10)
        self.top = 60 * (9 - piece.location % 10)
        self.content=ft.Container(
            width=60,
            height=60,
            border_radius=ft.border_radius.all(5),
            content=ft.Image(f"img/{str(piece).upper()}{piece.color}.png"),
        )
    



class Slot(ft.Container):
    def __init__(self, top, left):
        super().__init__()
        self.ontop = None
        self.width = 60
        self.height = 60
        self.left = left
        self.top = top


class janggiBoard(ft.Stack):
    def __init__(self, board: janggibase.Board):
        super().__init__()
        self.board = board
        self.slots = []
        self.controls = []
        self.width = 540
        self.height = 600
        for i in range(90):
            self.slots.append(Slot(60 * (9 - i % 10), 60 * (i // 10)))
        self.controls.extend(self.slots)
        self.piecelist = []
        for color in range(2):
            for piece in self.board.pieces[color]:
                self.piecelist.append(janggiPiece(piece, self))
        self.controls.extend(self.piecelist)
        self.move_start_top=None
        self.move_start_left=None


if __name__ == "__main__":
    def main(page):
        page.add(janggiBoard(janggibase.Board(15)))

    ft.app(target=main)

我还尝试将move_on_top函数修改为交换控件位置而非移除再添加,但仍出现相同错误:

def move_on_top(piece,controls:list):
    i=controls.index(piece)
    controls[i],controls[-1]=controls[-1],controls[i]
    piece.board.update()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:00:06