如何使用Qt Delegates进行自定义绘画?

发布于 2024-10-13 06:46:50 字数 1391 浏览 1 评论 0原文

我试图覆盖当项目被拖动到 QTreeWidgetItems 上时绘制 QTreeWidgetItems 的方式。我已经重写了拖动事件,将我想要绘制的 QTreeWidgetItems 的 Qt.UserRole 数据设置为 1。在 Item Delegate 中,我读取 UserRole 并进行相应的绘制。

我的自定义绘画完全按照预期显示(即粗体线);但是,我无法弄清楚如何在不抑制所有其他绘画(即文本等)的情况下抑制标准画家进行拖动(即小矩形)所做的绘图。

任何想法将不胜感激。

alt text

例如。

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

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.

alt text

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

滥情哥ㄟ 2024-10-20 06:46:50

使用 c++ 使用 qt 可以轻松解决此问题:您可以定义新样式,覆盖 drawPrimitive< /a> 方法,并在通过 element 参数接收 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 时遇到问题,请告诉我。

希望这有帮助,问候

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文