# QT-QPainter und QWidget



## Monchichu (2. Mai 2009)

Hallo ich brauche eure Hilfe.
Ich habe nichts brauchbares gefunde was mir weiter helfen könnte.
Ich habe folgendes Problem ich arbeite grade zum ersten mal mit dem QT-Creator und ich habe wie auf dem Bild (siehe Link) zusehen ist eine Widget (rot eingekreist) auf dieses Widget möchte ich malen mit dem QPainter.
Jedoch habe ich keine Ahnung wie ich das anstellen soll. Wie kann ich den QPainter auf dieses Element anwenden?

Bitte helft mir ich verzweifel allmälich.

MfG Monchichu


----------



## RedWing (3. Mai 2009)

Hallo,

auf ein QWidget zu zeichnen wird so nicht funktionieren. Wenn du zeichnen möchtest musst du dir dein eigenes Widget aus der Hierarchie ableiten und die QWidget:aintEvent Methode überschreiben. Dieses Widget kannst du dann manuell über die Methode QMainWindow::setCentralWidget als "Main-Widget" Element deines MainWindows setzen:


```
#include <QWidget>
#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QApplication>


class SimpleExampleWidget : public QWidget {

    Q_OBJECT

    void paintEvent(QPaintEvent *) {
        QPainter painter(this);
        painter.setPen(Qt::blue);
        painter.setFont(QFont("Arial", 30));
        painter.drawText(rect(), Qt::AlignCenter, "Qt");
    }
};

int main(int argc, char **argv) {
    QApplication app(argc, argv);
    QMainWindow mw;

    mw.setCentralWidget(new SimpleExampleWidget());
    mw.show();

    return app.exec();
}

#include "paint_example.moc"
```

Siehe auch:
http://doc.trolltech.com/4.5/qwidget.html#paintEvent
http://doc.trolltech.com/4.5/qpainter.html
http://doc.trolltech.com/4.5/qmainwindow.html#setCentralWidget

HTH,
RedWing


----------



## Monchichu (3. Mai 2009)

Danke für die Antwort und wie bekomme ich jetzt hin das ich dieses Widget auf eine bestimmte Stelle setzte und so das ich Buttons die ich n der linken Seite habe die auf dem MainWindow sind auch noch nutzen kann?
Es sollte im nachhinnein ungefähr so aus sehen....das Weiße ist ein Widget und das graue darunter is auch ein Widget.

Bildlink


MfG Monchichu


----------



## RedWing (3. Mai 2009)

Hallo,

wenn man ein eigenes Widget braucht führt am Überschreiben der paintEvent Methode kein Weg vorbei, d.h. du brauchst deinen eigenen Widgettypen.

Um das zu realisieren gibt es prinzipiell 2 Möglichkeiten:

1.) Du implementierst dir ein Custom Widget als Plugin für den QtDesigner. Dieses musst du einmal selber schreiben und kannst es dann als Plugin im Designer verwenden und kannst somit dein Widget komfortabel hinplatzieren wo du willst. Wie das geht steht dort beschrieben:
http://doc.trolltech.com/4.2/designer-creating-custom-widgets.html#getting-started
Wenn du Interesse hast, kann ich auch mit einem Beispielplugin dienen ...

2.) Du programmierst deine komplette Anwendung per Hand, evtl. unter Zuhilfenahme eines Layoutmanagers.

Gruß,
RedWing


----------



## Monchichu (3. Mai 2009)

Ich habe nur mit einem GridLayout meine OberFläche komplett selber geschrieben und kann auch schon malen und so weiter.
Nur jetzt stehe ich vor zwei weiteren Problemen.

1. Ich habe einen Button "Neu" wenn ich diesen Button betätige dann soll mit das Widget auf dem ich male neu gemacht werden bzw. einfach das gemalte verschwinden. Kann mir da vielleicht jemand sagen wie ich das anstellen kann?

2. Wenn ich die Maustaste gedrückt halte zum Malen dann malt er auch solange ich die Maustaste gedrückt halte. Kein Problem. Aber wenn ich dann woanders ansetzte zum malen dann malt er mir von dem letzten Punkt wo ich abgesetzt habe zu dem neuen Punkt von wo aus ich jetzt malen möchte eine Linie. Wie kann ich dies unterbinden?


Der Code des PaintEvents:

```
void zeichenFeld::paintEvent(QPaintEvent * )
{
    QPainter painter;                                // Klasse zum malen
    vector<struct myPoint *>::iterator pos, start;   // Iterator fuer pos und start

    painter.begin(this);                             // startet das Paint-Device

    if (points.size()>1)                             // wurde was gemalt?
    {
           pos=points.begin();                       // Iterator pos auf Anfang
           for(;;)                                   // Schleife startet
           {
                  start=pos;
                  pos++;

                  if (pos==points.end())             // Abbruchbedingung: pos am Ende von Vektor
                      break;

                  // ansonsten: Werte aus Instanz des Vektors start painter zuweisen
                  // und zeichnen
                  // diese Klammerung (*start)->color ist nur Zeiger-Arithmetik
                  painter.setPen(QPen((*start)->color, (*start)->width));

                  painter.drawLine((*start)->point,(*pos)->point);
           }
           painter.end();                           // beendet das Paint-Device

     }
}

// ***********************************************
//
void zeichenFeld::mouseMoveEvent(QMouseEvent *event)
{
    struct myPoint *point;                            // bei jedem Mouse-Event: neue Instanz

    point=new struct myPoint;
    point->point.setX(event->x());                    // der Instanz Werte zuweisen
    point->point.setY(event->y());
    point->color=color;
    point->width=width;
    points.push_back(point);                          // Instanz ans Ende des Vektors

    repaint();
}
```


----------



## RedWing (4. Mai 2009)

Hallo,

zu deinem ersten Problem:

Qt besitzt einen sogenannten Signal/Slot Mechanismus zur Interobjekt-Kommunikation, d.h. wenn sich eine Eigenschaft eines Objektes geändert hat und es diesem einen anderen Objekt mitteilen möchte kann das Objekt  ein Signal emittieren. Dies kann von dem anderen Objekt dann aufgefangen und behandelt werden. Um Signals und Slots zwischen Objekten verbinden zu können verwendet man die Methode QObject::connect. Die bekommt das "Sourceobjekt", den Namen des Signals, das "Targetobjekt" und den Namen des Slots übergeben. Somit kannst du nun das "clicked" Signal deines QPushButtons mit einem Slot verbinden welcher von dir dann implementiert werden muss. In diesem Slot kannst du dann bspw. ein Flag setzen welches die Löschung deiner Zeichenfläche beantragt, rufst danach repaint bzw update auf und löschst dann innerhalb deiner paintEvent Methode  deine Zeichenfläche eben abhängig von diesem Flag.
Ein Beispiel wie man Signals und Slots untereinander verbindet kannst du im anderen Thread sehen:
http://www.tutorials.de/forum/c-c/339875-qt-widget-als-bild-speichern.html#post1756558

Zu 2.:

Es wäre da hilfreich mal deinen kompletten Code zu sehen.

Gruß,
RedWing


----------

