我正在尝试使用 flet 制作 janggi(国际象棋变体)游戏。我想对片段使用拖放操作,因此我按照 flet 文档中的 Solitaire 教程进行操作。当我尝试执行“move_on_top”部分时出现问题。在添加 move_on_top 代码之前,一切都按预期完美运行。我可以自由地移动这些碎片。但是,在我添加 move_on_top 函数后,它有时会起作用,但它也会随机导致 AssertionError,并且拖动不再起作用。
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.
我认为这与 move_on_top 函数有关。我认为当我在函数删除并将该片段重新附加到控件后尝试更新它们时,就会发生错误。但我不明白为什么会发生这种情况,因为该函数在删除它后将其添加回控件中。我的代码在这里,我尽可能地简化了它。有90个隐形槽位,棋子根据棋盘放置在槽位上。 janggibase.Board 包含有关棋盘的信息,例如棋盘上的棋子列表。 janggibase.Piece 包含有关该片段的信息,例如它的位置。我还将完整代码上传到[我的github](github.com/limbaksa/janggi-v2/)
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()
我在链接的存储库中查看了您的代码。 主要问题是,在您的辅助方法中,您更新
board
而不是更新 piece
。我对链接存储库中的代码进行了以下 2 项修改 (janggiBoard.py
),它再次工作了:
def bounce_back(board, piece):
# ...
piece.update()
def place(piece, slot):
# ...
piece.update()