【问题标题】:Implementing a delegate for wordwrap in a QTreeView (Qt/PySide/PyQt)?在 QTreeView (Qt/PySide/PyQt) 中实现自动换行的委托?
【发布时间】:2016-04-09 22:44:51
【问题描述】:

我有一个带有自定义委托的树视图,我正在尝试向其中添加自动换行功能。自动换行工作正常,但 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)只是为了检查事情是否合理,这棵树看起来就像被火箭筒射中的金鱼(也就是说,它是一团糟):

如您所见,每行中的文本在树中没有正确对齐。

类似帖子

以前也出现过类似的问题,但我的问题没有解决方案(人们通常说要重新实现sizeHint(),这就是我正在尝试的):

QTreeWidget set height of each row depending on content

QTreeView custom row height of individual rows

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()

【问题讨论】:

    标签: qt pyqt pyqt4 pyside


    【解决方案1】:

    问题似乎源于传递给QStyledItemDelegate.sizeHint()option.rect.width() 的值是-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)
    

    【讨论】:

    • 哇,不错的发现。我什至不认为这是错误的可能来源,它现在看起来很漂亮。太棒了。
    • 当我发现那个假宽度时,我很生气。在 C++ 中,你不能在 const 被感染的 paint() 方法中执行 setData(),所以我给了委托类一个 QTreeView 成员变量并执行了 treeView-&gt;model()-&gt;setData( index, option.rect.width(), WIDTH_ROLE );。你也可以const_cast&lt;QAbstractItemModel*&gt;( index.model() )-&gt;setData(...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    相关资源
    最近更新 更多