IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Le contenu de Qt4 > QtGui
        Fenêtre et transparence ?
        Comment changer de style de fenêtre ?
        Comment connaître les styles disponibles ?
        Comment dessiner dans un QWidget ?
        Pourquoi je n'arrive pas à dessiner sur n'importe quels widgets ?
        Comment ajouter un lien vers une page HTML ?
        Comment créer une page d'accueil ?
        Comment afficher une image dans mon interface ?
        Comment dégeler simplement une ihm ?
        Comment afficher un gif animé ?
        Comment avoir une icône animée ?
        Quel est le rapport entre Item View et Graphics View ?
        Comment valider des entrées utilisateurs dans une zone d'édition ?
        Comment créer un programme dans la zone de notification ?
        Comment réaliser des fenêtres modales et amodales ?
        Comment manipuler du texte sélectionné avec QTextCursor ?
        Comment utiliser les icônes par défaut de Qt ?
        3.2.1. Graphics View (2)
                Qu'est-ce que Graphics View ?
                Comment accélérer Graphics View ?
        3.2.2. Model View (4)
                Qu'est ce que Model View ?
                Comment trier un QTreeWidget ?
                Comment trier un QListWidget ?
                Comment effacer le contenu d'un QTableWidget ?



Fenêtre et transparence ?
auteur : Yan Verdavaine
Qt permet diverses actions pour jouer avec la transparence d'une fenêtre :

* Mask : à partir d'une image binaire (QBitmap), il est possible de spécifier quelle partie est visible ou non sur la fenêtre. Cette méthode s'applique à tous les éléments d'une fenêtre top-level. Par exemple la partie d'un bouton qui se trouve dans une zone transparente, ne sera pas dessinée. Pour utiliser un mask il faut créer une QBitmap et utiliser la fonction setMask (définie par QWidget) sur la widget parente.
Sur certains OS comme windows xp il est obligatoire d'enlever la décoration avec le flag Qt::FramelessWindowHint.

*opacité : permet de rendre translucide toute une fenêtre. Pour cela il faut utiliser la méthode setWindowOpacity (définie par QWidget) sur la widget parente. Cette méthode prend en paramètre une valeur réelle entre 0 (transparent) et 1 (opaque)

*TranslucentWidget : depuis la version 4.5, il est possible de spécifier que le background de la widget parente soit transparent. Il est ainsi possible de jouer avec la transparence des différents éléments et QPainter pour créer une fenêtre translucide. Contrairement aux deux autres méthodes, ceci ne s'applique qu'au background de la fenêtre parente et les éléments enfants ne sont pas modifiés. Pour utiliser cette option, il faut activer l'attribut Qt::WA_TranslucentBackground sur la widget parente : setAttribute(Qt::WA_TranslucentBackground, true);
Sur certains OS comme windows xp il est obligatoire d'enlever la décoration avec le flag Qt::FramelessWindowHint.

Remarque : ces trois méthodes peuvent être utilisées en même temps
Voici un exemple vous montrant les différentes possibilités
#include <QtGui>
 
// base
// drag &drop sur la widget pour la déplacer
// bouton fermer pour fermer l'application
// dessine un dégradé RGBA en fond
class BaseWidget : public QWidget
{
    //position dans le repere widget de click gauche
    QPoint p;
    QPolygon polygon;
    QLinearGradient gradient;

public:
    BaseWidget()
    :QWidget
    (
        0,
        //enleve la decoration windows et l'entrée dans la bar de tâche
        Qt::FramelessWindowHint | Qt::SubWindow
    )
    {
        resize(200,200);
 
        //bouton pour fermer l'application
        QPushButton *b = new QPushButton("fermer",this);
        QLayout *l= new QVBoxLayout(this);
        l->addWidget(b);
        connect(b,SIGNAL(clicked()),qApp,SLOT(quit()));
         //initialisation du polygone
        QVector<QPoint>  points;
        //même suite aléatoire pour chaque polygone
        qsrand(150);
        const int nbpoints = 100;
        const double r2PI = 2. * 3.14159265;
        for (int i = 0 ; i < nbpoints ; ++i)
        {
            float distance = 80.+20*qrand()/RAND_MAX;
            points << QPoint
                        (
                            100 + distance*cos(r2PI * i/nbpoints),
                            100 + distance*sin(r2PI * i/nbpoints)
                        );
        }
        polygon = QPolygon (points);
 
        //initialisation du gradient
        gradient.setStart (0. , 0.);
        gradient.setFinalStop (size().width() , 0.);
        {
             //Gradienstops pour varier l'apha et la couleur du gradient
            QGradientStops gs;
            gs  <<QGradientStop(0. , QColor(50 , 0   , 50  , 255))
                <<QGradientStop(.5 , QColor(0  , 255 , 255 , 100))
                <<QGradientStop(1. , QColor(50 , 50  , 0   , 255));
 
            gradient.setStops (gs);
        }
   
    }
protected:
    void mousePressEvent   ( QMouseEvent * mouseEvent )
    {
        //sauvegarde du point dans le repère widget lors du click gauche
        if(mouseEvent->buttons() == Qt::LeftButton)  p = mouseEvent->pos();
 
    }
    void mouseMoveEvent  ( QMouseEvent * mouseEvent )
    {
        //repositionne la fênetre en fonction de la postion de la souris
        if(mouseEvent->buttons() & Qt::LeftButton)     move( mouseEvent->globalPos() - p);
    }
    protected:
    void paintEvent(QPaintEvent * )
        {
            QPainter p(this);
            p.setPen(Qt::NoPen);
            //utilisation un gradient linéaire entre deux coin de la fenetre
            p.setBrush(gradient);
            p.drawPolygon(polygon);
        }
};
 
 
//Widget avec un fond translucide
class TranslucideWidget : public BaseWidget
{
    //position dans le repere widget de click gauche
    QPoint p;
public:
    TranslucideWidget()
    {
        //windows avec fond translucide
        setAttribute(Qt::WA_TranslucentBackground, true);
    }   
};
 
