簡體   English   中英

PySide QlistView 拖放

[英]PySide QlistView drag and drop

我正在嘗試使用 PySide6 實現從一個 QListView 到另一個 QListView 的簡單拖放功能。

這是用戶界面:

import sys

import qdarktheme
from PySide6.QtWidgets import QApplication, QWidget, QMainWindow, QVBoxLayout, QListView

from models.pipeline_model import PipelineListModel
from models.toolbox_model import ToolboxListModel, MyModel


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        toolbox_list_model = ToolboxListModel()
        pipeline_list_model = PipelineListModel()

        for i in range(10):
            toolbox_list_model.toolbox_items.append(MyModel(x=i))

        toolbox_list_view = QListView()
        toolbox_list_view.setDragEnabled(True)
        toolbox_list_view.setModel(toolbox_list_model)

        pipeline_list_view = QListView()
        pipeline_list_view.setAcceptDrops(True)
        pipeline_list_view.setModel(pipeline_list_model)

        vbox = QVBoxLayout()
        vbox.addWidget(toolbox_list_view)
        vbox.addWidget(pipeline_list_view)

        main_widget = QWidget()
        main_widget.setLayout(vbox)
        self.setCentralWidget(main_widget)


if __name__ == '__main__':
    app = QApplication()
    app.setStyleSheet(qdarktheme.load_stylesheet())
    main_window = MainWindow()

    main_window.show()

    # Start the event loop.
    sys.exit(app.exec())

工具箱列表模型(應從中拖動項目):

from typing import Union, Any

import PySide6
from PySide6 import QtCore
from PySide6.QtCore import Qt

from models.model_data import MyModel


class ToolboxListModel(QtCore.QAbstractListModel):
    def __init__(self):
        super().__init__()
        self.toolbox_items: list[MyModel] = []

    def data(self, index: Union[PySide6.QtCore.QModelIndex, PySide6.QtCore.QPersistentModelIndex],
             role: int = ...) -> Any:
        if role == Qt.DisplayRole:
            model = self.toolbox_items[index.row()]
            return model.x

    def rowCount(self, parent: Union[PySide6.QtCore.QModelIndex, PySide6.QtCore.QPersistentModelIndex] = ...) -> int:
        return len(self.toolbox_items)

目標列表模型(應刪除工具箱項的位置):

from typing import Union, Any

import PySide6
from PySide6 import QtCore
from PySide6.QtCore import Qt

from models.model_data import MyModel


class PipelineListModel(QtCore.QAbstractListModel):
    def __init__(self):
        super().__init__()
        self.toolbox_items: list[MyModel] = []

    def data(self, index: Union[PySide6.QtCore.QModelIndex, PySide6.QtCore.QPersistentModelIndex],
             role: int = ...) -> Any:
        if role == Qt.DisplayRole:
            model = self.toolbox_items[index.row()]
            return model.x

    def rowCount(self, parent: Union[PySide6.QtCore.QModelIndex, PySide6.QtCore.QPersistentModelIndex] = ...) -> int:
        return len(self.toolbox_items)

最后是共享數據模型:

import dataclasses


@dataclasses.dataclass
class MyModel:
    x: int

即使將dragEnabled 設置為True 並且將接收器QListView 設置為接受放置,拖動操作甚至都不會開始。

我在這里做錯了什么? 如何正確進行 d'n'd 操作?

正如model 查看文檔(我強烈建議您完整閱讀)中解釋的那樣,您必須覆蓋flags() function,因為默認行為只會啟用和選擇項目。

在視圖上設置Drag標志只允許拖動操作,但只有 model 可以告訴哪些項目可以拖動。

如果要允許索引可拖動,還必須提供ItemIsDragEnabled標志:

class ToolboxListModel(QtCore.QAbstractListModel):
    def flags(self, index):
        flags = super().flags(index)
        if index.isValid():
            flags |= QtCore.Qt.ItemFlags.ItemIsDragEnabled
        return flags

然后,根據您希望在目標 model的行為,您可能需要覆蓋標志以接受對現有項目的拖放(以覆蓋項目),或實現其他功能,如有關子類化 QAbstractListModel的文檔中所示,因為它不支持默認情況下可調整大小的列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM