Реализация делегата для переноса слов в QTreeView (Qt/PySide/PyQt)?

У меня есть древовидное представление с пользовательским делегатом, к которому я пытаюсь добавить функциональность переноса слов. Перенос слов работает нормально, но sizeHint() кажется, не работает, поэтому, когда текст переносится, соответствующая строка не расширяется, чтобы включить его.

Я думал, что позаботился об этом в sizeHint() вернувшись document.size().height(),

def sizeHint(self, option, index):
    text = index.model().data(index)
    document = QtGui.QTextDocument()
    document.setHtml(text) 
    document.setTextWidth(option.rect.width())  
    return QtCore.QSize(document.idealWidth(), document.size().height())    

Тем не менее, когда я распечатаю document.size().height() это то же самое для каждого элемента.

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

WTF

Как видите, текст в каждой строке не выровнен должным образом в дереве.

Похожие посты

Подобные проблемы возникали и раньше, но решения моей проблемы не было (люди обычно говорят, что они будут реализованы заново) sizeHint()и вот что я пытаюсь)

QTreeWidget устанавливает высоту каждой строки в зависимости от содержимого

QTreeView пользовательская высота строки отдельных строк

http://www.qtcentre.org/threads/1289-QT4-QTreeView-and-rows-with-multiple-lines

SSCCE

import sys
from PySide import QtGui, QtCore

class SimpleTree(QtGui.QTreeView):
    def __init__(self, parent = None):    
        QtGui.QTreeView.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setGeometry(500,200, 400, 300)  
        self.setUniformRowHeights(False) #optimize: but for word wrap, we don't want this!
        print "uniform heights in tree?", self.uniformRowHeights()
        self.model = QtGui.QStandardItemModel()
        self.model.setHorizontalHeaderLabels(['Task', 'Description'])
        self.setModel(self.model)
        self.rootItem = self.model.invisibleRootItem()
        item0 = [QtGui.QStandardItem('Sneeze'), QtGui.QStandardItem('You have been blocked up')]
        item00 = [QtGui.QStandardItem('Tickle nose, this is a very long entry. Row should resize.'), QtGui.QStandardItem('Key first step')]
        item1 = [QtGui.QStandardItem('<b>Get a job</b>'), QtGui.QStandardItem('Do not blow it')]
        self.rootItem.appendRow(item0)
        item0[0].appendRow(item00) 
        self.rootItem.appendRow(item1)
        self.setColumnWidth(0,150)
        self.expandAll()
        self.setWordWrap(True)
        self.setItemDelegate(ItemWordWrap(self))

class ItemWordWrap(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None):
        QtGui.QStyledItemDelegate.__init__(self, parent)
        self.parent = parent
    def paint(self, painter, option, index):
        text = index.model().data(index) 
        document = QtGui.QTextDocument() # #print "dir(document)", dir(document)
        document.setHtml(text)       
        document.setTextWidth(option.rect.width())  #keeps text from spilling over into adjacent rect
        painter.save() 
        painter.translate(option.rect.x(), option.rect.y()) 
        document.drawContents(painter)  #draw the document with the painter
        painter.restore()
    def sizeHint(self, option, index):
        #Size should depend on number of lines wrapped
        text = index.model().data(index)
        document = QtGui.QTextDocument()
        document.setHtml(text) 
        document.setTextWidth(option.rect.width())  
        return QtCore.QSize(document.idealWidth() + 10,  document.size().height())       

def main():
    app = QtGui.QApplication(sys.argv)
    myTree = SimpleTree()
    myTree.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

1 ответ

Решение

Проблема, как представляется, связана с тем, что значение для option.rect.width() перешел в QStyledItemDelegate.sizeHint() это -1. Это явно фальшивка!

Я решил это, сохранив ширину в модели изнутри paint() метод и доступ к этому из sizeHint(),

Так в вашем paint() метод добавить строку:

index.model().setData(index, option.rect.width(), QtCore.Qt.UserRole+1)

и в вашем sizeHint() метод, заменить document.setTextWidth(option.rect.width()) с:

width = index.model().data(index, QtCore.Qt.UserRole+1)
if not width:
    width = 20
document.setTextWidth(width)
Другие вопросы по тегам