Как рисовать в QMainWindow?

У меня очень странное поведение QPainter. В моем 'MainWindow::paintEvent()' все работает правильно:

QPainter painter(this);
qDebug() << "painter adress in paintEvent: " << (&painter);
painter.setBrush(Qt::red);
painter.drawRect(100, 100, 100, 100);

Все идет нормально. Но на самом деле я хочу рисовать, используя функцию класса, которую я написал, поэтому мой 'paintEvent()' выглядит так:

QPainter painter(this);
qDebug() << "painter adress in paintEvent: " << (&painter);
painter.setBrush(Qt::red);
painter.drawRect(100, 100, 100, 100);
instance_of_my_class->paint(&painter);
painter.drawRect(150, 150, 100, 100);

А 'paint(QPainter *painter)', который вызывается выше, выглядит так:

qDebug() << "painter adress in paint: " << painter;
painter->setBrush(QColor(0, 0, 80));
painter->drawRect(0, 0, 1000, 1000);

Очевидно, теперь я ожидал бы увидеть темно-синий фон с одним красным прямоугольником (второй, первый должен быть перекрашен в «краске»). Однако я вижу два красных прямоугольника, а на панели инструментов все значки имеют темно-синий фон. Кроме того, вывод 'qDebug()' выглядит следующим образом:

painter adress in paintEvent:  0xbfd43b54
painter adress in paint:  0xbfd43b54

Это определенно тот же QPainter, но в моем классе он рисует под значками на моей панели инструментов!?!


person Bianfable    schedule 14.03.2014    source источник


Ответы (1)


Как правило, рисовать что-либо в событии рисования QMainWindow является ошибкой. Главное окно может иметь различные дочерние виджеты. Ваш художник с удовольствием вмешается в них - вы не показываете никакого кода, который перечисляет окна док-станции, дочерние окна и т. д.

Чтобы нарисовать что-то в главном окне, вам нужно нарисовать это в отдельном виджете, и этот виджет должен быть передан через setCentralWidget в главное окно.

Вам абсолютно не нужно использовать QMainWindow, если вам не нужна его полная функциональность. Это означает: если вам не нужна строка меню и виджеты в доке, не используйте QMainWindow.

Это работает:

скриншот

#include <QApplication>
#include <QMainWindow>
#include <QPainter>

class Bottom {
public:
    void paint(QPainter * p) {
        p->setBrush(Qt::blue);
        p->drawRect(0, 0, 1000, 1000);
    }
};

class Top : public QWidget {
    Bottom * m_bottom;
    void paintEvent(QPaintEvent *) {
        QPainter p(this);
        p.setPen(Qt::NoPen);
        p.setBrush(Qt::red);
        p.drawRect(0, 0, 100, 100);
        m_bottom->paint(&p);
        p.setBrush(Qt::green);
        p.drawRect(50, 50, 100, 100);
    }
public:
    Top(Bottom * bottom, QWidget * parent = 0) :
        QWidget(parent), m_bottom(bottom) {}
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMainWindow w;
    Bottom b;
    Top t(&b);
    w.setCentralWidget(&t);
    w.setMinimumSize(200, 200);
    w.show();
    return a.exec();
}
person Kuba hasn't forgotten Monica    schedule 14.03.2014
comment
Спасибо за совет, но, к сожалению, мою проблему он не решил. Я написал новый класс, унаследованный от QWidget, установил его экземпляр в качестве центрального виджета в моем MainWindow и переместил элементы рисования в paintEvent() виджета. Но все же: выполняются только команды рисования в paintEvent(), краска в моем подклассе игнорируется (теперь она больше не закрашивает панель инструментов). - person Bianfable; 15.03.2014
comment
@Bianfable Вы не показываете никакого кода, и это контрпродуктивно. У вас должен быть полный, один файл, минимальный пример, показывающий, что вы делаете. Почему это важно? Потому что я могу опубликовать тестовый пример прямо здесь, который показывает, что это работает, и все, что я делаю, это следую своим собственным инструкциям. Ваша проблема в том, что вы не показываете. Здесь есть сотни, если не тысячи вопросов, подобных вашему: люди настаивают на том, чтобы не показывать автономный, минимальный код, и каждый раз, когда я публикую контрпример, они говорят что-то вроде «ох, это было в каком-то другом моем коде». Дух. Покажи свой код. - person Kuba hasn't forgotten Monica; 15.03.2014
comment
Ваш пример был самым простым для развития. Спасибо! - person kuzavas; 22.06.2017