web-dev-qa-db-fra.com

Qt Débutant QPainter et QRect

Comment pourrais-je faire pour dessiner un rectangle?

J'ai essayé deux manières différentes. 

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

Ce qui fonctionne bien (même si le paramètre n'est pas nommé ni utilisé), mais je ne souhaite pas utiliser QPaintEvent * Je n'ai aucune utilisation de celui-ci. 

J'ai donc essayé de renommer ma fonction.

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

Cela n'affiche rien (n'a pas encore d'erreur).

Pourquoi cela ne fonctionnerait-il pas si je n'utilise pas QPaintEvent * ??

9
Ash

L'événement Paint est la méthode appelée par le système Paint lorsqu'un widget doit être redessiné. C’est pourquoi nommer votre propre méthode ne fonctionne pas. Il n'est jamais appelé par le système Paint. 

Vous devriez vraiment utiliser la QPaintEvent. Cela vous donne le rect qui doit être tracé. Ce rect sera basé sur la taille du widget. Par conséquent, au lieu d'utiliser un rect explicite dans votre événement Paint, définissez votre widget à la bonne taille. Un événement de peinture sera généré si votre widget se déplace, se redimensionne, etc.

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

Maintenant, si vous voulez séparer votre logique Paint en une autre méthode, c'est très bien. Mais vous devez le faire appeler à partir de l'événement 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);
}

Si vous souhaitez ignorer complètement les événements Paint, comme vous l'avez dit, et ne créer qu'un rectangle statique à afficher, vous pouvez le dessiner une fois sur un pixmap et l'afficher dans un QLabel:

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

Toutes les données dont votre paintEvent() a besoin doivent être accessibles en tant que champs de la classe contenante, dans votre cas, des champs privés de MyWidget. Ces champs privés peuvent être exposés aux clients de MyWidget via des "paramètres" qui définiraient les valeurs de données avant d'appeler update() sur MyWidget, ce qui déclencherait un appel à paintEvent().

2
Arnold Spence

Cette liste de lecture contient les meilleurs tutoriels Qt, le tutoriel 74 vous serait utile (Qpainter et QPen), le tutoriel 75 explique comment dessiner des rectangles avec QRect.

1
Ahmed Kato

De plus, @Mat vous a dit: le "événement" est le bon moyen de lancer un Painter.
QPainter ne peut être évoqué qu'après un événement QPaintEvent, qui transporte la région sûre où l'objet peut être dessiné .

Vous devez donc trouver une autre stratégie pour transporter vos données, pour aider Je proposerai une méthode simple, qui peut être ajustée à de nombreux cas.

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

Comme vous pouvez le voir dans le code est exécuté un timer, en dehors de l'objet "widget"

toutes les 10 ms envoie une nouvelle peinture au widget pour redessiner un "rect" avec une taille différente et tous les 20 cycles (200 ms) modifie le texte "hello" pour "world"

Dans cet exemple, vous pouvez constater que l’architecture QPainterDevice doit être écrasée.

Vous pouvez également remarquer que le "événement" du "paintEvent" est désactivé et n'est pas utilisé directement, mais il est essentiel d'exécuter une séquence QPainter.

1
RTOSkit

Le remplacement de la fonction paintEvent () d'un widget vous permet de personnaliser le widget. Cette fonction est appelée périodiquement pour redessiner le widget. Par conséquent, tout dessin doit être fait dans cette fonction. Cependant, le remplacement de paintEvent () peut entraîner des problèmes de performances. Je préférerais utiliser QGraphicsScene et QGraphicsView, puis ajouter un rectangle à la scène, ce qui est la façon habituelle de faire ce genre de dessin. S'il vous plaît vérifier le cadre GraphicsView

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

0
fatma.ekici