开发者

How to use Qt Delegates for custom painting?

I'm trying to override the way QTreeWidgetItems are drawn when an item is dragged over them. I've overridden the drag Events to set the Qt.UserRole data to 1 for the QTreeWidgetItems that I want to paint. In the Item Delegate, I read the UserRole and draw accordingly.

My custom painting is showing up exactly as expected (i.e. the bolded line); however, I have not been able to figure out how to suppress the drawing done by the standard painter for Dragging (i.e. the small rectangle) without suppressing all other painting (i.e. the text, etc.).

Any ideas would be appreciated.

How to use Qt Delegates for custom painting?

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.mode开发者_开发技巧l().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()


this is easily solvable with qt using c++: you can define a new style, override drawPrimitive method and do custom painting (or just do nothing) there whenever QStyle::PE_IndicatorItemViewItemDrop constant is received via element parameter. Below is an example:

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()));

now the bad news is that pyqt doesn't seem to know anything about QProxyStyle; looks like it's not wrapped there, so in order for this to work you would need to wrap style classes yourself.

another solution is to create a custom QTreeView descendant and override its paintEvent method. Default implementation is calling drawTree and paintDropIndicator; where paintDropIndicator is responsible for drag and drop indicator, and drawTree renders tree items. drawTree is protected and available for you to call from your paintEvent:

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

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

this should suppress the default drag and drop indicator. Let me know if you're having troubles converting it to python.

hope this helps, regards

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