Как использовать Qt Delegates для пользовательской рисования?

Я пытаюсь переопределить способ рисования QTreeWidgetItems при перетаскивании элемента поверх них. Я переопределил события перетаскивания, чтобы установить для данных Qt.UserRole значение 1 для QTreeWidgetItems, которые я хочу нарисовать. В делегате предметов я читаю UserRole и рисую соответственно.

Моя заказная картина отображается точно так, как ожидалось (то есть жирная линия); однако я не смог понять, как подавить рисунок, выполненный стандартным художником для перетаскивания (т. е. маленький прямоугольник), без подавления всех других рисунков (т. е. текста и т. д.).

Любые идеи были бы хорошы.

альтернативный текст

Ex.

def dragMoveEvent(self, event):
    pos = event.pos()
    item = self.myTreeWidget.itemAt(pos)

    # If hovered over an item during drag, set UserRole = 1
    if item:
        index = self.myTreeWidget.indexFromItem(item)
        self.myTreeWidget.model().setData(index, 1, Qt.UserRole)

    # reset UserRole to 0 for all other indices
    for i in range(self.myTreeWidget.model().rowCount()):
        _index = self.myTreeWidget.model().index(i, 0)
        if not item or index != _index:
            self.myTreeWidget.model().setData(_index, 0, Qt.UserRole)


class MyDelegate(QStyledItemDelegate):

    def paint( self, painter, option, index ):
        QStyledItemDelegate.paint(self, painter, option, index)
        painter.save()
        data = index.model().data( index, Qt.UserRole ).toInt()
            # if UserRole = 1 draw custom line
        if data[1] and data[0] == 1:
            line = QLine( option.rect.topLeft(), option.rect.topRight() )
            painter.drawLine( line )
        painter.restore()

1 ответ

Решение

Это легко решаемо с помощью qt с использованием C++: вы можете определить новый стиль, переопределить метод drawPrimitive и выполнить там произвольную рисование (или просто ничего не делать) всякий раз, когда константа QStyle::PE_IndicatorItemViewItemDrop получена через параметр элемента. Ниже приведен пример:

class TestStyle : public QProxyStyle
{
public:
    TestStyle(QStyle *baseStyle = 0) : QProxyStyle(baseStyle) {}

    void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
    {
        if (element == QStyle::PE_IndicatorItemViewItemDrop)
        {
            //?? do nothing or do custom painting here
        }
        else
        {
            QProxyStyle::drawPrimitive(element, option, painter, widget);
        }
    }
};

.. 

ui->treeView->setStyle(new TestStyle(ui->treeView->style()));

теперь плохие новости в том, что pyqt ничего не знает о QProxyStyle; Похоже, что он там не обернут, поэтому для того, чтобы это работало, вам нужно обернуть классы стиля самостоятельно.

Другое решение - создать собственный потомок QTreeView и переопределить его метод paintEvent. Реализация по умолчанию вызывает drawTree и paintDropIndicator; где paintDropIndicator отвечает за индикатор перетаскивания, а drawTree отображает элементы дерева. DrawTree защищен и доступен для вызова из вашего paintEvent:

class TestTreeView : public QTreeView
{
public:
    explicit TestTreeView(QWidget *parent = 0) : QTreeView(parent) {}

    void paintEvent(QPaintEvent * event)
    {
        QPainter painter(viewport());
        drawTree(&painter, event->region());
    }
};

это должно подавить индикатор перетаскивания по умолчанию. Дайте мне знать, если у вас возникли проблемы с преобразованием его в python.

надеюсь, что это помогает, привет

Другие вопросы по тегам