Как сделать отступ для данных расширяемой строки в QTreeView, PyQt5Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как сделать отступ для данных расширяемой строки в QTreeView, PyQt5

Сообщение Anonymous »

Это небольшой пример моего TableWidget:

Код: Выделить всё

from PyQt5.QtGui import QStandardItem, QStandardItemModel, QIcon

from PyQt5.QtWidgets import QVBoxLayout, QWidget, QStyledItemDelegate, QStyle, QTreeView, QApplication, \
QStyleOptionViewItem
from PyQt5.QtCore import Qt, QSize

leftArrow = "path\to\left-arrow.png"
downArrow = "path\to\down-arrow.png"

class GroupDelegate(QStyledItemDelegate):
def __init__(self, pic1=None, pic2=None, parent=None):
super().__init__(parent)
self._pic1 = QIcon(pic1)
self._pic2 = QIcon(pic2)

def initStyleOption(self, option, index):
option.state &= ~QStyle.State_Selected
super().initStyleOption(option, index)
if index.column() == index.model().columnCount() - 1 and not index.parent().isValid():
is_open = bool(option.state & QStyle.State_Open)
option.features |= QStyleOptionViewItem.HasDecoration
icon = self._pic2 if is_open else self._pic1
option.icon = icon
option.decorationSize = option.rect.size()

def sizeHint(self, option, index):
padding = 20

if index.data(Qt.UserRole + 1):
lines = index.data().count('\n') + 1
font_metrics = option.fontMetrics
line_height = font_metrics.lineSpacing()
return QSize(option.rect.width(), line_height * lines + padding)
return QSize(option.rect.width(), option.fontMetrics.height() + padding)

class GroupView(QTreeView):
def __init__(self, model, parent=None):
super().__init__(parent)
self.setIndentation(0)
self.clicked.connect(self.on_clicked)
self.setItemDelegate(GroupDelegate(pic1=leftArrow, pic2=downArrow, parent=self))
self.setModel(model)

def on_clicked(self, index):
if not index.parent().isValid():
parent_index = self.model().index(index.row(), 0)
self.setExpanded(parent_index, not self.isExpanded(parent_index))

class GroupModel(QStandardItemModel):
def __init__(self, parent=None):
super().__init__(parent)
headers = ["Column 1", "Column 2", "Column 3", ""]
self.setColumnCount(len(headers))
for i, header in enumerate(headers):
self.setHeaderData(i, Qt.Horizontal, header)

def add_group(self, row_data, additional_info):
parent_items = [QStandardItem(col_data) for col_data in row_data]
for item in parent_items:
item.setEditable(False)
self.appendRow(parent_items)

additional_info_item = QStandardItem(additional_info)
additional_info_item.setData(True, Qt.UserRole + 1)
additional_info_item.setEditable(False)

parent_items[0].appendRow([additional_info_item] + [QStandardItem("")] * (self.columnCount() - 1))
return parent_items[0].index()

class TableWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
layout = QVBoxLayout(self)
model = GroupModel(self)
tree_view = GroupView(model)
layout.addWidget(tree_view)

# Add sample data
model.add_group(["Parent Row 1", "Data 1", "Data 2"], "Additional info for Row 1")
model.add_group(["Parent Row 2", "Data 3", "Data 4"], "Additional info for Row 2")

# Span the additional info row across all columns
for row in range(model.rowCount()):
parent_index = model.index(row, 0)
additional_row = model.itemFromIndex(parent_index).rowCount() - 1
tree_view.setFirstColumnSpanned(additional_row, parent_index, True)

if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = TableWidget()
window.show()
window.resize(600, 400)
sys.exit(app.exec_())
Я хочу сделать отступ для данных в расширяемой строке. Когда я присваиваю self.setIndentation(0) значение выше 0, это отступ, но я также вижу стрелку слева, чего мне не хочется. Как вы можете видеть в коде, я поместил значки в последний столбец, чтобы стрелки располагались справа, поэтому исходная стрелка TreeView не нужна.
Мой виджет основан на об этом решении:
Как я могу создать таблицу, строки которой можно свернуть в категории в Qt?
Кроме того, я хочу сделать текст, который я помещаю в расширяемую строку, более темным фон и закругленные края, чтобы выглядеть лучше.
Я попробовал разместить на нем метку, но в результате текст вообще больше не был виден, возможно, я сделал это неправильно. p>
Надеюсь, что есть правильное решение моей проблемы.
Резюме:
Я хочу сделать отступ для текста в расширяемой строке (не видя исходной стрелки) из QTreeView) и сделайте фон светло-серым с закругленными краями.
РЕДАКТИРОВАТЬ:
Учитывая комментарии musicamante, это мое решение:

