使用多个小部件委派

时间:2017-08-01 16:54:31

标签: qt delegates pyqt4 pyside pyqt5

基础模拟:

你好,

我有什么:

  • 包含我的项目的QAbstractListModel。
  • 包含单个小部件或委托的QListView。
  • QListView中的每个单独项目都需要在窗口小部件中有3个可编辑区域。

序:

我无法弄清楚如何使适当的分层小部件系统正常工作。如果您查看附件图片,则每个绿色框表示一个'项目'在我的模型中,以及在我的视图中对用户的一个不可见的项目,而在'小部件上的数据'每个绿色框内部是来自模型中该项目的数据并与之相关。

因此,如果有人在Widget 1中编辑QLineEdit1,我希望数据将在Widget1所涉及的项目的模型中更新。

问题:

我无法弄清楚如何在同一个委托中使用多个编辑器。如果我点击该项目(QLineEdit),索引当然会与主要小部件项目(绿色框)相关 - 我找不到任何要告诉我我已经点击了绘制了QLineEdit,所以如果我只是在createEditor中返回一个可编辑的QLineEdit,它只是一个通用的,放在任何地方,我需要弄清楚它与哪个小部件相关,这样我才能正确更新模型,并且还可以使编辑器绘制在我点击绘制的QLineEdit的位置。

我无法弄清楚如何让一个好的系统正常工作。我理解代表,我理解MVC,所有这一切都很好。我只是不知道我尝试做什么是可能的,或者我需要切换它并做其他事情。如果我确实需要尝试别的东西,我会很感激一些建议。

感谢。

这里有一些基本代码(现在没有单独的项目在小部件内部绘制,但是已经设置了基础):

import sys
from PySide import QtCore, QtGui


DELEGATE_DATA_ROLE = 37
DELEGATE_INDEX = 0


class ItemWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ItemWidget, self).__init__(parent=parent)
        self.main_layout = QtGui.QVBoxLayout()
        self.setLayout(self.main_layout)


class ItemDelegate(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(ItemDelegate, self).__init__(parent=parent)

    def sizeHint(self, option, index):
        return QtCore.QSize(80, 80)

    def createEditor(self, parent, option, index):
        editor = QtGui.QLineEdit(parent)
        editor.setFixedWidth(200)
        editor.setFixedHeight(50)
        return editor

    def setEditorData(self, editor, index):
        item_str = index.data(QtCore.Qt.DisplayRole)
        description = item_str['description']
        editor.setValue(description)

    def setEditorData(self, editor, index):
        print 'running setEditorData'
        if index.column() == DELEGATE_INDEX:
            print 'delegate'
        else:
            QtGui.QStyledItemDelegate(self, editor, index)


class ItemModel(QtCore.QAbstractListModel):
    def __init__(self, parent=None):
        super(ItemModel, self).__init__(parent=parent)
        self.items = [
            {'one': '1', 'name': 'one', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
            {'two': '2', 'name': 'two', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
            {'three': '3', 'name': 'three', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
            {'four': '4', 'name': 'four', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
            {'five': '5', 'name': 'five', 'thumbnail': 'charlie.jpg', 'description': 'aabb'},
            {'six': '6', 'name': 'six', 'thumbnail': 'charlie.jpg', 'description': 'aabb'}
        ]

    def rowCount(self, index):
        return len(self.items)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return None

        if role == QtCore.Qt.DisplayRole:
            if 0 <= index.row() < self.rowCount(index):
                return self.items[index.row()]
        if role == DELEGATE_DATA_ROLE:
            item = self.items[index.row()]
            return item, item.get('name'), item.get('description'), item.get('thumbnail')
        if role == QtCore.Qt.EditRole:
            return self.items[index.row()]

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if role == QtCore.Qt.EditRole:
            self.items[index.row()] = value
            self.dataChanged.emit(index, index)
            return True
        return False

    def flags(self, index):
        flag = super(ItemModel, self).flags(index)
        return flag | QtCore.Qt.ItemIsEditable


class ListView(QtGui.QListView):
    def __init__(self, parent=None):
        super(ListView, self).__init__(parent=parent)


class TestUI(QtGui.QDialog):
    def __init__(self, parent=None):
        super(TestUI, self).__init__(parent)
        self.main_layout = QtGui.QVBoxLayout()
        self.resize(700, 500)

        self.view = ListView()
        self.item_delegate = ItemDelegate()
        self.view.setItemDelegate(self.item_delegate)

        self.model = ItemModel()
        self.view.setModel(self.model)

        self.item_widget = ItemWidget()

        self.setLayout(self.main_layout)
        self.main_layout.addWidget(self.view)
        self.main_layout.addWidget(self.item_widget)


def start():
    app = QtGui.QApplication(sys.argv)
    ui = TestUI()
    ui.show()
    ui.setWindowState(QtCore.Qt.WindowActive)
    ui.raise_()
    app.exec_()


if __name__ == '__main__':
    start()

1 个答案:

答案 0 :(得分:0)

您的代码仅定义编辑器-即Qt在编辑项目时显示的内容。您需要提供一个绘画方法,然后Qt会调用它来绘制每个项目。

下面是一个示例(在C ++中),在该项目的右侧边缘绘制了一个三点按钮:

void ColorDelegate::paint(
    QPainter * a_Painter,
    const QStyleOptionViewItem & a_Option,
    const QModelIndex & a_Index
) const
{
    // Draw the button:
    QStyleOptionButton button;
    button.rect = buttonRectFromItemRect(a_Option.rect);
    button.text = "...";
    button.state = QStyle::State_Enabled;
    QApplication::style()->drawControl(QStyle::CE_PushButton, &button, a_Painter);

    // Draw the text, using the original delegate:
    QStyleOptionViewItem txt(a_Option);
    txt.rect.setWidth(txt.rect.width() - txt.rect.height() - 1);
    Super::paint(a_Painter, txt, a_Index);
}

(取自https://github.com/madmaxoft/SkauTan/blob/a40b94d8646c215ddde3efe422c466ca8b15cb88/src/UI/ColorDelegate.cpp#L20-L37