//Widget utilisant un mask
class MaskWidget : public BaseWidget
{
public:
    MaskWidget()
    {
        //création d'un mask sous forme de chessboard.
        QBitmap mask(5,5);
        {
            QPainter p(&mask);
            p.fillRect(mask.rect(),Qt::color0);
            p.setPen(Qt::color1);
            for (int i = 0 ; i < mask.height() ; ++i)
            for(int j = 0 ; j< mask.width() ; ++j)
            if( !(i%2 ^ j%2))
            p.drawPoint(j,i);
        }
        //retaille le mask a la taille de la fenetre
        mask = mask.scaled(size());
        //application du mask sur toute la widget
        setMask(mask);
    }
};
 
//Widget utilisant windowOpacity
class OpacityWidget : public BaseWidget
{
public:
    OpacityWidget()
    {
        //modifie l'opacite de la fenetre
        setWindowOpacity (.5);
    }    
};
 
 
class CompositionWidget : public BaseWidget
{
public:
    CompositionWidget()
    {
        //windows avec fond translucide
        setAttribute(Qt::WA_TranslucentBackground, true);
 
        //création d'un mask sous forme de chessboard.
         //création d'un mask sous forme de chessboard.
        QBitmap mask(5,5);
        {
            QPainter p(&mask);
            p.fillRect(mask.rect(),Qt::color0);
            p.setPen(Qt::color1);
            for (int i = 0 ; i < mask.height() ; ++i)
            for(int j = 0 ; j< mask.width() ; ++j)
            if( !(i%2 ^ j%2))
            p.drawPoint(j,i);
        }
        //retaille le mask a la taille de la fenetre
        mask = mask.scaled(size());
        //application du mask sur toute la widget
        setMask(mask);
 
 
        //modifie l'opacite de la denetre
        setWindowOpacity (.5);
    }
};
 
int main(int argc, char **argv)
{
    QApplication app(argc, argv);   
    TranslucideWidget translucideWidget;
    translucideWidget.show();
    translucideWidget.move(50,50);
 
    MaskWidget maskWidget;
    maskWidget.show();
    maskWidget.move(300,50);
 
    OpacityWidget opacityWidget;
    opacityWidget.show();
    opacityWidget.move(50,300);
 
    CompositionWidget compositionWidget;
    compositionWidget.show();
    compositionWidget.move(300 , 300);
 
    return app.exec();
}

Comment changer de style de fenêtre ?
auteurs : Matthieu Brucher, Benjamin Poulain
Par défaut, Qt utilise le style natif du système d'exploitation. Si vous voulez modifier le style, vous pouvez le faire au niveau de chaque widget à l'aide de QWidget::setStyle() ou au niveau de l'application complète avec QApplication::setStyle().

Voici par exemple comment utiliser le style "Plastique" pour toute l'application:

    QApplication::setStyle(new QPlastiqueStyle);
Remarque : il est possible de créer un style par son nom avec QStyleFactory::create() ou la fonction static QApplication::setStyle ().

Créer un style complet est généralement une tâche difficile. Heureusement Qt fournit un mécanisme simple pour personnaliser les styles: les CSS (Cascading Style Sheets). Avec CSS pour Qt, il est possible de personnaliser le design d'une application à l'aide d'une syntaxe simple dérivée des CSS de HTML. Cela peut se faire au niveau de designer, ou comme pour les styles classiques, au niveau des widgets ou de l'application.
Voici une exemple d'une feuille CSS de Qt:

QWidget {
     border: 1px solid gray;
     border-radius: 10px;
     padding: 1px 10px 1px 10px;
     margin: 3px;
 }
 
 QLineEdit:enabled {
     background: green;
 }
 QLineEdit:!enabled {
     background: grey;
 }
 QComboBox::drop-down {
     subcontrol-origin: padding;
     subcontrol-position: top right;
     width: 50px;
     border-radius: 0;
 }
lien : en Un exemple de création et d'utilisation de style sur le site de Trollech
lien : faq Comment connaître les styles disponibles ?
lien : en QApplication::setStyle ( const QString & style )
lien : en QStyleFactory

Comment connaître les styles disponibles ?
auteur : Benjamin Poulain
Les styles disponibles dépendent de la plateforme et des plugins. La classe QStyleFactory permet de lever toute ambiguïté en fournissant la liste des styles disponibles à l'exécutions. La méthode statique QStyleFactory::keys retourne une liste de nom de style qu'il est possible de charger. À partir des noms de cette liste, il est possible de charge les styles avec la méthode statique QStyleFactory::create. Notez qu'en général il est déconseillé de changer de style car l'application perd son intégration avec le reste du système.


Comment dessiner dans un QWidget ?
auteur : Yan Verdavaine
Lorsqu'un widget doit être dessiné ou redessiné, la fonction protégée QPaintEvent est appelée. Pour se dessiner, la majorité des widgets de Qt utilise un QPainter lors de l'appel de cette fonction. Il est donc naturel de suivre cette logique.

L'évènement QPaintEvent passé en paramètre indique la zone à redessiner. Cette zone est donnée sous forme de rectangle QPaintEvent::rect ou sous forme quelconque QRegion. Ces informations peuvent être utilisées pour optimiser l'affichage du widget.

La classe QPainter est un outil qui permet de dessiner sur toutes les classes graphique de Qt : QCustomRasterPaintDevice, QGLFramebufferObject, QGLPixelBuffer, QImage, QPicture, QPixmap, QPrinter, QSvgGenerator, et QWidget.

