Вопрос

Я пытаюсь написать простой редактор недвижимости. У меня автоматически сгенерировал класс PYQT (Workzone в коде ниже), и мне нужно просмотреть / редактировать некоторые свойства свойства с PropertiodeDitor, с PropertyEdeDeDeLegate делегатом делегата, в котором используются пользовательские редакторы Kminitor, LineEditor и т. Д.

Основная идея состоит в том, что Workzone знает, какие свойства необходимо отредактировать и как, и Povalyeditor Parse Workzone, ищите такие свойства и заполните QTreewidget со своими значениями.

Но есть проблема: делегат не запускает редактирование двойного щелчка или «Enter» или Smth. Он добавляется в правый ряд, он рисует предмет, но это все. Кроме того, когда я переключал тип контейнера PropertyEditor в QtableWidget, делегат начал работать более правильным (но редактор окрашены в углу экрана, а не в таблице)!

Придавать И один дополнительный вопрос: есть ли способ добавить некоторые делегаты в строки без необходимости хранить экземпляры из них где-то еще (Self._Delegates в сценарии), это просто уродливо. Способ SetiteMDelegate принимает указатель на делегат, а в C ++ он получает владение на нем, но в Pyqt это не так ... рядом, например, такая проблема с setiTem, например.

Следующий скрипт иллюстрирует проблему:

# -*- coding: utf-8 -*-
#!/usr/bin/env python

from PyQt4 import QtCore, QtGui
import inspect


class LineEditor(QtGui.QLineEdit):


    def __init__(self, name = None, parent = None, slot = None):
        QtGui.QLineEdit.__init__(self, parent)
        self.textChanged.connect(slot)
        self.name = name

    @staticmethod
    def paintForDelegate(delegate, painter, option, index):
        QtGui.QItemDelegate.paint(delegate, painter, option, index)

    def get(self):
        return str(self.text())

    def set(self, val):
        self.setText(QtCore.QString.fromUtf8(val))

class ColorEditor(QtGui.QComboBox):


    def _populateList(self):
        for name in QtGui.QColor.colorNames():
            self.addItem(name)
            index = self.findText(name)
            self.setItemData(index, QtGui.QColor(name), QtCore.Qt.DecorationRole)

    def __init__(self, name = None, parent = None, slot = None):
        QtGui.QComboBox.__init__(self, parent)
        self._populateList()
        self.currentIndexChanged.connect(slot)
        self.name = QtCore.QString.fromUtf8(name)

    @staticmethod
    def paintForDelegate(delegate, painter, option, index):
        QtGui.QItemDelegate.paint(delegate, painter, option, index)

    def get(self):
        qColor = QtGui.QColor(self.itemData(self.currentIndex(), QtCore.Qt.DecorationRole))        
        color = ((qColor.blue() | (qColor.green() << 8)) | (qColor.red() << 16))
        return color

    def set(self, val):
        blue = (val & 255)
        green = ((val & 65280) >> 8)
        red = ((val & 16711680) >> 16)
        color = QtGui.QColor(red, green, blue)
        index = self.findData(color, QtCore.Qt.DecorationRole)
        self.setCurrentIndex(index) 

class PropertyEditorDelegate(QtGui.QItemDelegate):


    def __init__(self, object, propName, parent = None):
        QtGui.QItemDelegate.__init__(self, parent)
        self._object = object
        self._propName = propName

    def paint(self, painter, option, index):
        self._object.paintForDelegate(self._propName, self, painter, option, index)

    def createEditor(self, parent, option, index):
        return self._object.createEditor(self._propName)

    def setEditorData(self, editor, index):
        value = index.model().data(index, QtCore.Qt.EditRole)
        editor.set(value)

    def setModelData(self, editor, model, index):
        if index.column() == 0:
            model.setData(index, editor.name, QtCore.Qt.EditRole)
        else:
            model.setData(index, editor.get(), QtCore.Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)

class PropertyEditor(QtGui.QWidget):

    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)
        self._object = None
        self._delegates = []
        self._mainLayout = QtGui.QVBoxLayout()
        self._mainLayout.setContentsMargins(2, 2, 2, 2)
        self._mainLayout.setSpacing(2)
        self.setLayout(self._mainLayout)
        self._contents = QtGui.QTreeWidget()
        self._contents.setColumnCount(2)
        self._contents.currentItemChanged.connect(self.printCurrent)
        self._mainLayout.addWidget(self._contents)

    def printCurrent(self, curr, prev):
        print self._contents.currentIndex().row()
        print self._contents.currentIndex().column()
        print self._contents.itemDelegate(self._contents.currentIndex())._propName
        print self._contents.itemDelegate(self._contents.currentIndex())

    def object(self):
        return self._object

    def setObject(self, value):       
        self._object = value

        def isProperty(p):
            return isinstance(p, property)

        for (name, value) in inspect.getmembers(type(self._object), isProperty):
            if self._object.isEditable(name):
                item = QtGui.QTreeWidgetItem()
                item.setData(0, QtCore.Qt.EditRole, QtCore.QString.fromUtf8(self._object.getPropertyName(name)))
                item.setData(1, QtCore.Qt.EditRole, self._object.get(name))
                self._contents.addTopLevelItem(item)

                self._delegates.append(PropertyEditorDelegate(self._object, name, self._contents))
                index = self._contents.indexOfTopLevelItem(item)    
                self._contents.setItemDelegateForRow(index, self._delegates[index])

