Qt начинающий QPainter и QRect

Как я буду рисовать прямоугольник?

Я пробовал два разных варианта;

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

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

поэтому я попытался просто переименовать свою функцию;

void MyWidget::draw()
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

это ничего не отображает (пока не имеет ошибок).

почему это не сработает, если я не использую QPaintEvent * ??

5 ответов


событие paint-это метод, вызываемый системой paint при необходимости перерисовки виджета. Вот почему просто назвать свой собственный метод не работает. Он никогда не вызывается системой paint.

вы действительно должны использовать QPaintEvent. Это дает вам прямую кишку, которую нужно нарисовать. Этот rect будет основан на размере виджета, поэтому вместо использования явного rect в событии paint установите виджет в нужный размер. Событие paint будет сгенерировано Ваш когда-нибудь виджета, перемещать, изменять размер и т. д.

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

теперь, если вы хотите разделить свою логику рисования на другой метод, это нормально. Но вам нужно будет вызвать его из события paint:

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    draw(rect);
}

void MyWidget::draw(QRect &rect)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

если вы хотите полностью обойти события paint, как вы сказали, и хотите создать только статический прямоугольник для отображения, один из способов-просто нарисовать его один раз в pixmap и отобразить его в QLabel:

QPixMap pix(200,100);
QPainter painter(&pix);
// do paint operations
painter.end()
someLabel.setPixmap(pix)

любые данные, которые paintEvent() потребности должны быть доступны как поля, содержащего класса, в вашем случае, частная полях MyWidget. Эти частные поля могут быть открыты для клиентов MyWidget через "сеттеры", которые будут устанавливать значения данных перед вызовом update() on MyWidget который вызовет вызов paintEvent().


этот плейлист содержит лучшие учебники Qt, начиная учебник 74 было бы полезно для вас (Qpainter и QPen), учебник 75, как рисовать прямоугольники с помощью QRect.


также @Mat сказал вам:"мероприятие" это правильный способ запуска художника.
QPainter может быть вызван только после события QPaintEvent,который несет безопасную область, где объект может быть нарисован.

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

виджет.cpp

#include <QtGui>
#include "widget.h"

#define MIN_DCX    (0.1)
#define MAX_DCX    (5.0)

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{    
    dcx=MIN_DCX;
    setFixedSize(170, 100);
}

void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event); 
    QPainter painter;
    painter.begin(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    pcx=dcx*2;
    QRect rect = QRect(50-dcx,25-dcx,60+pcx,40+pcx);
    painter.drawText(rect, Qt::AlignCenter,printData);
    painter.drawRect(rect);
    painter.end();

}

void Widget::setPrintData(QString value){
   printData = value;
   dcx=(dcx>MAX_DCX)?MIN_DCX:dcx+MIN_DCX;
}

виджет.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent);
    void setPrintData(QString value);

protected:
    void paintEvent(QPaintEvent *event);

private:
    QString printData;
    float dcx;
    float pcx;
};


#endif


переопределение функции paintEvent () виджета позволяет настроить виджет, и эта функция периодически вызывается для перерисовки виджета. Поэтому в этой функции должен быть выполнен любой чертеж. Однако переопределение paintEvent () может вызвать некоторые проблемы с производительностью. Я бы предпочел использовать QGraphicsScene и QGraphicsView, тогда я бы добавил прямоугольник к сцене, которая является распространенным способом выполнения такого рода рисования. Пожалуйста, проверьте GraphicsView Рамки

http://qt-project.org/doc/qt-4.8/graphicsview.html