Cette classe utilise d'autres outils de Qt. Les plus importants à mon avis sont :

  • QPen : caractérise le contour d'une forme (ligne, point, contour d'une forme...)
  • QBrush : caractérise l'intérieur d'une forme (intérieur d'un rectangle...)
Voici un exemple :
dessiner sur une widget

#include <QtGui>

class MyTest : public QWidget
{
public:
    MyTest ( QWidget * parent = 0, Qt::WindowFlags f = 0 ) : QWidget  (parent,f){};
    void paintEvent ( QPaintEvent * event )
    {
        //creation d'un QPainter
        //QPen : aucun contour
        //QBrush : aucun remplissage
        QPainter painter(this);
        
        //On definie au QPainter un stylo rouge de taille 4
        QPen pen;
        pen.setColor (Qt::red);
        pen.setWidth (4);
        painter.setPen(pen);
        
        //On dessine un rectangle
        //QPen : rouge de taille 4
        //QBrush : aucun remplissage
        painter.drawRect (10, 10, 80, 80);
        
        //on definie au QPainter un pinceau vert utilisant le pattern SOLID
        QBrush brush(Qt::SolidPattern);
        brush.setColor(Qt::green);
        painter.setBrush(brush);
        
        //on dessine un rectangle
        //QPen : rouge de taille 4
        //QBrush : remplissage vert avec le pattern SOLID
        painter.drawRect (15, 15, 70, 70);
        
        
        //on definie au QPainter stylo bleu  de taille 8
        pen.setColor (Qt::blue);
        pen.setWidth (8);
        painter.setPen(pen);
        
        //dessine une ligne
        //QPen : bleu de taille 8
        //QBrush : n'est pas utilise pour une ligne
        painter.drawLine(0, 0, 100, 100);
    }
};

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MyTest win;
    win.resize(100, 100);
    win.show();
    return app.exec();
}

Pourquoi je n'arrive pas à dessiner sur n'importe quels widgets ?
auteur : Yan Verdavaine
Certaines widgets sont basées sur QAbstractScrollArea dont le but est de permettre l'affichage d'une widget plus grande que sa zone d'affichage. En ajoutant des scrollbar par exemple. Appliquer un painter directement sur celle-ci n'aura pas l'effet souhaité. Cette classe implémente la méthode viewport() qui permet d'accéder à la widget qui est réellement affichée. Il faut donc appliquer le painter sur celle-ci.

On constate ainsi trois étapes lors de la redéfinition du paintevent :
  • pre-dessin :le dessin en arrière plan
  • dessin originel : le dessin d'origine.
  • post-dessin : le dessin au premier plan.
Dessiner avec un QListView
#include <QtGui>
 
class myListView : public QListView
{
public:
    myListView()
    {}

protected:
    void paintEvent(QPaintEvent *event)
    {
       /*pre-dessin*/
        if (this->viewport())
        {
            QPainter painter(this->viewport());
            painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
            painter.drawRect(QRect(0,0,50,50));
        }
 
        /*dessin originel*/
        QListView::paintEvent(event);
 
        /*post-dessin*/
        if (this->viewport())
        {
            QPainter painter(this->viewport());
            painter.setBrush(QBrush(Qt::red, Qt::SolidPattern));
            painter.drawRect(QRect(25,25,50,50));  
        }
        event->accept();
    }
};
 
int main(int argc, char **argv) 
{
    QApplication app(argc, argv);
    QStringList list;
    list<<"dessiner"<<"avec"<<"un"<<"QListView";
 
    myListView w;
    w.setModel(new QStringListModel(list,&w));
    w.show();
    return app.exec();
}
Remarque: Comme le traitement pre-dessin se dessine en arrière plan, il peut être totalement effacé par le dessin originel ou le post-dessin


Comment ajouter un lien vers une page HTML ?
auteur : Yan Verdavaine
La façon la plus simple est d'utiliser un QLabel et ses possibilités de Rich text (http://doc.trolltech.com/4.3/richtext.html). Pour cela il suffit :

  • D'autoriser l'ouverture vers une page web
  • De remplir le label avec un petit morceau en HTML : <a href= 'site referencé'>XXXXX</a> . où XXX peut être
    • une phrase simple.
    • une phrase en HTML : <font size='S' family='...' color='C'> ... </font>
      • size : facultatif. Taille de la police
      • family : facultatif. Police à utiliser dans l'ordre de préférence
      • color : couleur du texte
      • Il est possible de compléter la phrase en utilisant les balises de formatage de texte comme gras(<b>...<\b>), italique ( <i>...</i> )...

  • une image en HTML : <img src='MON_IMAGE' height ='H' width= 'W'>
    • src : path de l'image à afficher. Peut se situer dans les ressources
    • height : facultatif. Hauteur de l'image
    • width : facultatif. Largeur de l'image
exemple avec un lien text et un lien image

#include <QtGui>
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QLabel label;
    //on ecrit un petit bout de html
    label. setText (    "La doc de"
                        //lien par un text HTML
                        "<a href='http://doc.trolltech.com/4.3/qlabel.html'>" 
                                "<font size='15' family='Arial, Helvetica, sans-serif' color='green'><b> Qt </b></font>" 
                        "</a>"
                        "est voici "
                        //lien par une image
                        "<a href='http://qt.developpez.com/faq/'>"
                            "<img src='FAQ-Qt.gif'>"
                        "</a>");
    //on autorise l'ouverture du lien vers le viewer par defaut
    label.setOpenExternalLinks ( true );
    label.show();
    return app.exec();
}

Comment créer une page d'accueil ?
auteur : Shugo78
Qt propose la classe QSplashScreen pour simplifier la gestion des pages de démarrage. Une page de démarrage est une image affichée lors du démarrage d'un programme, pour masquer un démarrage lent ou tout simplement par marketing.