class WorkZone(object):


    def __init__(self):

        self._name = ''
        self.currentEditor = None
        self.red = 100
        self.green = 100
        self.blue = 100
        self._width = 1

    def _getColor(self):
        color = ((self.blue | (self.green << 8)) | (self.red << 16))
        return color

    def _setColor(self, color):
        self.blue = (color & 255)
        self.green = ((color & 65280) >> 8)
        self.red = ((color & 16711680) >> 16)

    color = property(_getColor, _setColor)

    def currentColorChanged(self, index):
        if self.currentEditor is not None:
            self.color = self.currentEditor.get()
        print self.color

    def currentNameChanged(self, newName):
        if self.currentEditor is not None:
            self.name = self.currentEditor.get()
        print self.name

    def createEditor(self, prop):
        if prop == 'color':
            self.currentEditor = ColorEditor('Color', None, self.currentColorChanged)
            self.currentEditor.set(self.color) 
            return self.currentEditor
        elif prop == 'name':
            self.currentEditor = LineEditor('Name', None, self.currentNameChanged) 
            self.currentEditor.set(self.name)
            return self.currentEditor
        else:
            return None

    def releaseEditor(self):
        self.currentEditor = None

    def isEditable(self, prop):
        if prop == 'color':
            return True
        elif prop == 'name':
            return True
        else:
            return False

    def set(self, prop, val):
        if prop == 'color':
            self.color = val
        elif prop == 'name':
            self.name = val

    def get(self, prop):
        if prop == 'color':
            return self.color
        elif prop == 'name':
            return self.name

    def getPropertyName(self, prop):
        if prop == 'color':
            return 'Color'
        elif prop == 'name':
            return 'Name'

    def paintForDelegate(self, prop, delegate, painter, option, index):
        if prop == 'color':
            ColorEditor.paintForDelegate(delegate, painter, option, index)
        elif prop == 'name':
            LineEditor.paintForDelegate(delegate, painter, option, index)

    def _setWidth(self, Width):
        self._width = Width

    def _getWidth(self):
        return self._width

    width = property(_getWidth, _setWidth)

    def _getName(self):
        return self._name

    def _setName(self, val):
        self._name = val

    name = property(_getName, _setName)



if __name__ == '__main__':

    import sys

    app = QtGui.QApplication(sys.argv)
    zone = WorkZone()
    zone.color = 0
    zone.width = 1
    propertyEditor = PropertyEditor()
    propertyEditor.setObject(zone)


    propertyEditor.show()
    sys.exit(app.exec_())
Это было полезно?

Решение

Я закончил обрабатывать двойной щелчок, чтобы установить для редактируемой, насильните элемент, чтобы редактировать режим с помощью редактирования (), а затем настроить его обратно. Сам делегат обрабатывает весь дисплей и редактирование.

# In __init__:
    self.tree.itemActivated.connect(self.onDoubleClick)


def onDoubleClick(self, item, index):
    """ 
    The logic will happen in the editor delegate. This is needed to let
    the delegate run by making this editable
    """        
    item.setFlags(QtCore.Qt.ItemIsSelectable |
                  QtCore.Qt.ItemIsEnabled |
                  QtCore.Qt.ItemIsEditable)            

    # Force the item in to edit mode so the delegate picks it up
    self.tree.editItem(item, index)

    # Set the item back to not editable. The delegate will still do its
    #    job, but the read-only state will already be set when done!
    item.setFlags(QtCore.Qt.ItemIsSelectable |
                  QtCore.Qt.ItemIsEnabled)

Первые SetFlags, вероятно, нужны только детализируемые для работы, но это чувствовало себя правильно.

Другие советы

На PS.

Из документации PYQT

QABSTRACTITEMVIEW.SETITEMDELEGE (SEA, QABSTRACTITEMDELEGE)

Устанавливает делегат элемента для этого представления и его модели для делегирования. Это полезно, если вы хотите полный контроль над редактированием и отображением элементов.

Любой существующий делегат будет удален, но не удален. QabstractiteMView. не принимает владение делегатом.

ПРЕДУПРЕЖДЕНИЕ. Вы не должны делиться один и тот же экземпляр делегата между просмотрами. Это может привести к неправильному или неразруситетному поведению редактирования, поскольку каждый вид, подключенный к данному делегату, может принимать сигнал CloseDitor () и попытаться получить доступ, изменять или закрыть редактор, который уже был закрыт.

Ответ прост, как всегда ..%) Флаги по умолчанию для QtreewidGetItem не включают QtCore.QT.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top