如何修复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
相关产品推荐
相关产品推荐

