Комбинация QTreeWidget и QPainter - PullRequest
       47

Комбинация QTreeWidget и QPainter

0 голосов
/ 04 апреля 2020

Я немного растерялся с QTreeWidget и не смог высосать соответствующую информацию из найденных тем (например: как установить фоновое изображение QTreeView с QStyle :: StandardPixmap в методе таблицы стилей? или Python: пример PyQt QTreeview - выбор или Стилизация Qt QTreeView с помощью CSS или Отображение табличных данных в Qt5 ModelViews ).

У меня есть два файла, один gui, один рабочий класс:

gui:

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")

        self.tree = QtWidgets.QTreeWidget(Dialog)
        self.tree.setGeometry(QtCore.QRect(10, 60, 760, 480))
        self.tree.setHeaderLabels(['circ', 'state', 'test'])
        self.tree.setSortingEnabled(True)

работник:

class AppWindow(QDialog):   
    def __init__(self, fullscreen=False):          
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.show()  


        self.timer = QTimer()
        self.timer.setInterval(500)
        self.timer.timeout.connect(self.refresh_gui) 
        self.timer.start()


    def refresh_gui(self):
        self.painter = QPainter(self)
        tmp = {0: {"state": 1, "info": "hello"}, 1: {"state": 0, "info": "world"}}          
        for i in tmp:
            if tmp[i]["state"] == 0:
                painter.setPen(QPen(Qt.red,  8, Qt.SolidLine))
            else:
                painter.setPen(QPen(Qt.green,  8, Qt.SolidLine))
            circ = painter.drawEllipse(2,2,20,20)

            item = QtWidgets.QTreeWidgetItem(self.ui.tree, [circ, tmp[i]["state"], "empty"])
            item.setText(2, "circ painted")

Я хочу добиться, чтобы, если state == 0, то в первом столбце отображался красный круг, а если state == 1 - зеленый. Я не знаю, как передать QTreeWidgetItem объект PyQt5.Qt Gui .QPainter вместо строки.

Кроме того, я получаю ошибку:

QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
QPainter::end: Painter not active, aborted

и некоторые строки ниже (из-за этого): QPainter::setPen: Painter not active , потому что я вызываю self.painter = QPainter(self), который обсуждается в этом git проблема с matplotlib , но я не могу исправить это в своем коде. Я нашел этот учебник по QPainter , который рисует на QPixmap, который также работает для меня, но это не то, что я ищу здесь.

1 Ответ

2 голосов
/ 04 апреля 2020

Рисование виджета не выполняется ни в одном методе, но метод paintEvent должен быть переопределен, который вызывается всякий раз, когда это необходимо Qt или с помощью update или repaint от разработчика. Но в случае классов, которые обрабатывают модель (то есть много организованной информации), которая наследуется от QAbstractItemView, делегат должен использоваться, если элемент будет окрашен.

Учитывая вышеизложенное, решение:

class Delegate(QtWidgets.QStyledItemDelegate):
    def paint(self, painter, option, index):
        state = index.data(QtCore.Qt.UserRole)
        color = (
            QtGui.QColor(QtCore.Qt.red) if state == 0 else QtGui.QColor(QtCore.Qt.green)
        )
        painter.setPen(QtGui.QPen(color, 4, QtCore.Qt.SolidLine))
        diameter = min(option.rect.width(), option.rect.height())
        rect = QtCore.QRect(0, 0, diameter // 2, diameter // 2)
        rect.moveCenter(option.rect.center())
        painter.drawEllipse(rect)


class AppWindow(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.show()

        delegate = Delegate(self.ui.tree)
        self.ui.tree.setItemDelegateForColumn(0, delegate)

        self.timer = QtCore.QTimer(interval=500, timeout=self.refresh_gui)
        self.timer.start()

    @QtCore.pyqtSlot()
    def refresh_gui(self):

        tmp = [{"state": 1, "info": "hello"}, {"state": 0, "info": "world"}]

        for d in tmp:
            item = QtWidgets.QTreeWidgetItem(self.ui.tree, ["", str(d["state"]), "empty"])
            item.setData(0, QtCore.Qt.UserRole, d["state"])
            item.setText(2, "circ painted")

enter image description here

...