web-dev-qa-db-ja.com

QtビギナーQPainterとQRect

長方形を描くにはどうすればよいですか?

私は2つの異なる方法を試しました。

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 *を使用しないと機能しないのはなぜですか?

9
Ash

Paintイベントは、ウィジェットを再描画する必要があるときにPaintシステムによって呼び出されるメソッドです。そのため、独自のメソッドに名前を付けるだけでは機能しません。ペイントシステムによって呼び出されることはありません。

本当にQPaintEventを使用する必要があります。それはあなたに描かれる必要があるrectを与えます。この四角形はウィジェットのサイズに基づいているため、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イベントを完全にバイパスし、表示する静的な長方形のみを作成したい場合、1つの方法は、それをピックスマップに1回描画し、QLabelに表示することです。

QPixMap pix(200,100);
QPainter Painter(&pix);
// do Paint operations
Painter.end()
someLabel.setPixmap(pix)
10
jdi

paintEvent()が必要とするすべてのデータは、それを含むクラスのフィールド、この場合はMyWidgetのプライベートフィールドとしてアクセスできる必要があります。これらのプライベートフィールドは、MyWidgetupdate()を呼び出す前にデータ値を設定する「setters」を介してMyWidgetのクライアントに公開できます。これにより、paintEvent()

2
Arnold Spence

このプレイリスト 最高のQtチュートリアルが含まれています。チュートリアル74を開始すると(QpainterとQPen)、チュートリアル75はQRectを使用して長方形を描画する方法です。

1
Ahmed Kato

同様に@Matはあなたに言った: "イベント"はPainterを起動する正しい方法です。
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();
}

コードでわかるように、オブジェクト「ウィジェット」の外側でタイマーが実行されます

10ミリ秒ごとにウィジェットの再描画を送信して、異なるサイズの「長方形」を再描画し、20サイクル(200ミリ秒)ごとに「世界」のテキスト「こんにちは」を変更します

この例では、何らかの方法でQPainterDeviceアーキテクチャを上書きする必要があることがわかります。

また、「paintEvent」内の "event"は無音であり、直接使用されていないことに気付くかもしれませんただし、シーケンスQPainter。

1
RTOSkit

ウィジェットのpaintEvent()関数をオーバーライドすると、ウィジェットをカスタマイズできます。この関数は、ウィジェットを再描画するために定期的に呼び出されます。したがって、この関数で描画を行う必要があります。ただし、paintEvent()をオーバーライドすると、パフォーマンスの問題が発生する可能性があります。 QGraphicsSceneとQGraphicsViewを使用したいので、この種の描画を行う一般的な方法である長方形をシーンに追加します。 GraphicsViewフレームワークを確認してください

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

0
fatma.ekici