Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Modules  ·  Fonctions  · 

Analog Clock Example

Files:

The Analog Clock example shows how to draw the contents of a custom widget.

Screenshot of the Analog Clock example

This example also demonstrates how the transformation and scaling features of QPainter can be used to make drawing custom widgets easier.

AnalogClock Class Definition

The AnalogClock class provides a clock widget with hour and minute hands that is automatically updated every few seconds. We subclass QWidget and reimplement the standard paintEvent() function to draw the clock face:

    class AnalogClock : public QWidget
    {
        Q_OBJECT

    public:
        AnalogClock(QWidget *parent = 0);

    protected:
        void paintEvent(QPaintEvent *event);
    };

AnalogClock Class Implementation

    AnalogClock::AnalogClock(QWidget *parent)
        : QWidget(parent)
    {
        QTimer *timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(update()));
        timer->start(1000);

        setWindowTitle(tr("Analog Clock"));
        resize(200, 200);
    }

When the widget is constructed, we set up a one-second timer to keep track of the current time, and we connect it to the standard update() slot so that the clock face is updated when the timer emits the timeout() signal.

Finally, we resize the widget so that it is displayed at a reasonable size.

    void AnalogClock::paintEvent(QPaintEvent *)
    {
        static const QPoint hourHand[3] = {
            QPoint(7, 8),
            QPoint(-7, 8),
            QPoint(0, -40)
        };
        static const QPoint minuteHand[3] = {
            QPoint(7, 8),
            QPoint(-7, 8),
            QPoint(0, -70)
        };

        QColor hourColor(127, 0, 127);
        QColor minuteColor(0, 127, 127, 191);

        int side = qMin(width(), height());
        QTime time = QTime::currentTime();

The paintEvent() function is called whenever the widget's contents need to be updated. This happens when the widget is first shown, and when it is covered then exposed, but it is also executed when the widget's update() slot is called. Since we connected the timer's timeout() signal to this slot, it will be called at least once every five seconds.

Before we set up the painter and draw the clock, we first define two lists of QPoints and two QColors that will be used for the hour and minute hands. The minute hand's color has an alpha component of 191, meaning that it's 75% opaque.

We also determine the length of the widget's shortest side so that we can fit the clock face inside the widget. It is also useful to determine the current time before we start drawing.

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.translate(width() / 2, height() / 2);
        painter.scale(side / 200.0, side / 200.0);

The contents of custom widgets are drawn with a QPainter. Painters can be used to draw on any QPaintDevice, but they are usually used with widgets, so we pass the widget instance to the painter's constructor.

We call QPainter::setRenderHint() with QPainter::Antialiasing to turn on antialiasing. This makes drawing of diagonal lines much smoother.

The translation moves the origin to the center of the widget, and the scale operation ensures that the following drawing operations are scaled to fit within the widget. We use a scale factor that let's us use x and y coordinates between -100 and 100, and that ensures that these lie within the length of the widget's shortest side.

To make our code simpler, we will draw a fixed size clock face that will be positioned and scaled so that it lies in the center of the widget.

The painter takes care of all the transformations made during the paint event, and ensures that everything is drawn correctly. Letting the painter handle transformations is often easier than performing manual calculations just to draw the contents of a custom widget.

We draw the hour hand first, using a formula that rotates the coordinate system counterclockwise by a number of degrees determined by the current hour and minute. This means that the hand will be shown rotated clockwise by the required amount.

        painter.setPen(Qt::NoPen);
        painter.setBrush(hourColor);

We set the pen to be Qt::NoPen because we don't want any outline, and we use a solid brush with the color appropriate for displaying hours. Brushes are used when filling in polygons and other geometric shapes.

        painter.save();
        painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
        painter.drawConvexPolygon(hourHand, 3);
        painter.restore();

We save and restore the transformation matrix before and after the rotation because we want to place the minute hand without having to take into account any previous rotations.

        painter.setPen(hourColor);

        for (int i = 0; i < 12; ++i) {
            painter.drawLine(88, 0, 96, 0);
            painter.rotate(30.0);
        }

We draw markers around the edge of the clock for each hour. We draw each marker then rotate the coordinate system so that the painter is ready for the next one.

        painter.setPen(Qt::NoPen);
        painter.setBrush(minuteColor);

        painter.save();
        painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
        painter.drawConvexPolygon(minuteHand, 3);
        painter.restore();

The minute hand is rotated in a similar way to the hour hand.

        painter.setPen(minuteColor);

        for (int j = 0; j < 60; ++j) {
            if ((j % 5) != 0)
                painter.drawLine(92, 0, 96, 0);
            painter.rotate(6.0);
        }
    }

Again, we draw markers around the edge of the clock, but this time to indicate minutes. We skip multiples of 5 to avoid drawing minute markers on top of hour markers.

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 44
  2. Microsoft ouvre aux autres compilateurs C++ AMP, la spécification pour la conception d'applications parallèles C++ utilisant le GPU 22
  3. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  4. RIM : « 13 % des développeurs ont gagné plus de 100 000 $ sur l'AppWord », Qt et open-source au menu du BlackBerry DevCon Europe 0
  5. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  6. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
  7. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
Page suivante

Le blog Digia au hasard

Logo

Déploiement d'applications Qt Commercial sur les tablettes Windows 8

Le blog Digia est l'endroit privilégié pour la communication sur l'édition commerciale de Qt, où des réponses publiques sont apportées aux questions les plus posées au support. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 4.1
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web