Remarque :

  • Cette page se fermera si l'on clique dessus
  • QSplashScreen est lancé avant la boucle d'événement de l'application, il est donc préférable d'appeler QApplication::processEvents() de temps en temps pour traiter les événements en cours.

#include <QtGui>
#include <windows.h> //Sleep


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

    // Création de la page de demarrage
    QSplashScreen splash;
    //La page sera devant toute les fenetres
    splash.setWindowFlags ( Qt::WindowStaysOnTopHint);
    splash.setPixmap(QPixmap ("c:/figure1.jpg"));
    splash.show();

    //On ecrit sur l'image l'etape en cours
    splash.showMessage (QObject::tr ("Etape 1"), Qt::AlignRight | Qt::AlignTop, Qt::white);
    //On simule un traitement de durée 2s
    // /!\ pour Windows
    Sleep(2000);
     //On lance un traitement sur les evenements
    app .processEvents();

    //On change l'image
    splash.setPixmap(QPixmap ("c:/figure2.jpg"));
    //On ecrit sur l'image l'etape en cours
    splash.showMessage (QObject::tr ("Etape 2"), Qt::AlignRight | Qt::AlignTop, Qt::white);
    //On simule un traitement de durée 2s
    // /!\ pour Windows
    Sleep(2000);
    //On lance un traitement sur les evenements
    app .processEvents();

    QWidget w;
    w.show();
    //La page se fermera une fois le widget affiché
    splash.finish (&w);

    return app.exec ();
}

Comment afficher une image dans mon interface ?
auteur : IrmatDen
La méthode la plus simple est d'utiliser un QLabel conjointement à un QPixmap.

#include <QtGui>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QLabel label;
    //on donne l'image au label
    label.setPixmap(QPixmap("c :/image.png")); 
    label.show();
    QObject::connect(&label, SIGNAL(clicked()), &app, SLOT(quit()));
    return app.exec();
}

Comment dégeler simplement une ihm ?
auteur : Yan Verdavaine
Si une action longue est exécuté (ex :parcours récursif de répertoire, copie de plusieurs fichiers,...) par l'ihm, celle ci va se geler et ne plus répondre... Pour remédier à cela il est souvent préférable d'utiliser une thread.

Mais il existe une alternative intéressante lorsque ce traitement n'a vraiment aucun intérêt à être mis dans un thread : QCoreApplication (et donc QApplication ) possède la méthode static processevents permettant l'exécution dune partie ou de tous les events de l'eventloop.
Simulation d'un traitement long. L'un utilise le processevents l'autre non
#include <QtGui>
#include <cmath>
#include <ctime>
 
//Simule une action
double action_simulation(int nb =1000)
{
    double somme(0.);
    for (unsigned int j=0;j<nb;++j) somme+=sqrt(static_cast<double>(j));
    return somme;
}
 
 
class MyQPushButton : public QPushButton
{
    public :
    MyQPushButton(const QString & text, QWidget * parent = 0)
        :QPushButton (text,parent)
    {
        resize(75, 30);
        setFont(QFont("Times", 12, QFont::Bold));
    };
protected:
    //action lorsque le bouton est relache
    void mouseReleaseEvent ( QMouseEvent * event )
    {
        //progress bar infinie
        QProgressDialog mybar( "Wait ...", 0, 0, 0);
        mybar.setWindowModality(Qt::ApplicationModal);
        mybar.show();
 
        //simule une action lente de 5s
        double somme(0.);
        clock_t endwait;
        endwait = clock () + 5* CLOCKS_PER_SEC ;
        while (clock() < endwait)
        {
          somme+= action_simulation() ;
        }
        qDebug()<<somme;
    }
};
 
 
class MyQPushButton2 : public QPushButton
{
public :
    //createur.
    //text : text du boutton
    MyQPushButton2(const QString & text, QWidget * parent = 0)
    :QPushButton (text,parent)
    {
        resize(75, 30);
        setFont(QFont("Times", 12, QFont::Bold));
    };
protected :
    //action lorsque le bouton est relache
    void mouseReleaseEvent ( QMouseEvent * event )
    {
        //progress bar infinie
        QProgressDialog mybar( "Wait ...", 0, 0, 0);
        mybar.setWindowModality(Qt::ApplicationModal);
        mybar.show();
 
        //simule une action lente de 5s
        double somme(0.);
        clock_t endwait;
        endwait = clock () + 5 * CLOCKS_PER_SEC ;
        while (clock() < endwait)
        {
            QCoreApplication::processEvents();
            somme+= action_simulation() ;
        }
         qDebug()<<somme;
    }
};
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QWidget w;
    QVBoxLayout * vl = new QVBoxLayout;
    {
        //boutton : L'appliquation se bloque pendant le traitement
        MyQPushButton * bouton1 = new MyQPushButton("Sans QCoreApplication::processEvents()");
 
        //boutton : L'appliquation ne se bloque pas pendant le traitement
        MyQPushButton2 * bouton2 = new MyQPushButton2("Avec QCoreApplication::processEvents()");
 
        vl->addWidget(bouton1);
        vl->addWidget(bouton2);
    }
    w.setLayout(vl);
    w.show();
    return app.exec();
}

Comment afficher un gif animé ?
auteur : Yan Verdavaine
Comme un Gif animé est quelque chose de non statique, on ne peut pas afficher l'animation avec une QImage ou une QPixmap. Pour cela, Qt fournie une classe dédiée aux vidéos : QMovie.

La méthode la plus simple est de créer un QMovie avec le gif et de l'associer à un label.

#include <QtGui>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QLabel w;
    
    //On cree une video. Ici c'est un gif
    QMovie movie("c:/Mickey-11.gif");
    //On l'associe a un label
    w.setMovie (&movie);
    //On lance la video
    movie.start ();

    w.show();
    return app.exec();
}
Il faut tout de même préciser que la compilation du plugin Gif est nécessaire pour que ce code marche correctement.


Comment avoir une icône animée ?
auteur : Yan Verdavaine
Il peut être intéressant d'avoir des icônes qui évoluent dans le temps. Par exemple, une icône dans la barre des tâches qui donne l'avancement d'un traitement. Pour animer une QIcon, il suffit de remplacer l'image à utiliser à l'instant t.

Voici trois méthodes simples:

1- Un fichier image animé (gif, mng,...) et QMovie :
  • QMovie émet un signal à chaque changement d'image.
  • Il suffit de connecter un slot qui va récupérer l'image courante de QMovie
  • Icône peut être animée par la lecture de l'animation.
  • Possibilité de contrôler l'avancement de l'animation avec la méthode jumpToFrame
Le bouton permet de charger une image animée.
#include <QtGui>
 
class MyWindow : public QWidget
{
    Q_OBJECT
    //lecteur d'image animee
    QMovie      m_movie;
    //objets qui utilise une icone
    QPushButton *m_but;
    QSystemTrayIcon m_sysTray;
public :
    MyWindow( )
    {
        //layout et le boutton seront re-parente
        //par le setLayout
        QLayout * l = new QVBoxLayout;
        {
            m_but = new QPushButton;
            l->addWidget(m_but);
        }
        setLayout(l);
        //connect l'evenement updated pour changer d'image dans les icones
        connect(&m_movie, SIGNAL(updated ( const QRect & )),this,SLOT(nouvelleIcone()));
        //boutton : permet de prendre une autre images animee
        connect(m_but, SIGNAL(clicked( )),this,SLOT(nouvelleImageAnimee()));
 
        //ajout dans l'event loop
        QTimer::singleShot(0,this,SLOT(chargerImageAnimee()));
    }
private slots:
    //selection d'une image animee et lecture par le QMovie
    void chargerImageAnimee()
    {
        QString s =QFileDialog::getOpenFileName(this,"choisir une image animee",QString(),"*.gif *.mng");
        if (!s.isEmpty())
        {
           m_movie.stop();
           m_movie.setFileName(s);
           m_movie.start();
        }
      
    }
 
    //modifie l'icone pour le boutton, le systray et le titre de la fenetre
    void nouvelleIcone()
    {
        QIcon icon(m_movie.currentPixmap());
        //modifie l'icone du boutton
        m_but->setIcon(icon);
        //modifie l'icone du systray
        m_sysTray.setIcon(icon);
        m_sysTray.show();
        //modifie l'icone de la fenetre
        setWindowIcon(icon);
    }
  
};
//astuce pour ne pas avoir plusieurs fichiers
#include "main.moc"
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MyWindow w;
    w.show();
    return app.exec();
}
2- Une liste d'image :
  • A chaque évènement de changement d'image, on choisi l'image dans la liste
  • Un timer permet de faire évoluer l'animation de manière constante
Charge les images d'un répertoire dans une liste.
#include <QtGui>
 
class MyWindow : public QWidget
{
    Q_OBJECT
    //liste d'image
    QList<QPixmap>     m_lImages;
    //objets qui utilise une icone
    QPushButton *m_but;
    QSystemTrayIcon m_sysTray;
public :
    MyWindow( )
    {
        //layout et le boutton seront re-parente 
        //par le setLayout
        QLayout * l = new QVBoxLayout;
        {
             /*slider qui permet d'emuler l'avancement*/
            QSlider * slider = new QSlider(Qt::Horizontal);
            slider->setRange ( 0,100 );
            connect (slider,SIGNAL(valueChanged  ( int )),this,SLOT (nouvelleIcone(int)));
            l->addWidget(slider);
 
 
            m_but = new QPushButton;
            l->addWidget(m_but);
        }
        setLayout(l);
    
        //boutton : permet de prendre une autre images animee
        connect(m_but, SIGNAL(clicked( )),this,SLOT(chargerRepertoire()));
 
        //ajout dans l'event loop 
        QTimer::singleShot(0,this,SLOT(chargerImageAnimee()));
    }
private slots:
    //charger les image d'un repertoire dans une liste
    void chargerRepertoire()
    {
        QString s =QFileDialog::getExistingDirectory(this,"choisir une image animee",QString());
        m_lImages.clear();
        QDir d(s);
        QStringList filters;
        filters << "*.jpg" << "*.png" << "*.gif";
        //pour chaque fichier image du repertoire
        //on lie l'image et on l'ajoute dans la liste
        foreach(QString file,d.entryList (filters,QDir::Files))
        {
            QPixmap tmp(d.absolutePath()+"/"+file);
            if ( !tmp.isNull ())
                m_lImages<<tmp;
        }
 
    }
 
    //modifie l'icone pour le bouton, le systray et le titre de la fenêtre
    void nouvelleIcone(int pourcent)
    {
        if (m_lImages.size() == 0) 
            return;
 
        //on choisie l'image
        QIcon icon(m_lImages[pourcent%m_lImages.size()]);
        //modifie l'icone du boutton
        m_but->setIcon(icon);
        //modifie l'icone du systray
        m_sysTray.setIcon(icon);
        m_sysTray.show();
        //modifie l'icone de la fenetre
        setWindowIcon(icon);
    }
   
};
//astuce pour ne pas avoir plusieurs fichiers
#include "main.moc"
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MyWindow w;
    w.show();
    return app.exec();
}
3- Un QPainter :
  • A chaque évènement qui demande un changement de l'icône , on créé une nouvelle image avec un QPainter
  • La plus compliqué à mettre en place mais la plus puissante.
  • La création d'une nouvelle icône peut mettre du temps
