Home > Enterprise >  QTreeView item's editor position problem?
QTreeView item's editor position problem?

Time:07-20

I have a QTreeView widget in which I have set indentation to 0 with QTreeView::setIndentation(0), but when editing an item, the editor still appears at the indentation level of the default indented behaviour: enter image description here

I have tried changing the editor position with a QStyledItemDelegate::updateEditorGeometry's method, but it seems that there is a limit to where I can move the editor horizontally, as I cannot move it to a negative offset, past the x == 0 position, like for example QRect(-50, 0, 100, 30).

Any ideas would be greatly appreciated, thanks.

P.S.: Here is an attempt of a minimal-reproducible-example, but this has another bug: the editor widget does not display when the geometry of the widget in drawRow is changed! The editor works when typing and pressing enter, it's just not displayed! I'll try to figure out what's the difference between my example in the image above and this code.

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sip


class MyTreeWidget(QTreeWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        
        self.setIndentation(0)
        self.setMouseTracking(True)
        self.setUniformRowHeights(True)
        self.setExpandsOnDoubleClick(False)
        self.setColumnCount(1)
        self.setHeaderLabels(["Items"])
        self.setHeaderHidden(True)
        self.header().setVisible(False)
        self.header().setStretchLastSection(False)
        self.header().setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
        
        self.add_items()
        self.itemClicked.connect(self.click)
    
    def click(self, item, column):
        item.setFlags(
            Qt.ItemFlag.ItemIsEditable |
            Qt.ItemFlag.ItemIsEnabled |
            Qt.ItemFlag.ItemIsSelectable
        )
        index = self.indexFromItem(item, 0)
        self.edit(index)
    
    def drawRow(self, painter, option, index):
        model = self.model()
        row = index.row()
        column = index.column()
        item = self.itemFromIndex(index)
        widget = self.itemWidget(item, 0)
        if widget is not None:
            geo = QRect(widget.geometry())
            geo.setX(geo.x()   50)
            widget.setGeometry(geo) # <- This line causes the editor's horizontal offset

        super().drawRow(painter, option, index)
    
    def add_items(self):
        items = [
            'Cookie dough',
            'Hummus',
            'Spaghetti',
            'Dal makhani',
            'Chocolate whipped cream'
        ]

        parent = None
        for item in items:
            new_item = QTreeWidgetItem(None)
            if parent is not None:
                new_item = QTreeWidgetItem(parent)
            else:
                self.addTopLevelItem(new_item)
            new_item.setText(0, item)
            new_item.setExpanded(True)
            parent = new_item
        
        def edit_last_item(*args):
            new_item.setFlags(
                Qt.ItemFlag.ItemIsEditable |
                Qt.ItemFlag.ItemIsEnabled |
                Qt.ItemFlag.ItemIsSelectable
            )
            index = self.indexFromItem(new_item, 0)
            self.edit(index)
            print("Editing")
        
        QTimer.singleShot(1000, edit_last_item)


class Window(QWidget):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        layout.addWidget(MyTreeWidget())


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

CodePudding user response:

In trying to create a minimal reproducible example as @Parisa.H.R mentioned in the comment, I discovered that in the drawRow method in the QTreeView/QTreeWidget there is some code that adjusts the geometry of item widgets, like so (Python/PyQt example):

class MyTreeView(QTreeView):

    def drawRow(self, painter, option, index):
        model = self.model()
        row = index.row()
        column = index.column()
        item = self.itemFromIndex(index)
        widget = self.itemWidget(item, 0)
        
        geo = ... # <- Code that calculates new geometry
        widget.setGeometry(geo) # <- This line causes the editor's horizontal offset
        
        super().drawRow(painter, option, index)

which is what causes the editor widget to be moved horizontally to the right.

Thanks @Parisa.H.R

  • Related