QML视图间拖放时如何避免列表出现空白区域?
First, straight to the point: Using only reparenting (as in the basic Tiles example) won’t automatically make the list rearrange to fill the blank space. Here’s why, and how to fix it:
Why reparenting alone doesn’t work
In the default Tiles example, when you drag a tile from the list to the grid, you’re just changing the item’s parent from the list container to the grid container. However:
- If your list is a static container (like a
Columnwith hardcoded items) or aListView/Repeaterbound to a model that isn’t updated, the list doesn’t "know" the item is gone. It’ll keep the empty space where the tile was, because the model still includes the item (if using a model) or the container’s child list still has a placeholder (if static). - Even if the list detects the item is removed, most Qt Quick container components (like
Column,ListView) don’t automatically reflow their remaining items to fill gaps unless their underlying data source (the model) is modified.
The better approach: Use two separate models
To get automatic rearrangement in both the list and grid, you need to tie each view to its own model, and update those models when a drag-and-drop occurs:
- Define two models: One for the available tiles in the list (e.g., a
ListModel), another for the tiles placed in the grid. - On drag start: Keep track of which tile is being moved.
- On drop completion:
- Remove the tile’s data from the list’s model.
- Add that data to the grid’s model.
- The
ListViewwill automatically remove the delegate and shift remaining items up to fill the gap. - The
GridViewwill automatically add the new tile to its layout.
Conceptual code snippet
ListModel { id: listModel ListElement { text: "Button 1"; color: "red" } ListElement { text: "Button 2"; color: "blue" } } ListModel { id: gridModel } ListView { model: listModel delegate: TileDelegate { // Handle drag completion onDragFinished: { if (dropTarget === gridView) { listModel.remove(index); gridModel.append({ text: text, color: color }); } } } } GridView { id: gridView model: gridModel delegate: TileDelegate { /* Delegate styling and behavior */ } }
Can you make reparenting work?
Technically, you could manually adjust the positions of the remaining list items after reparenting, but this is error-prone and not recommended. You’d have to iterate over the list’s children, calculate their new positions, and animate them into place—this bypasses Qt Quick’s built-in layout management and creates unnecessary maintenance work. Using models is the idiomatic Qt Quick way to handle dynamic item lists and grids.
So to sum up: You need two separate models to get the automatic rearrangement behavior you want. Reparenting alone won’t trigger the list to fill the gap without manual intervention.
内容的提问来源于stack exchange,提问作者user4072916