Compose une image à partir de deux images
#include <QtGui>
 
class myWindows : public QWidget
{
    Q_OBJECT
public :
    myWindows()
    {
        QGridLayout * l = new QGridLayout;
        {
            /*slider qui permet d'emuler l'avancement*/
            QSlider * slider = new QSlider(Qt::Horizontal);
            slider->setRange ( 0,100 );
            connect (slider,SIGNAL(valueChanged  ( int )),this,SLOT (noucelleIcone(int)));
            l->addWidget(slider,0,0,1,3);
 
            /*bouton pour charge la premiere image*/
            QPushButton * b = new QPushButton("charger Pix1");
            connect(b,SIGNAL(clicked()),this,SLOT(OpenPix1()));
            /*label qui affiche la premiere image*/
            m_Apix1 =new  QLabel;
            l->addWidget(b,1,0);
            l->addWidget(m_Apix1,2,0);
       
            /*button qui affiche une l'icon calcule*/
            m_AresultIcone = new QPushButton;
            /*label qui affiche l'image clacule*/
            m_Aresult =new  QLabel;
            l->addWidget(m_AresultIcone,1,1);
            l->addWidget(m_Aresult,2,1);
       
            /*bouton pour charger la deusieme image*/
            QPushButton * b = new QPushButton("charger Pix2");
            connect(b,SIGNAL(clicked()),this,SLOT(OpenPix2()));
            /*label qui affiche la deusieme image*/
            m_Apix2 =new  QLabel;
            l->addWidget(b,1,2);
            l->addWidget(m_Apix2,2,2);
        }
        setLayout(l);
       
        m_trayIcon.show();
    }
 
 
private slots :
 
    void noucelleIcone(int percent)
    {
   
        //pixmap avec un fond transparent
        QPixmap resultImage(200,200);
        resultImage.fill(Qt::transparent);
        {
            QPainter painter(&resultImage);
 
            //precalcule des pourcentages de la hauteur
            float percent_1 = (100.- percent)/100.;
            float percent_2 =  percent/100.;
            
            //heut de l'image
            QRect target(0, 0, resultImage.width(), percent_1*resultImage.height());
            QRect source(0, 0, m_pix1.width(), percent_1*m_pix1.height());
            painter.drawPixmap(target, m_pix1, source);
            
            //bas de l'image
            QRect target2(0, percent_1*resultImage.height(), resultImage.width(), percent_2*resultImage.height());
            QRect source2(0, percent_1*m_pix2.height(), m_pix2.width(), percent_2*m_pix2.height());
            painter.drawPixmap(target2, m_pix2, source2);
        
            //pourcentage
            painter.setPen(QPen(Qt::black));
            painter.setFont(QFont("TAHOMA",80,20));
            painter.drawText(10,resultImage.height()/2,QString::number(percent));
        }
        QIcon  iconeCourante(resultImage);
        //affichage dans un label
        m_Aresult->setPixmap(resultImage);
        //affichage sous forme d'icone dans un bouton
        m_AresultIcone->setIcon(iconeCourante);
        //icone de la fenetre
        setWindowIcon (iconeCourante);
        //icone du systray
        m_trayIcon.setIcon(iconeCourante);
 
    }
    void OpenPix1()
    {
        static QString s;
        s =QFileDialog::getOpenFileName
            (
                this,
                "image 1",
                s,
                "images (*.jpg *.png *.bmp *.gif)\n *.*"
            );
        if (! s.isEmpty())
        {
            QPixmap tmp(s);
            m_pix1 = tmp.scaled(200,200,Qt::KeepAspectRatio);
            m_Apix1->setPixmap(m_pix1);
        }
    }
    void OpenPix2()
    {
        static QString s;
        s =QFileDialog::getOpenFileName
            (
                this,
                "image 2",
                s,
                "images (*.jpg *.png *.bmp *.gif)\n *.*"
            );
        if (! s.isEmpty())
        {
            QPixmap tmp(s);
            m_pix2 = tmp.scaled(200,200,Qt::KeepAspectRatio);
            m_Apix2->setPixmap(m_pix2);
        }
    }
private :
     QPixmap m_pix1;
     QPixmap m_pix2;
 
     QLabel * m_Apix1;
     QLabel * m_Apix2;
 
     QSystemTrayIcon m_trayIcon;
     QPushButton * m_AresultIcone;
     QLabel * m_Aresult;
};
 
#include "main.moc"
 
int main(int argc, char *argv[])
{
   
    QApplication app(argc,argv);
    myWindows w;
    w.show();
 
    return app.exec();
}

Quel est le rapport entre Item View et Graphics View ?
auteur : Benjamin Poulain
Il n'y a pas de liens de parenté entre ces deux là. Au début il arrive de se tromper entre Item View et Graphics View simplement car il y a "View" dans les deux noms. Graphics View permet de dessiner et gérer des objets 2D. Item View permet de gérer des éléments (les items), et de les représenter visuellement (en table, liste et arbre). Rien n'empêche de combiner ces deux infrastructures, mais il vaut mieux ne pas les confondre pour lire la documentation ou pour communiquer.


Comment valider des entrées utilisateurs dans une zone d'édition ?
auteur : François Jaffré
Qt fournit un mécanisme de gestion de la validation et de vérification des entrées utilisateurs dans une zone d'édition. La classe de base est la classe QValidator dont dérive les classes QDoubleValidator, QIntValidator, et QRegExpValidator. L'utilisation de ces classes est très simple au moins pour ce qui est des deux premières.

Exemple d'utilisation: On veut limiter l'entrée dans une zone d'édition de nombres entiers compris entre 0 et 100 et uniquement ce type de nombre.

