Login
Newsletter
Werbung

So, 5. März 2006, 00:00

Entwicklung von Applikationen in Qt 4.0

Listing 8. main.cpp: Zeichnen von Widgets

#include <QtGui/QApplication>
#include <QtGui/QPushButton>
#include <QtGui/QMouseEvent>
#include <QtGui/QFrame>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
class BoardWidget : public QFrame
{
 Q_OBJECT
public:
 BoardWidget(QWidget *parent = 0);
public slots:
 void clear();
protected:
 void mouseMoveEvent(QMouseEvent *event);
 void resizeEvent(QResizeEvent *event);
 void paintEvent(QPaintEvent *event);
private:
 QPixmap m_pixmap;
};
BoardWidget::BoardWidget(QWidget *parent)
 : QFrame(parent)
{
 setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
}
void BoardWidget::clear()
{
 m_pixmap.fill(Qt::white);
 update();
}
void BoardWidget::mouseMoveEvent(QMouseEvent *event)
{
 event->accept();
 QPoint pos = event->pos();
 QPainter painter(&m_pixmap);
 painter.fillRect(pos.x() - 2, pos.y() - 2 , 4, 4, Qt::black);
 update();
}
void BoardWidget::resizeEvent(QResizeEvent *event)
{
 event->accept();
 QPixmap new_pixmap(event->size());
 new_pixmap.fill(Qt::white);
 QPainter painter(&new_pixmap);
 painter.drawPixmap(QPoint(0, 0), m_pixmap);
 m_pixmap = new_pixmap;
}
void BoardWidget::paintEvent(QPaintEvent *event)
{
 event->accept();
 QPainter painter(this);
 painter.drawPixmap(QPoint(0, 0), m_pixmap);
 QFrame::paintEvent(event);
}
int main(int argc, char *argv[])
{
 QApplication app(argc, argv);
 QWidget window;
 window.resize(300, 200);
 window.setWindowTitle("Painter");
 QVBoxLayout top_layout(&window);
 top_layout.setMargin(3);
 BoardWidget board(&window);
 top_layout.addWidget(&board);
 QHBoxLayout button_layout;
 top_layout.addLayout(&button_layout);
 button_layout.addStretch();
 QPushButton clear_button("Clear", &window);
 QObject::connect(&clear_button, SIGNAL(clicked()), &board, SLOT(clear()));
 button_layout.addWidget(&clear_button);
 QPushButton close_button("Close", &window);
 QObject::connect(&close_button, SIGNAL(clicked()), &window,
 SLOT(close()));
 button_layout.addWidget(&close_button);
 window.show();
 return app.exec();
}
#include "main.moc"

Listing 8 zeigt ein einfaches Programm zum Zeichnen. Mit dem Zeichnen beschäftigt sich ein BoardWidget. Das Zeichnen erfolgt nicht direkt auf dem Widget, sondern auf einer Pixmap im Speicher, da das BoardWidget in jedem Moment in der Lage sein muss, jeden Teil seiner Fläche zu zeichnen. In paintEvent() zeichnet das BoardWidget eine fertige Pixmap auf sich selbst. Das BoardWidget erweitert QFrame. Dies ist ein Widget, das verschiedenartige Rahmen zeichnen kann. Ohne einen Rahmen würde das BoardWidget flach und uninteressant aussehen. Die Rahmenart legen wir im Konstruktor mit Hilfe von QFrame::setFrameStyle() fest.

Verfolgen wir, was passiert, wenn ein Benutzer die Maus über das BoardWidget bewegt. Wenn der Benutzer die Maus mit einer gedrückten Taste über das Widget verschiebt, liefert QApplication dem Widget unter der Maus ein QMouseEvent, wodurch das Widget mouseMoveEvent() aufruft. Wenn die Maustaste nicht gedrückt ist, bekommt das Widget unter der Maus kein QMouseEvent, es sei denn, dass es vorher die Maus mit Hilfe von QWidget::grabMouse() gefangen hat. Innerhalb von mouseMoveEvent() bekommen wir die Lage der Maus bezüglich der linken oberen Ecke des Widgets, indem wir die Funktion QMouseEvent::pos() benutzen. Dann erstellen wir QPainter zum Zeichnen auf der Pixmap und zeichnen ein 4x4-Rechteck. Zum Schluss rufen wir update() auf, was bewirkt, dass in der nächsten Iteration der Ereignisschleife unser BoardWidget ein QPaintEvent bekommt.

Innerhalb der Funktion paintEvent() legt BoardWidget ein Objekt QPainter zum Zeichnen auf sich selbst und zum Anzeigen von Pixmaps an. Zum Schluss ruft es die Funktion QFrame::paintEvent() auf, die einen Rahmen zeichnet.

Das BoardWidget behandelt auch den QResizeEvent. Innerhalb von resizeEvent() legen wir eine Pixmap mit neuen Abmessungen an und kopieren den Inhalt der alten Pixmap hinein. Qt garantiert, dass jedes Widget zumindest einmal ein QResizeEvent bekommt, bevor das Widget zum ersten Mal angezeigt wird.

In der main-Funktion erstellen wir ein vertikales Layout top_layout mit zwei Positionen. Die obere Position enthält das BoardWidget, die untere beinhaltet ein eingebettetes, horizontales Layout mit Schaltflächen - button_layout. Zum horizontalen Layout fügen wir zuerst eine leeren, verstreckbaren Bereich (addStretch()), danach zwei Schaltflächen hinzu. Somit werden Schaltflächen immer in der rechten unteren Ecke gruppiert.

Zusammenfassung

Wir haben eine einfache Applikation geschrieben, die die wichtigsten Mechanismen in Qt verwendet: Signale und Slots, die Ereignisbehandlung und das Zeichnen. Im nächsten Teil schreiben wir eine umfangreichere Applikation: QtCommander.

Über den Autor

Der Autor arbeitet bei der Firma Trolllech. Er beschäftigt sich mit der Entwicklung der Applikation Qt Designer und vieler anderen Qt-Klassen.

Lizenz

Dieser Artikel wurde im Magazin Programmieren unter Linux publiziert. Alle Rechte vorbehalten. Kostenlose Vervielfältigung und Vertreiben des Artikels ist in unveränderter Form gestattet.

Kommentare (Insgesamt: 2 || Alle anzeigen )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung