Рисование наложения поверх окна приложения

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

Я могу пройтись по дереву виджетов и извлечь соответствующую информацию, но вопрос в том, как я могу наложить эту информацию на все окна приложений?

Одним из способов было бы переопределить событие рисования моего QMainWindow, но это нужно сделать для всех окон верхнего уровня. Есть ли альтернативный метод, с помощью которого вы можете рисовать, например, на QDesktopWidget? Или какие-нибудь крючки в каждом методе рисования QWidget? Все, что связано с подклассом самого QWidget, не будет работать со стандартными виджетами.

Это следует из моего предыдущего вопроса:

ура Мандрил

РЕДАКТИРОВАТЬ: благодаря Дмитрию у меня теперь есть действительно простой метод, который легко расширяется:

class DiagnosticStyle : public QWindowsVistaStyle
{
Q_OBJECT

public: 
    typedef QWindowsVistaStyle BaseStyle;
    void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const;
};


void DiagnosticStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
    BaseStyle::drawControl(element, option, painter, widget);
    if (widget && painter) {
        // draw a border around the widget
        painter->setPen(QColor("red"));
        painter->drawRect(widget->rect());

        // show the classname of the widget
        QBrush translucentBrush(QColor(255,246,240, 100));
        painter->fillRect(widget->rect(), translucentBrush);
        painter->setPen(QColor("darkblue"));
        painter->drawText(widget->rect(), Qt::AlignLeft | Qt::AlignVCenter, widget->metaObject()->className()); 
    }
}

qApp->setStyle(new DiagnosticStyle());

person the_mandrill    schedule 06.05.2011    source источник


Ответы (2)


Вы можете создать собственный класс стиля на основе QMotifStyle или другого... и рисовать на любом виджете/элементе управления, относящемся к нему информацию.

void MyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,QPainter *painter, const QWidget *widget) const
{
     QStyle::State flags = option->state;
     QRect      rect     = option->rect;
     QPalette   pal      = option->palette;
     QBrush brush;

    switch (element)
    {
        case PE_FrameTabWidget:
        {
             painter->save();

                 // for example: draw anything on TabWidget
                painter->drawPixmap(rect,centerPm,centerPm.rect());
             painter->restore();
        }
        break;
        default:
         QMotifStyle::drawPrimitive(element, option, painter, widget);
         break;

    }
}
person Dmitry    schedule 06.05.2011
comment
Это хорошая идея — не будет ли полезнее вместо этого переопределить QStyle::drawControl(), так как это даст вам доступ к виджету? - person the_mandrill; 06.05.2011
comment
Оказывается, это именно то, что мне было нужно - см. мой отредактированный пост - person the_mandrill; 06.05.2011

Где-то в Qt5 стили (GTK, Windows и т.д.) были сделаны внутренними. Теперь вам нужно использовать QCommonStyle.

Если кому-то интересно, как это сделать с Qt5+. Вот автономная версия кода @the_mandrill выше.

class DiagnosticStyle : public QCommonStyle
{
Q_OBJECT

public: 
    typedef QStyle BaseStyle;
    void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
    {
        QCommonStyle::drawControl(element, option, painter, widget);
        if (widget && painter) {
            // draw a border around the widget
            painter->setPen(QColor("red"));
            painter->drawRect(widget->rect());

            // show the classname of the widget
            QBrush translucentBrush(QColor(255,246,240, 100));
            painter->fillRect(widget->rect(), translucentBrush);
            painter->setPen(QColor("darkblue"));
            painter->drawText(widget->rect(), Qt::AlignLeft | Qt::AlignVCenter, widget->metaObject()->className()); 
        }
    };
};

Затем в вызове конструктора главного окна

qApp->setStyle(new DiagnosticStyle());
person Alchete    schedule 23.02.2020