//On définit un objet de type QIntValidator acceptant uniquement des nombre entier entre 0 et 100
QIntValidator* validator =  new QIntValidator (0, 100, this); 
//Création d'une zone d'édition : ici une QLineEdit
QLineEdit *edit= new QLineEdit(this); 
//On applique l'objet QIntValidator à la zone d'edition
edit->setValidator(validator); 
Le même principe est utilisable pour contrôler par exemple une valeur double avec QDoubleValidator. Si l'on souhaite un motif spécifique par exemple une adresse IP, un numéro de téléphone ou autre il faut utiliser la classe QRegExpValidator ou créer soit même un validator à partir d'une classe dérivant de QValidator.

lien : en QValidator

Comment créer un programme dans la zone de notification ?
auteur : François Jaffré
Qt depuis sa version 4.2 permet grâce à la classe QSystemTrayIcon de créer facilement des programmes ayant une entrée dans la zone de notification. Cela se fait à l'aide des quelques méthodes suivantes :

  • void setIcon (const QIcon & icon) -> Permet d'appliquer une image qui servira d'icon dans la zone de notification
  • void setContextMenu (QMenu * menu) -> Permet l'ajout d'un menu quand on fait un click droit sur l'icone se trouvant dans la zone de notification.
  • void showMessage (const QString & title, const QString & message, MessageIcon icon = Information, int millisecondsTimeoutHint = 10000) -> Permet l'affichage d'un popup dans la zone de notification.
Exemple

#include <QApplication>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QPushButton>
#include <QHBoxLayout>
 
class SysTray : public QWidget
{
    Q_OBJECT
 
private :
    QSystemTrayIcon* m_SystIcon;
    QPushButton* m_Bouton_Message;
 
 
public :
    SysTray()
    {
        //Bontou qui nou servira pour l'affichage de l'info bulle
        this->m_Bouton_Message = new QPushButton("Affiche text",this);
        
        //Gestion du Layout pour l'affichage
        QHBoxLayout *layout = new QHBoxLayout();
        layout->addWidget(m_Bouton_Message);
        this->setLayout(layout);
         
        //Création de l'objet gérant l'entré dans la zone de notification
        m_SystIcon = new QSystemTrayIcon(this);
         
        //Création du menu qui apparaitera apres un click droit sur l'icon
        QMenu* sysTrayMenu = new QMenu(this);
        
        //Création des differents actions pour le menu de la zone de notification
        QAction* hide = new QAction("Hide",this);
        QAction* show = new QAction("Show",this);
        QAction* quit = new QAction("Quit",this);
         
        
        //On ajoute nos actions au menu system
        sysTrayMenu->addAction(hide);
        sysTrayMenu->addAction(show);
        sysTrayMenu->addAction(quit);
         
        //On lie le menu avec l'icon
        m_SystIcon->setContextMenu(sysTrayMenu);
        
        //On charge l'image dans l'object icon
        QIcon unIcon("windows.png");
        
        //On place notre image dans la zone de notification
        m_SystIcon->setIcon(unIcon);
        
        //Affichage de l'icone dans la zone de notification 
        m_SystIcon->show();
        
        //On ferme si la personne click sur "Quit" 
        connect(quit, SIGNAL(triggered()), this, SLOT(close()));
        //On affiche la fenetre si la personne click sur "Show"
        connect(show, SIGNAL(triggered()), this, SLOT(show()));
        //On cache la fenetre si la personne click sur "Hide"
        connect(hide, SIGNAL(triggered()), this, SLOT(hide()));
        //On affiche une info bulle dans la zone de notification
        connect(m_Bouton_Message, SIGNAL(clicked(bool)), this, SLOT(Affiche(bool))); 
    }
 
private slots:
    void Affiche(bool valid)
    {
        //Affichage de l'info bulle
        m_SystIcon->showMessage
                (
                "Bavo !",
                "Vous venez de créer une application dans la zone de notification !"
                );
    }
 
};
 
#include "main.moc"
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    SysTray w;
    w.show();
    return a.exec();
}
Remarque : La méthode showMessage() (arrivée à partir de Qt 4.3) qui fait apparaitre une info bulle est dépendante des paramètres de l'OS.

lien : en QSystemTrayIcon
lien : en QSystemTrayIcon::showMessage
lien : fr Tutoriel sur QSystemTrayIcon

Comment réaliser des fenêtres modales et amodales ?
auteur : François Jaffré
Qt permet comme tous les framworks gérant les GUI, la création de fenêtre modale (fenêtre bloquant l'accès aux autres fenêtres du programme) et amodale (fenêtre indépendante des autres fenêtres du programme). La classe de base gérant les boites de dialogues est QDialog. Celle-ci gère le mode modale ou amodale de la fenêtre au partir des méthodes suivantes :

  • bool isModal () const -> Permet de savoir si la boite de dialogue est modale ou pas.
  • void setModal (bool modal) -> Permet de définir si la boite de dialogue est modale ou pas (Par défaut une boite de dialogue Qt est amodale).
  • int exec() -> Force l'affichage de la boite de dialogue en mode modale (la valeur définie par setModal() est ignorée).
  • void show() -> Force l'affichage de la boite de dialogue.
  • void hide() -> Permet de cacher la boite de dialogue.
Création de boites de dialogues modales et amodales

#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>
#include <QDialog>
#include <QLabel>
 
class AmodaleDial : public QDialog 
{
    Q_OBJECT
 
private :
    QLabel * m_Label;
 
public :
    AmodaleDial(QWidget *parent): QDialog(parent)//Contructeur de la fenêtre amodale
    {
        //Création du label contenu dans la fenêtre
        m_Label = new QLabel("Cette fenêtre n'est pas modal", this); 
        m_Label->resize(100,50);
        //Gestion du layout
        QHBoxLayout* layout = new QHBoxLayout();
        layout->addWidget(m_Label);
        setLayout(layout);
    }
 
};
 
class ModaleDial : public QDialog 
{
    Q_OBJECT
 
private :
QLabel* m_Label;
 
public :
    //Contructeur de notre fenêtre
    ModaleDial(QWidget *parent): QDialog(parent)
    {
        //Création du label contenu dans la fenêtre
        m_Label = new QLabel ("Cette fenêtre est modale", this); 
        m_Label->resize(100,50);
        QHBoxLayout* layout = new QHBoxLayout();
        layout->addWidget(m_Label);
        setLayout(layout);
    }
 
};
 
class Window : public QDialog 
{
    Q_OBJECT
 
private :
    QPushButton* m_Bouton_ModaleFrame;
    QPushButton* m_Bouton_AmodaleFrame;
    //Pointeur sur notre fenêtre qui sera amodale
    AmodaleDial* m_amodaleDial;
     
public :
    Window()
    {
        //Création des differents bouton
        m_Bouton_ModaleFrame = new QPushButton("Modale Frame", this);
        m_Bouton_AmodaleFrame = new QPushButton("Amodale Frame", this);
        //Gestion du layout
        QHBoxLayout* layout = new QHBoxLayout();
        layout->addWidget(m_Bouton_ModaleFrame);
        layout->addWidget(m_Bouton_AmodaleFrame);
        setLayout(layout);
        //Instanciation de notre fenêtre qui sera amodale
        m_amodaleDial = new AmodaleDial(this);
        //Connections des different signaux slots pour gérer le click
        connect(this->m_Bouton_ModaleFrame, SIGNAL(clicked(bool)), this, SLOT(clickModale(bool)));
        connect(this->m_Bouton_AmodaleFrame, SIGNAL(clicked(bool)), this, SLOT(clickAmodale(bool)));
    }
 
private slots:
    void clickModale(bool valid)
    {
        //Création de notre fenêtre modale
        ModaleDial modaleDial(this);
        //On rend visible et modale notre fenêtre avec la methode exec()
        modaleDial.exec();
    }
     
    void clickAmodale(bool valid)
    {
        //On rend visible notre fenêtre amodale qui par default est amodale
        m_amodaleDial->show();
    }
 
};
 
#include "main.moc"
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window w;
    w.show();
    return a.exec();
}
Remarque : Tout les QWidgets et par conséquent leurs classes dérivé peuvent être modal en modifiant leur propriétés windowModality à l'aide de la méthode setWindowModality(). Cependant il est préférable de gérer ce type de boite de dialogue à partir d'une QDialog et nom d'un QWidget.

lien : en QDialog
lien : en QWidget::setWindowModality

Comment manipuler du texte sélectionné avec QTextCursor ?
auteur : Louis du Verdier
Les curseurs sont très utilisés dans les classes pouvant les accueillir (comme l'autorisent par défaut QTextEdit, QTextBrowser et d'autres classes encore).

Pour retrouver la sélection courante qu'à faite l'utilisateur d'un programme, il suffit d'utiliser la fonction selectedText() de la manière qui suit :
// QString QTextCursor::selectedText () const
widget->textCursor().selectedText();
Notes : Cette fonction, retournant un QString, peut parfaitement être vide (ou empty en anglais).

Il est de même possible de supprimer la sélection courant à l'aide de removeSelectedText() :
// void QTextCursor::removeSelectedText ()
widget->textCursor().removeSelectedText();
Note : La suppression du texte sélectionné ne se produira que s'il y a lieu d'une sélection.

L'insertion de texte avec l'assistance des curseurs s'effectue avec insertText() qui entre du texte à partir de la position du curseur.
// void QTextCursor::insertText ( const QString & text, const QTextCharFormat & format )
widget->textCursor().insertText("Chaine de type QString");
Voici un exemple, reprenant ce qui est inscrit ci-dessus, permettant d'effectuer une modification sur un texte sélectionné sans pour autant modifier plusieurs chaines identiques :
 // ...
zoneTexte = new QTextEdit(this); 
connect(zoneTexte, SIGNAL(selectionChanged()), this, SLOT(transformer()));
// ...
 
void XXXXXXXX::transformer()
{
    // On garde en mémoire le texte sélectionné
    QString selectionTexte(zoneTexte->textCursor().selectedText()); 
    // On supprime celui-ci sans pour autant supprimer les chaines identiques
    zoneTexte->textCursor().removeSelectedText(); 
    // Et on effectue l'opération voulue au départ
    zoneTexte->textCursor().insertText("<italique>" + selectionTexte + "</italique>"); 
}
lien : en QTextCursor

Comment utiliser les icônes par défaut de Qt ?
auteur : François Jaffré
Qt fournit dans son framework des icônes standards comme flèches, fichier, dossiers, lecteur DVD, corbeille, etc. La récupération de ces icônes se fait à l'aide de la classe QStyle avec la méthode suivante :
QIcon QStyle::standardIcon (StandardPixmap standardIcon, const QStyleOption * option = 0, const QWidget * widget = 0) const 
Qui permet de récupérer l'icône choisi à partir de l'énumération StandardPixmap.

Exemple d'utilisation en appliquant un icone flèche sur un bouton :
//Création d'un contrôle ici un bouton
QPushButton button;
//On récupère un pointeur sur l'objet QStyle correspondant à l'application
QStyle* style =  QApplication::style();
//On récupère l'icône désiré ici une flèche pointant vers le haut 
QIcon iconFleche = style->standardIcon(QStyle::SP_ArrowUp);
//On applique notre icônes à notre contrôle
button.setIcon(iconFleche);
lien : en QStyle::StandardIcon
lien : en Liste des icons standard


Consultez les autres F.A.Q's


Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.