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), но это было более простое и короткое решение
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)
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_()) [/code] Я хочу сделать отступ для данных в расширяемой строке. Когда я присваиваю self.setIndentation(0) значение выше 0, это отступ, но я также вижу стрелку слева, чего мне не хочется. Как вы можете видеть в коде, я поместил значки в последний столбец, чтобы стрелки располагались справа, поэтому исходная стрелка TreeView не нужна. Мой виджет основан на об этом решении: Как я могу создать таблицу, строки которой можно свернуть в категории в Qt? Кроме того, я хочу сделать текст, который я помещаю в расширяемую строку, более темным фон и закругленные края, чтобы выглядеть лучше. Я попробовал разместить на нем метку, но в результате текст вообще больше не был виден, возможно, я сделал это неправильно. p> Надеюсь, что есть правильное решение моей проблемы. Резюме: Я хочу сделать отступ для текста в расширяемой строке (не видя исходной стрелки) из QTreeView) и сделайте фон светло-серым с закругленными краями. РЕДАКТИРОВАТЬ: Учитывая комментарии musicamante, это мое решение: [code]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
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)
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_()) [/code] есть также другой подход к отступу данных в расширяемой строке с помощью события рисования (установка self.setIndentation в 0), но это было более простое и короткое решение
Я работаю над приложением PyQt5, в котором у меня есть QTreeView, заполненный QStandardItemModel. Корневые элементы должны быть перетаскиваемыми и перемещаться в иерархии древовидного представления. Но корневой элемент не должен перетаскиваться...
Я работаю над приложением PyQt5, в котором у меня есть QTreeView, заполненный QStandardItemModel. Корневые элементы представляют документы и дочерние разделы внутри документа. Поэтому их не следует смешивать. Я хочу добиться следующего поведения:...
введите здесь описание изображения
Я хочу, чтобы неокрашенная часть обернутой части была с отступом и выровнена, поскольку размер каждого символа не фиксирован, я не могу сделать это путем подсчета количества символов, мне нужно переопределить какой...
введите здесь описание изображения
Я хочу, чтобы неокрашенная часть обернутой части была с отступом и выровнена, поскольку размер каждого символа не фиксирован, я не могу сделать это путем подсчета количества символов, мне нужно переопределить какой...