Qt初学者QPainter和QRect

时间:2012-12-31 11:58:14

标签: 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 个答案:

答案 0 :(得分:10)

paint事件是在需要重绘窗口小部件时由绘制系统调用的方法。这就是为什么简单地命名自己的方法不起作用。它永远不会被油漆系统调用。

你真的应该使用QPaintEvent。它为您提供了需要绘制的矩形。此rect将基于窗口小部件的大小,因此不要在绘制事件中使用显式rect,而是将窗口小部件设置为正确的大小。如果您的小部件移动,调整大小等,将生成一个绘制事件。

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

如果你想完全绕过绘画事件,并且只想创建一个静态矩形来显示,一种方法是只绘制一次像素图并将其显示在QLabel中:

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

答案 1 :(得分:2)

paintEvent()所需的任何数据都应作为包含类的字段(在您的情况下为MyWidget的私有字段)进行访问。这些私有字段可以通过“setter”向MyWidget的客户端公开,这些客户端会在update()上调用MyWidget之前设置数据值,这将触发对paintEvent()的调用。< / p>

答案 2 :(得分:1)

This playlist包含最好的Qt教程,开始教程74对你有用(Qpainter和QPen),教程75是如何使用QRect绘制矩形。

答案 3 :(得分:1)

@Mat告诉你:“event”是启动画家的正确方法。
QPainter只能在QPaintEvent事件后引发,带有可以绘制对象的安全区域

因此,您必须找到另一种传输数据的策略,以提供帮助 我将提出一种简单的方法,可以根据很多情况进行调整。

widget.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;
}

widget.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

window.cpp

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

#define MAX_SDCX  20

Window::Window()
    : QWidget()
{
    gobject = new Widget(this);

    textMode=1;
    rectMode=1;
    gobject->setPrintData(msgs[textMode]);

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(gobject, 0, 0);
    setLayout(layout);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(dataOnAir()));
    timer->start(10);

    setWindowTitle(tr("Rect Shaking"));
}



void Window::dataOnAir(){
    if((++rectMode)>MAX_SDCX){
        rectMode=0;
        textMode^=1;
    }
    gobject->setPrintData(msgs[textMode]);
    gobject->repaint();
}

window.h中

#ifndef WINDOW_H
#define WINDOW_H

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

class Window : public QWidget
{
    Q_OBJECT

public:
    Window();

private slots:
    void dataOnAir();

private:
    Widget *gobject;
    const QString msgs[2] = {"Hello","World"};
    int textMode;
    int rectMode;
};

#endif

的main.cpp

#include <QApplication>
#include "window.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Window window;
    window.show();
    return app.exec();
}

正如您在代码中看到的那样,在对象“widget”

之外执行了一个计时器

每隔10ms重新发送一个小部件,重新绘制一个不同大小的“rect”,每20个周期(200ms)更改“hello”为“world”的文本

在此示例中,您可以看到以任何方式需要覆盖QPainterDevice体系结构。

您可能还注意到“paintEvent”中的“event”已被静音且未直接使用,但必须执行序列QPainter。

答案 4 :(得分:0)

覆盖窗口小部件的paintEvent()函数使您可以自定义窗口小部件,并定期调用此函数以重绘窗口小部件。因此,任何绘图都应该在此功能中进行。但是,重写paintEvent()可能会导致一些性能问题。我更喜欢使用QGraphicsScene和QGraphicsView然后我会在场景中添加一个矩形,这是做这种绘图的常用方法。请检查GraphicsView Framework

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