Код: Выделить всё

from PyQt5.QtGui import QStandardItem, QStandardItemModel, QIcon, QColor, QPainterPath
from PyQt5.QtWidgets import QVBoxLayout, QWidget, QStyledItemDelegate, QStyle, QTreeView, QApplication, \
QStyleOptionViewItem
from PyQt5.QtCore import Qt, QSize, QRectF

leftArrow = "path\to\left-arrow.png"
downArrow = "path\to\down-arrow.png"

class GroupDelegate(QStyledItemDelegate):
def __init__(self, pic1=None, pic2=None, parent=None):
super().__init__(parent)
self._pic1 = QIcon(pic1)
self._pic2 = QIcon(pic2)

def initStyleOption(self, option, index):
option.state &= ~QStyle.State_Selected
super().initStyleOption(option, index)
if index.column() == index.model().columnCount() - 1 and not index.parent().isValid():
is_open = bool(option.state &  QStyle.State_Open)
option.features |= QStyleOptionViewItem.HasDecoration
icon = self._pic2 if is_open else self._pic1
option.icon = icon
option.decorationSize = option.rect.size()

def sizeHint(self, option, index):
padding = 20

if index.data(Qt.UserRole + 1):
lines = index.data().count('\n') + 1
font_metrics = option.fontMetrics
line_height = font_metrics.lineSpacing()
return QSize(option.rect.width(), line_height * lines + padding)
return QSize(option.rect.width(), option.fontMetrics.height() + padding)

def paint(self, painter, option, index):
if index.data(Qt.UserRole + 1):
painter.save()

lightGrey = QColor(220, 220, 220)
painter.setBrush(lightGrey)
painter.setPen(Qt.NoPen)

rect = option.rect

rect.setLeft(option.rect.left())
rect.setRight(option.rect.right())

rect_f = QRectF(rect)

radius = 10
path = QPainterPath()
path.addRoundedRect(rect_f, radius, radius)
painter.fillPath(path, lightGrey)

painter.restore()

rect = option.rect
rect.setLeft(option.rect.left())
else:
super().paint(painter, option, index)

super().paint(painter, option, index)

class GroupView(QTreeView):
def __init__(self, model, parent=None):
super().__init__(parent)
self.setIndentation(20)
self.setRootIsDecorated(False)
self.clicked.connect(self.on_clicked)
self.setItemDelegate(GroupDelegate(pic1=leftArrow, pic2=downArrow, parent=self))
self.setModel(model)

def on_clicked(self, index):
if not index.parent().isValid():
parent_index = self.model().index(index.row(), 0)
self.setExpanded(parent_index, not self.isExpanded(parent_index))

class GroupModel(QStandardItemModel):
def __init__(self, parent=None):
super().__init__(parent)
headers = ["Column 1", "Column 2", "Column 3", ""]
self.setColumnCount(len(headers))
for i, header in enumerate(headers):
self.setHeaderData(i, Qt.Horizontal, header)

def add_group(self, row_data, additional_info):
parent_items = [QStandardItem(col_data) for col_data in row_data]
for item in parent_items:
item.setEditable(False)
self.appendRow(parent_items)

additional_info_item = QStandardItem(additional_info)
additional_info_item.setData(True, Qt.UserRole + 1)
additional_info_item.setEditable(False)

parent_items[0].appendRow([additional_info_item])
return parent_items[0].index()

class TableWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
layout = QVBoxLayout(self)
model = GroupModel(self)
tree_view = GroupView(model)
layout.addWidget(tree_view)

model.add_group(["Parent Row 1", "Data 1", "Data 2"], "Additional info for Row 1")
model.add_group(["Parent Row 2", "Data 3", "Data 4"], "Additional info for Row 2")

for row in range(model.rowCount()):
parent_index = model.index(row, 0)
additional_row = model.itemFromIndex(parent_index).rowCount() - 1
tree_view.setFirstColumnSpanned(additional_row, parent_index, True)

if __name__ == '__main__':
import sys

app = QApplication(sys.argv)
window = TableWidget()
window.show()
window.resize(600, 400)
sys.exit(app.exec_())
есть также другой подход к отступу данных в расширяемой строке с помощью события рисования (установка self.setIndentation в 0), но это было более простое и короткое решение

Подробнее здесь: https://stackoverflow.com/questions/791 ... view-pyqt5
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»