<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C++, Qt et GPU &#187; QtQuick</title>
	<atom:link href="https://blog.developpez.com/gpu/?cat=20&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/gpu</link>
	<description></description>
	<lastBuildDate>Fri, 24 May 2013 17:02:21 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Développez en natif pour Android avec Qt 5.1</title>
		<link>https://blog.developpez.com/gpu/?p=522</link>
		<comments>https://blog.developpez.com/gpu/?p=522#comments</comments>
		<pubDate>Thu, 23 May 2013 11:24:04 +0000</pubDate>
		<dc:creator><![CDATA[gbdivers]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Facile]]></category>
		<category><![CDATA[Qt5]]></category>
		<category><![CDATA[QtQuick]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/gpu/?p=522</guid>
		<description><![CDATA[La sortie de Qt 5.1 est prévue en release candidat pour le 27 mai. Cette version propose le support d&#8217;Android et iOS, bien qu&#8217;il était déjà possible de porter sur Android avec Qt 4.8 et le projet Necessitas. Je vais &#8230; <a href="https://blog.developpez.com/gpu/?p=522">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>La sortie de Qt 5.1 est prévue en release candidat pour le 27 mai. Cette version propose le support d&rsquo;Android et iOS, bien qu&rsquo;il était  déjà possible de porter sur Android avec Qt 4.8 et le projet <a href="http://www.developpez.net/forums/d1278983/plateformes/android-necessitas-port-android-qt-integre-au-qt-project/">Necessitas</a>. Je vais vous présenter ici comment créer une application Qt pour Android sous Ubuntu 13.04.</p>
<p><span id="more-522"></span></p>
<h1>Vue d&rsquo;ensemble</h1>
<p>Avant de commencer, une remarque sur Windows. À priori, il est possible de travailler sur Windows. Cependant, les binaires Qt pour Android ne sont disponibles que pour Linux. Comme la compilation de Qt pour Windows est pénible et que je ne l&rsquo;ai pas faite depuis longtemps, je présente seulement l&rsquo;utilisation de Linux. Pour ceux qui aimeraient pouvoir utiliser Windows&#8230; tant pis pour vous <img src="https://blog.developpez.com/gpu/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>Je n&rsquo;avais pas testé Qt sur Android depuis quelques temps, en fait depuis Qt 4.8 et Necessitas. Du coup, j&rsquo;ai découvert le portage Android dans Qt 5.1 en même temps que je prenais des notes pour cet article. Comme base de travail, je suis parti des pages des pages de documentation de Qt : <a href="http://doc-snapshot.qt-project.org/qt5-stable/qtdoc/android-support.html">Qt &#8211; Android support</a>.</p>
<p>L&rsquo;utilisation de Qt sur Android nécessite l&rsquo;installation de plusieurs outils :</p>
<ul>
<li>la version de <a href="http://download.qt-project.org/development_releases/qt/5.1/5.1.0-beta1/">Qt 5.1 pour Android</a> : ok, on s&rsquo;y attendait un peu. Contient la bibliothèque complète et Qt Creator ;</li>
<li>le <a href="http://developer.android.com/sdk/index.html">kit de développement (SDK) pour Android</a> : permet de créer des applications Java pour Android et un simulateur pour tester ses applications ;</li>
<li>le <a href="http://developer.android.com/tools/sdk/ndk/index.html">kit de développement natif (NDK) pour Android</a> : permet de créer des applications C++ pour Android ;</li>
<li>l&rsquo;<a href="http://openjdk.java.net/install/index.html">environnement d&rsquo;exécution de Java (JRE)</a> : nécessaire pour le SDK Android ;</li>
<li><a href="http://ant.apache.org/bindownload.cgi">Apache Ant</a> : pour faire beau. (bon ok, ce n&rsquo;est pas que pour faire beau, ça sert au déploiement. Mais comme c&rsquo;est un outil Java, je ne connais pas du tout).</li>
</ul>
<p>Dans ce tutoriel, je vais montrer l&rsquo;utilisation de Qt Creator, mais il doit être possible d&rsquo;utiliser d&rsquo;autres outils.</p>
<h1>Installations</h1>
<h2>Installation de OpenJDK 7</h2>
<p>Pour commencer, il faut installer l&rsquo;environnement d&rsquo;exécution de Java. Il est fort possible qu&rsquo;il soit déjà installé. Dans la documentation, il est indiqué qu&rsquo;il faut par exemple OpenJDK en version 6 ou plus récente.</p>
<p><del datetime="2013-05-24T14:58:09+00:00">Personnellement, j&rsquo;avais la version 7. Cependant, j&rsquo;ai eu des problème avec Apache Ant, qui me retournait une erreur. J&rsquo;ai donc dû installer la version 6 en plus. Comme j&rsquo;ai pas mal bidouillé, je ne suis pas sûr de la procédure. Si des personnes testent et remarquent des problèmes, n&rsquo;hésitez pas à me le signaler.</del></p>
<p><em>Merci à <a href="http://www.developpez.net/forums/u657013/rotoom/">rotoOm</a> qui m&rsquo;a indiqué l&rsquo;origine du problème. Il suffit en fait d&rsquo;installer le JDK en plus du JRE. Merci à lui pour l&rsquo;information.</em></p>
<p>Vous pouvez tester si Java est installé avec la ligne de commande suivante :</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">java -version</div></div>
<p>Pour l&rsquo;installation, j&rsquo;ai donc utilisé les paquets fournis par Ubuntu. Il faut donc juste taper ces lignes de commande :</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo apt-get install openjdk-6-jre<br />
sudo apt-get install openjdk-7-jdk</div></div>
<p>Pour les autres systèmes Linux, vous pouvez consulter la page de documentation d&rsquo;OpenJDK : <a href="http://openjdk.java.net/install/index.html">How to download and install prebuilt OpenJDK packages</a>.</p>
<h2>Installation d&rsquo;Apache Ant</h2>
<p>Pour l&rsquo;installation d&rsquo;Apache Ant, même méthode, j&rsquo;utilise les paquets Ubuntu :</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo apt-get -u install ant</div></div>
<p>Pour tester l&rsquo;installation d&rsquo;Apache Ant, vous pouvez taper la ligne de commande suivante :</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ant -version</div></div>
<h2>Installation du SDK Android</h2>
<h3>Pourquoi installer le kit de développement Java ?</h3>
<p>Pour commencer, on ne peut se poser une question : pourquoi installer le kit de développement Java et le kit de développement natif et pas simplement ce dernier ? La réponse est simple : parce qu&rsquo;on ne peut développer que en Java pour Android !</p>
<p>Ok&#8230;</p>
<p>Donc cela veut dire qu&rsquo;il faudra utiliser le binding Java de Qt ? On parlait pas de développement C++ dans ce tutoriel ?</p>
<p>Oui, pas d&rsquo;inquiétude <img src="https://blog.developpez.com/gpu/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /> En fait, il y a un point à savoir sur les applications natives C++ sur Android. C&rsquo;est une application Java qui appelle un &laquo;&nbsp;module&nbsp;&raquo; écrit en C++ (on utilise le terme &laquo;&nbsp;activité&nbsp;&raquo; en Java). Avec Qt, on va donc simplement créer notre code C++/Qt et Qt Creator va s&rsquo;occuper de créer l&rsquo;application Java qui appelle notre code.</p>
<p>Ouf !</p>
<h3>Installation</h3>
<p>L&rsquo;installation du SDK Android est simple aussi&#8230; puisqu&rsquo;il n&rsquo;y a pas d&rsquo;installation à faire. Vous devez simplement télécharger le <a href="http://developer.android.com/sdk/index.html">kit de développement pour Android</a> et décompresser l&rsquo;archive. Ce SDK contient les outils de développement Android, des plateformes de compilation, l&rsquo;éditeur Eclipse ADT (Android Developer Tools, configuré spécialement pour Android), un simulateur Android pour tester ses applications.</p>
<p>Pour installer d&rsquo;autres outils, par exemple d&rsquo;autres versions de plateforme, vous pouvez utiliser le SDK Manager. Dans Eclipse ADT, allez dans le menu Windows puis Android SDK Manager.</p>
<h3>Tester Eclipse</h3>
<p>Comme je suis curieux et que j&rsquo;ai envie de voir un peu comment fonctionne une application Java sur Android, j&rsquo;ai testé un peu Eclipse et Java. Ceux qui ne sont pas intéressés, vous pouvez passer directement à l&rsquo;installation du NDK.</p>
<p>Pour cela, j&rsquo;ai simplement suivi le tutoriel : <a href="http://developer.android.com/training/basics/firstapp/index.html">Building Your First App</a> (il faut reconnaître que la documentation est très claire et simple à suivre, même pour un développeur C++ comme moi).</p>
<p>Allez dans le répertoire d&rsquo;installation du SDK Android puis dans le répertoire eclipse/. Celui-ci contient un binaire eclipse, que vous lancez. Si c&rsquo;est la première utilisation d&rsquo;Eclipse, il va falloir faire quelques réglages de configuration. En premier le Workspace (l&rsquo;espace de travail d&rsquo;Eclipse, dans lequel il range les fichiers). Personnellement, j&rsquo;ai accepté toutes les valeurs par défaut.</p>
<p>Une fois qu&rsquo;Eclipse est lancé, créez un nouveau projet de type &laquo;&nbsp;Android Application Project&nbsp;&raquo; dans Fichier puis Créer un projet. Un dialogue permet de donner un nom à votre application (c&rsquo;est le nom qui apparaîtra sur le téléphone), la version minimale d&rsquo;Android à prendre en charge et la version Android de destination. J&rsquo;ai laissé par défaut. Vous pouvez ensuite choisir l&rsquo;icône de l&rsquo;application et le type d&rsquo;activité. Choisissez BlanckActivity, qui va créer une activité &laquo;&nbsp;hello world&nbsp;&raquo;.</p>
<p>Après quelques minutes (je vais rien dire que la lenteur d&rsquo;Eclipse&#8230;), un projet est créé, qui contient quelques fichiers et répertoires. Les plus importants sont :</p>
<ul>
<li>le fichier AndroidManifest.xml : contient les informations sur l&rsquo;application, en particulier les versions minimale et ciblée de la plateforme ;</li>
<li>le répertoire res/layout/ : contient les interfaces de l&rsquo;application, décrites dans des fichiers XML ;</li>
<li>le répertoire src/ : contient les sources Java du projet. Dans ce projet par défaut, il lance simplement une activité, qui affiche l&rsquo;interface décrite dans le fichier XML de layouts/ ;</li>
<li>les répertoires res/drawable-xxx/ : contient les images de l&rsquo;application.</li>
</ul>
<p>Comme c&rsquo;est une application Android, vous ne pouvez pas simplement la lancer comme une application de Bureau classique. Il existe deux méthodes pour la lancer : utiliser un simulateur ou déployer sur un téléphone.</p>
<h3>Tester l&rsquo;application sur simulateur</h3>
<p>Pour cela, il faut dans un premier temps créer un simulateur. Le SDK Android est fournit avec un gestionnaire, permettant de créer différentes configurations pour le simulateur, permettant ainsi de tester l&rsquo;application sur plusieurs types de téléphone.</p>
<p>Allez dans le menu Windows puis Android Virtual Device Manager. Dans le dialogue, créez un nouveau périphérique en cliquant sur &laquo;&nbsp;New&nbsp;&raquo;, puis configurez selon le type de téléphone que vous voulez tester. Par exemple, comme j&rsquo;ai un téléphone Samsung Galaxy S1, j&rsquo;ai choisit un écran 4&Prime; en 480*800. Après la création du périphérique, lancez-le.</p>
<p>Lancez ensuite l&rsquo;application en ouvrant le fichier java (dans src/) puis en cliquant sur le bouton Run. Un dialogue &laquo;&nbsp;Run As&#8230;&nbsp;&raquo; s&rsquo;ouvre pour choisir comment exécuter l&rsquo;application. Choisissez Android Application. Normalement, l&rsquo;application devrait se lancer.</p>
<h3>Tester l&rsquo;application sur téléphone</h3>
<p>Bon, un simulateur, c&rsquo;est bien, mais on aimerait avoir l&rsquo;application sur un vrai téléphone pour tester. Ce n&rsquo;est pas très compliqué non plus, mais il va falloir faire une manipulation sur le téléphone. Celle-ci permet d&rsquo;activer les fonctionnalités de développement du téléphone, en particulier le Debug Mode USB, qui permet de déployer des applications via un cable USB.</p>
<p>Pour Android 4.2, allez dans les paramètres puis dans le menu À propos du téléphone. Cliquez plusieurs fois sur Numéro de build par activer le mode développeur. Vous allez avoir un message confirmant le passage en mode Debug. Revenez ensuite à l&rsquo;écran précédent et allez dans les options de développeur. Activez le mode Debug USB. Pour les autres versions d&rsquo;Android, vous pouvez consulter la page suivante : <a href="http://developer.android.com/training/basics/firstapp/running-app.html#RealDevice">Run on a Real Device</a>.</p>
<p>Pour terminer, il suffit de brancher le téléphone sur l&rsquo;ordinateur avec un câble USB puis de lancer l&rsquo;application comme précédemment. L&rsquo;application devrait se lancer sur le téléphone.</p>
<h2>Installation du NDK Android</h2>
<p>Rien de compliqué ici non plus, il n&rsquo;y a pas d&rsquo;installation à faire, il faut simplement décompresser l&rsquo;archive.</p>
<h2>Installation de Qt Android</h2>
<p>Le plus simple, comme indiqué au début de ce tutoriel, est d&rsquo;utiliser les binaires fournis de <a href="http://download.qt-project.org/development_releases/qt/5.1/5.1.0-beta1/">Qt 5.1 pour Android</a>. Si vous n&rsquo;utilisez pas Ubuntu, il vous faudra compiler Qt vous-même. Bon courage <img src="https://blog.developpez.com/gpu/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>Lancez le binaire Qt pour Android. Le processus d&rsquo;installation est classique, avec une particularité : le SDK propose par défaut l&rsquo;installation de Qt Desktop, mais pour Android (versions ARM ou x86), il faut l&rsquo;activer soi-même. Une fois l&rsquo;installation finie, allez dans les répertoires Tools, QtCreator, bin puis lancez qtcreator.</p>
<p>La première étape va être de configurer Android. Pour cela, allez dans le menu Outils puis Options. Dans la liste de gauche, allez dans Android, puis configurez les répertoires du SDK et du NDK. Cochez la case pour laisser Qt Creator créer automatiquement les kits de compilation.</p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/android.png"><img src="http://blog.developpez.com/gpu/files/2013/05/android-300x188.png" alt="android" width="300" height="188" class="aligncenter size-medium wp-image-555" /></a></p>
<p>Il faut ensuite créer un périphérique pour le simulateur si ce n&rsquo;est pas encore fait. Pour cela, cliquez sur le bouton Start Android AVD Manager. </p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/avd-manager.png"><img src="http://blog.developpez.com/gpu/files/2013/05/avd-manager.png" alt="avd manager" width="680" height="500" class="aligncenter size-full wp-image-556" /></a></p>
<p>Cliquez sur New pour créer un nouveau périphérique. Choisissez le type de Device (pour simuler mon Galaxy S, j&rsquo;ai donc choisit un 4&Prime; en 480*800). N&rsquo;oubliez pas d&rsquo;activer la prise en charge du GPU (Use Host GPU) pour que Qt puisse utiliser OpenGL ES.</p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/new-device.png"><img src="http://blog.developpez.com/gpu/files/2013/05/new-device.png" alt="new device" width="480" height="709" class="aligncenter size-full wp-image-558" /></a></p>
<p>Pour créer une application Qt, allez dans le menu Fichier puis Nouveau projet. Choisissez un projet compatible avec Android (par exemple Application Graphique Qt ou Application Qt Quick 2 (élément de base)).</p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/new-project.png"><img src="http://blog.developpez.com/gpu/files/2013/05/new-project.png" alt="new project" width="1440" height="900" class="aligncenter size-full wp-image-559" /></a></p>
<p>Dans un premier temps, le simulateur se lance.</p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/simulator.png"><img src="http://blog.developpez.com/gpu/files/2013/05/simulator.png" alt="simulator" width="481" height="827" class="aligncenter size-full wp-image-561" /></a></p>
<p>Puis l&rsquo;application à la fin du déploiement.</p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/run-simulator.png"><img src="http://blog.developpez.com/gpu/files/2013/05/run-simulator.png" alt="run simulator" width="714" height="829" class="aligncenter size-full wp-image-560" /></a></p>
<p>Pour déployer sur un téléphone (préalablement passé en mode Debug USB, voir au début), il suffit simplement de le brancher, Qt Creator lancera alors l&rsquo;application dessus.</p>
<p><a href="http://blog.developpez.com/gpu/files/2013/05/IMG_4736.jpg"><img src="http://blog.developpez.com/gpu/files/2013/05/IMG_4736.jpg" alt="IMG_4736" width="477" height="900" class="aligncenter size-full wp-image-557" /></a></p>
<h1>Conclusion</h1>
<p>Rien de très compliqué finalement. Le déploiement est relativement simple une fois que les outils sont configurés. Reste plus qu&rsquo;à tester les performances. <img src="https://blog.developpez.com/gpu/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>Pour ceux qui sont intéressés par Qt Quick, je rappelle le livre auquel je participe : <a href="http://www.d-booker.fr/110-qt-5-les-essentiels.html">Créer des applications avec Qt 5 &#8211; Les essentiels</a>. J&rsquo;ai en particulier participé à la rédaction de Qt Quick. C&rsquo;est encore une pré-version du livre final, mais il y a déjà pas mal de choses sur Qt Quick. Et n&rsquo;hésitez pas à me dire s&rsquo;il y a des points que vous souhaiteriez voir abordés dans ce livre.</p>
<p>Si vous êtes intéressé par Qt Quick sur mobile, je fais une présentation le 5 juin à Paris. Contactez-moi par MP pour plus d&rsquo;informations.</p>
<p>Merci à <a href="http://www.developpez.net/forums/u39401/prgasp77/">prgasp77</a> et <a href="http://www.developpez.net/forums/u329028/winjerome/">winjerome</a> pour leur relecture orthographique.</p>
<p><a href="http://www.developpez.net/forums/d1346162/qt/developpez-en-natif-pour-android-avec-qt-51/">N&rsquo;hésitez pas à commenter cet article sur le forum.</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vidéos d&#8217;installation de Qt 5</title>
		<link>https://blog.developpez.com/gpu/?p=411</link>
		<comments>https://blog.developpez.com/gpu/?p=411#comments</comments>
		<pubDate>Fri, 10 May 2013 22:29:56 +0000</pubDate>
		<dc:creator><![CDATA[gbdivers]]></dc:creator>
				<category><![CDATA[Facile]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Qt5]]></category>
		<category><![CDATA[QtQuick]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/gpu/?p=411</guid>
		<description><![CDATA[Bonjour à tous Un problème que l&#8217;on revoit souvent sur le forum est l&#8217;installation de Qt 5. J&#8217;ai réalisé, dans le cadre du livre sur Qt auquel je participe (Créer des applications avec Qt 5 &#8211; Les essentiels), plusieurs vidéos &#8230; <a href="https://blog.developpez.com/gpu/?p=411">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Bonjour à tous</p>
<p>Un problème que l&rsquo;on revoit souvent sur le forum est l&rsquo;installation de Qt 5. J&rsquo;ai réalisé, dans le cadre du livre sur Qt auquel je participe (<a href="http://www.d-booker.fr/110-qt-5-les-essentiels.html">Créer des applications avec Qt 5 &#8211; Les essentiels</a>), plusieurs vidéos pour expliquer comment installer et tester l&rsquo;installation.</p>
<p>Il y a quatre vidéos pour le moment : </p>
<ul>
<li>installation sur Windows avec Microsoft Visual C++ 2010 ;</li>
<li>installation sur Windows avec MinGW ;</li>
<li>installation sur Linux en utilisant les binaires ;</li>
<li>installation sur Ubuntu en utilisant les dépôts.</li>
</ul>
<p>Les vidéos sont disponibles sur le site de l&rsquo;éditeur : <a href="http://www.youtube.com/playlist?list=PLJ0RWFYCJZYF1pxD5FlAFqQVYkmebeTUY">D-booker.fr (YouTube)</a>.</p>
<p>Je n&rsquo;ai pas fait de prise son, donc penser à activer les sous-titres pour avoir les explications. J’essaierais de proposer prochainement d&rsquo;autres vidéos d&rsquo;installation (sur Mac, sur Raspberry Pi) ou des démos.</p>
<p>Bonne visualisation (et bonne lecture à ceux qui liront le livre ;))</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un ColorPicker avec Qt – Version QML</title>
		<link>https://blog.developpez.com/gpu/?p=366</link>
		<comments>https://blog.developpez.com/gpu/?p=366#comments</comments>
		<pubDate>Fri, 15 Feb 2013 18:31:20 +0000</pubDate>
		<dc:creator><![CDATA[gbdivers]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Facile]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[QtQuick]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/gpu/?p=366</guid>
		<description><![CDATA[Cet article est la solution que j’avais proposé à l’exercice Qt sur la création d’un ColorPicker (voir le première article de cette série). Dans cette partie, j&#8217;utilise le QML pour créer le ColorPicker. L&#8217;objet QML ColorPicker L&#8217;objet ColorPicker permet d&#8217;afficher &#8230; <a href="https://blog.developpez.com/gpu/?p=366">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Cet article est la solution que j’avais proposé à l’exercice Qt sur la création d’un ColorPicker (<a href="http://blog.developpez.com/gpu/p11791/difficulte/facile/un-colorpicker-avec-qt-enonce-de-lexercice">voir le première article de cette série</a>). Dans cette partie, j&rsquo;utilise le QML pour créer le ColorPicker.<br />
<span id="more-366"></span></p>
<h1>L&rsquo;objet QML ColorPicker</h1>
<p>L&rsquo;objet ColorPicker permet d&rsquo;afficher les nuances de gris d&rsquo;une couleur et de sélectionner une nuance directement en cliquant dans l&rsquo;item. Les composantes des couleurs sont manipulées directement puisqu&rsquo;il n&rsquo;est pas possible d&rsquo;extraire les composantes d&rsquo;une couleur donnée en QML.<br />
La couleur principale est définie par les variables main_red, main_green et main_blue. La couleur sélectionnée est récupérée grâce aux variables selected_red, selected_green et selected_blue dans le contexte ColorPickerContext.</p>
<p>La taille de l&rsquo;item est fixée à 256&#215;256 :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">import Qt <span style="color:#800080;">4.7</span><br />
Item<br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; width<span style="color: #008080;">:</span> <span style="color: #0000dd;">256</span><br />
&nbsp; &nbsp; height<span style="color: #008080;">:</span> <span style="color: #0000dd;">256</span></div></td></tr></tbody></table></div>
<p>Pour dessiner les nuances de gris, on va utiliser deux gradients linéaires :</p>
<ul>
<li>le premier, horizontal, va du blanc à la couleur principale ;</li>
<li>le second, vertical, va du transparent au noir.</li>
</ul>
<p>Pour créer les gradients, on commence par définir un rectangle ayant les mêmes dimensions et position que l&rsquo;item :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Rectangle<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; anchors.<span style="color: #007788;">fill</span><span style="color: #008080;">:</span> parent<br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>On utilise ensuite l&rsquo;objet gradient pour remplir le rectangle avec le dégradé. Par exemple pour le second gradient :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Rectangle<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; anchors.<span style="color: #007788;">fill</span><span style="color: #008080;">:</span> parent<br />
&nbsp; &nbsp; &nbsp; &nbsp; gradient<span style="color: #008080;">:</span> Gradient<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GradientStop <span style="color: #008000;">&#123;</span> position<span style="color: #008080;">:</span> <span style="color:#800080;">0.0</span><span style="color: #008080;">;</span> color<span style="color: #008080;">:</span> Qt.<span style="color: #007788;">rgba</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GradientStop <span style="color: #008000;">&#123;</span> position<span style="color: #008080;">:</span> <span style="color:#800080;">1.0</span><span style="color: #008080;">;</span> color<span style="color: #008080;">:</span> Qt.<span style="color: #007788;">rgba</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>On obtient ainsi un gradient vertical allant du transparent au noir. Pour le premier gradient, il faut donc effectuer une rotation du rectangle de 90° après l&rsquo;avoir correctement dimensionné et positionné :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Rectangle<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; width<span style="color: #008080;">:</span> parent.<span style="color: #007788;">height</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; height<span style="color: #008080;">:</span> parent.<span style="color: #007788;">width</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; transform<span style="color: #008080;">:</span> Rotation <span style="color: #008000;">&#123;</span> angle<span style="color: #008080;">:</span> <span style="color: #0000dd;">90</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; x<span style="color: #008080;">:</span> parent.<span style="color: #007788;">width</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; y<span style="color: #008080;">:</span> <span style="color: #0000dd;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; gradient<span style="color: #008080;">:</span> Gradient<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GradientStop <span style="color: #008000;">&#123;</span> position<span style="color: #008080;">:</span> <span style="color:#800080;">0.0</span><span style="color: #008080;">;</span> color<span style="color: #008080;">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Qt.<span style="color: #007788;">rgba</span><span style="color: #008000;">&#40;</span>main_red, main_green, main_blue, <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GradientStop <span style="color: #008000;">&#123;</span> position<span style="color: #008080;">:</span> <span style="color:#800080;">1.0</span><span style="color: #008080;">;</span> color<span style="color: #008080;">:</span> <span style="color: #FF0000;">&quot;white&quot;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Pour visualiser la position de la couleur sélectionnée, on va afficher un cercle entourant la dernière position connue. Cependant, dessiner un cercle en QML est un peu complexe (il faut créer des objets path pour dessiner des courbes quadratiques et constituer le cercle). Pour simplifier, on va afficher une image de taille 8&#215;8 pixels représentant un cercle avec le fond transparent :</p>
<p><img src="http://blog.developpez.com/gpu/files/2013/02/curseur.png" class="aligncenter" /></p>
<p>On crée un objet image en indiquant la source du fichier. Par défaut, la taille de l&rsquo;image est celle du fichier chargé :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Image<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; source<span style="color: #008080;">:</span> <span style="color: #FF0000;">&quot;cursor.png&quot;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Par défaut, on souhaite que le curseur soit placé au centre de l&rsquo;item. Pour cela, on utilise les variables x et y :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Image<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; x<span style="color: #008080;">:</span> width<span style="color: #000040;">/</span><span style="color: #0000dd;">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; y<span style="color: #008080;">:</span> height<span style="color: #000040;">/</span><span style="color: #0000dd;">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; source<span style="color: #008080;">:</span> <span style="color: #FF0000;">&quot;cursor.png&quot;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Pour déplacer, le curseur en fonction de la position de la souris, il faut pouvoir identifier cette image :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Image<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; id<span style="color: #008080;">:</span> cursor<br />
&nbsp; &nbsp; &nbsp; &nbsp; x<span style="color: #008080;">:</span> width<span style="color: #000040;">/</span><span style="color: #0000dd;">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; y<span style="color: #008080;">:</span> height<span style="color: #000040;">/</span><span style="color: #0000dd;">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; source<span style="color: #008080;">:</span> <span style="color: #FF0000;">&quot;cursor.png&quot;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>On pourra alors déplacer l&rsquo;image en modifiant les variables x et y, en ajoutant le code suivant n&rsquo;importe où dans notre item :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; cursor.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span><br />
&nbsp; &nbsp; cursor.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span></div></td></tr></tbody></table></div>
<p>Pour terminer, il faut pouvoir récupérer les évènements souris survenant sur notre item. Cela est réalisé en créer un objet MouseArea de même dimension que l&rsquo;item :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; MouseArea<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; anchors.<span style="color: #007788;">fill</span><span style="color: #008080;">:</span> parent<br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Il faut ensuite demander à cette MouseArea de récupérer les clics sur le bouton gauche de la souris :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; MouseArea<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; anchors.<span style="color: #007788;">fill</span><span style="color: #008080;">:</span> parent<br />
&nbsp; &nbsp; &nbsp; &nbsp; acceptedButtons<span style="color: #008080;">:</span> Qt.<span style="color: #007788;">LeftButton</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>On va réagir à deux types d’évènements : un clic sur le bouton gauche, qui déclenche un évènement de type onPressed, et le déplacement de la souris avec le bouton enfoncé, qui déclenche un évènement de type onPositionChanged.<br />
Lors de ces évènements, on récupère la position de la souris grâce aux variables mouseX et mouseY que l&rsquo;on affecte aux positions de l&rsquo;image avec cursor.x et cursor.y. Cependant, il ne faut pas oublier que la position de cursor correspond au coin en haut à gauche de l&rsquo;image alors que la souris correspond au centre de l&rsquo;image. Il faut donc corriger en fonction des dimensions de l&rsquo;image :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; cursor.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> mouseX <span style="color: #000040;">-</span> <span style="color: #0000dd;">4</span><br />
&nbsp; &nbsp; cursor.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> mouseY – <span style="color: #0000dd;">4</span></div></td></tr></tbody></table></div>
<p>Pour terminer, après un changement de la couleur sélectionnée, il faut recalculer les variables selected_red, selected_green et selected_blue. Pour cela, on appelle un fonction JavaScript updateSelectedColor(), qu&rsquo;il faudra créer :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; MouseArea<br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; anchors.<span style="color: #007788;">fill</span><span style="color: #008080;">:</span> parent<br />
&nbsp; &nbsp; &nbsp; &nbsp; acceptedButtons<span style="color: #008080;">:</span> Qt.<span style="color: #007788;">LeftButton</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; onPressed<span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> mouseX <span style="color: #000040;">-</span> <span style="color: #0000dd;">4</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> mouseY <span style="color: #000040;">-</span> <span style="color: #0000dd;">4</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; onPositionChanged<span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> mouseX <span style="color: #000040;">-</span> <span style="color: #0000dd;">4</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> mouseY <span style="color: #000040;">-</span> <span style="color: #0000dd;">4</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Pour connaître la couleur sélectionnée, on ne dispose pas de fonction équivalente à Qimage::pixel(). Les seuls éléments que l&rsquo;on dispose sont : la position (x, y) de la couleur sélectionnée dans le widget de taille (width, height) et les composantes RGB de la couleur principale.<br />
Il faut donc calculer les composantes RGB de la couleur sélectionnée à partir de ces éléments et de la méthode utilisée pour dessiner l&rsquo;item.</p>
<p>Lorsque l&rsquo;on dessine le premier gradient, on va du blanc (1, 1, 1) à la couleur principale (R, G, B). Le rapport entre la position cursor.x et la largeur est équivalent au rapport entre la composante de la couleur principale et le blanc :</p>
<p><img src="http://blog.developpez.com/gpu/files/2013/02/composantes.png" class="alignnone" /></p>
<p>On obtient alors l&rsquo;équivalence suivante :</p>
<p>{r &#8211; 1} over {X} ~ = ~ {R &#8211; 1} over {width} ~ = ~ pente de la droite</p>
<p>Alors :</p>
<p>r ~ = ~ 1 ~ + ~ (R-1) {X} over {width} </p>
<p>De même pour les autres composantes :</p>
<p>g ~ = ~ 1 ~ + ~ (G-1) {X} over {width} newline<br />
b ~ = ~ 1 ~ + ~ (B-1) {X} over {width} </p>
<p>Lorsque l&rsquo;on dessine le second gradient, on va du transparent (alpha = 0) au noir (0, 0, 0, 1). La couleur final s&rsquo;écrit :</p>
<p>couleur finale ~ = ~ couleur initiale * (1 &#8211; alpha) ~ + ~ noir * alpha ~ = ~ couleur initiale * (1-alpha)</p>
<p>La transparence alpha est liée à la position cursor.y par :</p>
<p>alpha ~ = ~ {Y} over {height} </p>
<p>On obtient donc la formule suivante pour la composante rouge :</p>
<p>r&rsquo; ~ = ~ r * (1 &#8211; {Y} over {height} ) newline<br />
r&rsquo; ~ = ~ (1 + (R-1) {X} over {width}) * (1 &#8211; {Y} over {height} )</p>
<p>De même pour les autres composantes :</p>
<p>g&rsquo; ~ = ~ (1 + (G-1) {X} over {width}) * (1 &#8211; {Y} over {height} ) newline<br />
b&rsquo; ~ = ~ (1 + (B-1) {X} over {width}) * (1 &#8211; {Y} over {height} )</p>
<p>La fonction JavaScript s&rsquo;écrit alors, en utilisant ces formules :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; function updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ColorPickerContext.<span style="color: #007788;">selected_red</span> <span style="color: #000080;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000040;">-</span> <span style="color: #008000;">&#40;</span>cursor.<span style="color: #007788;">y</span> <span style="color: #000040;">/</span> height<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000040;">+</span> <span style="color: #008000;">&#40;</span>cursor.<span style="color: #007788;">x</span> <span style="color: #000040;">/</span> width<span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #008000;">&#40;</span>main_red <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ColorPickerContext.<span style="color: #007788;">selected_green</span> <span style="color: #000080;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000040;">-</span> <span style="color: #008000;">&#40;</span>cursor.<span style="color: #007788;">y</span> <span style="color: #000040;">/</span> height<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000040;">+</span> <span style="color: #008000;">&#40;</span>cursor.<span style="color: #007788;">x</span> <span style="color: #000040;">/</span> width<span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #008000;">&#40;</span>main_green <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ColorPickerContext.<span style="color: #007788;">selected_blue</span> <span style="color: #000080;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000040;">-</span> <span style="color: #008000;">&#40;</span>cursor.<span style="color: #007788;">y</span> <span style="color: #000040;">/</span> height<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #000040;">+</span> <span style="color: #008000;">&#40;</span>cursor.<span style="color: #007788;">x</span> <span style="color: #000040;">/</span> width<span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #008000;">&#40;</span>main_blue <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<h1>La classe GradientWidget</h1>
<p>Pour utiliser cet item QML dans du code C++, il est nécessaire d&rsquo;écrire un wrapper pour récupérer les signaux et slots de l&rsquo;item. Cette classe n&rsquo;est pas un widget et dérive donc de QObject (pour pouvoir utiliser le système de signaux et slots) :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> GradientWidget <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> QObject<br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; Q_OBJECT</div></td></tr></tbody></table></div>
<p>Pour récupérer la couleur sélectionnée, il faut créer une variable pour chaque composante et utiliser la macro Q_PROPERTY pour la rendre accessible en QML. Il faut également définir les fonctions d&rsquo;écriture (pour modifier la variable depuis le QML) et de lecture (pour lire la variable à l&rsquo;extérieur de la classe) :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; Q_PROPERTY<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">float</span> &nbsp; &nbsp;selected_red<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;READ &nbsp; &nbsp; selectedRed<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WRITE &nbsp; &nbsp;setSelectedRed<span style="color: #008000;">&#41;</span><br />
<br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">float</span> &nbsp; selected_red<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">float</span> &nbsp; selectedRed<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> selected_red<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;setSelectedRed<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> red<span style="color: #008000;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span> selected_red <span style="color: #000080;">=</span> red<span style="color: #008080;">;</span> selectedColorChanged<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Après avoir mis à jour la couleur avec la fonction setSelectedColor(), il faut émettre un signal contenant la couleur créée à partir des composantes :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">signals<span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;colorSelected<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> QColor <span style="color: #000040;">&amp;</span>color<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;selectedColorChanged<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; emit colorSelected<span style="color: #008000;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; QColor<span style="color: #008080;">::</span><span style="color: #007788;">fromRgbF</span><span style="color: #008000;">&#40;</span>selected_red, selected_green, selected_blue<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Il faut également définir les variables et fonctions pour les deux autres composantes :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Q_PROPERTY<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">float</span> &nbsp; &nbsp;selected_green<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;READ &nbsp; &nbsp; selectedGreen<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WRITE &nbsp; &nbsp;setSelectedGreen<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; Q_PROPERTY<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">float</span> &nbsp; &nbsp;selected_blue<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;READ &nbsp; &nbsp; selectedBlue<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WRITE &nbsp; &nbsp;setSelectedBlue<span style="color: #008000;">&#41;</span></div></td></tr></tbody></table></div>
<p>La création de l&rsquo;item ColorPicker est réalisée dans le constructeur de la classe :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; GradientWidget<span style="color: #008000;">&#40;</span>QWidget <span style="color: #000040;">*</span>parent <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Dans ce constructeur, il faut créer un objet QDeclarativeView pour afficher l&rsquo;item QML puis fournir le code QML à l&rsquo;aide la fonction setSource. La taille est fixée à 256&#215;256, comme dans le code QML. Dans cet exemple, le code QML est fournit dans un fichier .qml et référencé dans un fichier ressource .qrc :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">GradientWidget</span><span style="color: #008000;">&#40;</span>QWidget <span style="color: #000040;">*</span>parent<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008080;">:</span> QObject<span style="color: #008000;">&#40;</span>parent<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; view <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> QdeclarativeView<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; view<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>resize<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">256</span>, <span style="color: #0000dd;">256</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; view<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>setSource<span style="color: #008000;">&#40;</span>QUrl<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;qrc:/qml/colorpicker.qml&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Pour permettre au code QML de transmettre les variables contenant les composantes de la couleur sélectionnée, il faut récupérer le contexte par défaut de la vue et définir une propriété ColorPickerContext dans celui-ci. Cette propriété permet d&rsquo;accéder à l&rsquo;objet dans le code QML à partir de la variable ColorPickerContext et permettre ainsi d&rsquo;accéder aux propriétés définies ci-dessus :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; context <span style="color: #000080;">=</span> view<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>rootContext<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; context<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>setContextProperty<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;ColorPickerContext&quot;</span>, <span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Les variables view et context sont définies dans l&rsquo;en-tête de la classe par :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; QDeclarativeView<span style="color: #000040;">*</span> &nbsp; &nbsp; &nbsp; view<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; QDeclarativeContext<span style="color: #000040;">*</span> &nbsp; &nbsp;context<span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Lors de la création de l&rsquo;item, on attribue également une couleur principale par défaut à l&rsquo;aide de la fonction setMainColor() :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; setMainColor<span style="color: #008000;">&#40;</span>Qt<span style="color: #008080;">::</span><span style="color: #007788;">red</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Cette fonction setMainColor() est un slot ayant un paramètre, la couleur a attribuer :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">public</span> slots<span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;setMainColor<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> QColor <span style="color: #000040;">&amp;</span>color<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Pour transmettre cette couleur au code QML, on utilise la fonction setContextProperty(), qui permet d&rsquo;attribuer une valeur à une variable QML :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">setMainColor</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> QColor <span style="color: #000040;">&amp;</span>color<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; context<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>setContextProperty<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;main_red&quot;</span>, color.<span style="color: #007788;">redF</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; context<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>setContextProperty<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;main_green&quot;</span>, color.<span style="color: #007788;">greenF</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; context<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>setContextProperty<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;main_blue&quot;</span>, color.<span style="color: #007788;">blueF</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Pour terminer, il faut créer les fonctions show() et move() pour pouvoir afficher et déplacer la vue :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;show<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;move<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> x, <span style="color: #0000ff;">int</span> y<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">show</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; view<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>show<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">move</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> x, <span style="color: #0000ff;">int</span> y<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; view<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>move<span style="color: #008000;">&#40;</span>x, y<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<h1>Le résultat final</h1>
<p>Voici le rendu obtenu :</p>
<p><img src="http://qt.developpez.com/exercices/01-colorpicker/1-degrade/gbdivers_qml/gbdivers_qml_capture.png" class="aligncenter" /></p>
<p><a href="http://qt.developpez.com/exercices/01-colorpicker/1-degrade/gbdivers_qml/gbdivers_qml_sources.zip">Télécharger les sources de cet article.</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un ColorPicker avec Qt &#8211; Version Qt</title>
		<link>https://blog.developpez.com/gpu/?p=353</link>
		<comments>https://blog.developpez.com/gpu/?p=353#comments</comments>
		<pubDate>Fri, 15 Feb 2013 18:04:33 +0000</pubDate>
		<dc:creator><![CDATA[gbdivers]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Facile]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[QtQuick]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/gpu/?p=353</guid>
		<description><![CDATA[Cet article est la solution que j&#8217;avais proposé à l&#8217;exercice Qt sur la création d&#8217;un ColorPicker (voir l&#8217;article précédent du blog). Il décrit la création d&#8217;un widget permettant d&#8217;afficher et sélectionner les nuances de gris d&#8217;une couleur. Conception Le widget &#8230; <a href="https://blog.developpez.com/gpu/?p=353">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Cet article est la solution que j&rsquo;avais proposé à l&rsquo;exercice Qt sur la création d&rsquo;un ColorPicker (voir <a href="http://blog.developpez.com/gpu/p11791/difficulte/facile/un-colorpicker-avec-qt-enonce-de-lexercice">l&rsquo;article précédent du blog</a>). Il décrit la création d&rsquo;un widget permettant d&rsquo;afficher et sélectionner les nuances de gris d&rsquo;une couleur.<br />
<span id="more-353"></span></p>
<h1>Conception</h1>
<p>Le widget devra simplement afficher un fond (les nuances de gris d&rsquo;une couleur) et gérer les évènements de la souris (clique et déplacement pour sélectionner une nuance de gris).</p>
<p>Il est possible de partir de plusieurs classes différentes pour créer le nouveau widget. Voyons les avantages et inconvénients de chacune :</p>
<ol>
<li>QWidget est la classe parent de tous les widgets de Qt. Elle fournit l&rsquo;interface de base commune de tous les objets visibles. Par défaut, elle n&rsquo;affiche rien et ne fait rien.</li>
<li>QScrollArea est destinée à afficher le contenu d&rsquo;un widget dans un autre, en gérant les barres de déplacement horizontale et verticale. Dans cet exercice, la présence de barre de déplacement n&rsquo;est pas souhaitée et il est préférable d&rsquo;ajuster la taille de la zone de dessin à la taille du widget.</li>
<li>QLabel permet d&rsquo;afficher un texte ou une image sans interaction avec l&rsquo;utilisateur. Même s&rsquo;il est possible de surcharger les fonctions de gestion des évènements souris, utiliser cette classe pour créer noter widget revient à ne pas respecter la conception de QLabel.</li>
<li>QpushButton permet également d&rsquo;afficher des images mais gère aussi les évènements souris. Mais cette classe n&rsquo;est pas destiner à gérer la position précise des évènements souris et de réagir différemment en fonction de celle-ci.</li>
</ol>
<p>Au final, même si certaine classe présentent des fonctionnalités qui seraient intéressantes (affichage d&rsquo;images, gestion des clics), seule l&rsquo;utilisation de QWidget respecte la conception des objets Qt.</p>
<p>En partant de QWidget, quels seront les fonctions qu&rsquo;il faudra implémenter ?</p>
<ol>
<li>L&rsquo;affichage des nuances de gris sera réalisée dans la fonction paintEvent(), qui prend en charge le dessin du widget. Il suffit de dessiner les nuances de gris puis la position de la couleur sélectionnée par un petit cercle.</li>
<li>La création des nuances de gris peut être réalisée directement dans paintEvent(). Cependant, cela implique de redessiner l&rsquo;image à chaque déplacement de la souris, ce qui peut rendre le widget non fluide. De plus, la récupération de la couleur sélectionnée utilisera la fonction QImage::pixel(). Au final, il est donc préférable de dessiner les nuances de gris dans une QImage et d&rsquo;afficher cette QImage dans la fonction paintEvent(). Cette image sera recalculée que lors d&rsquo;un changement de la couleur principale ou lors du redimensionnement du widget.</li>
<li>La fonction resizeEvent() sera utilisée pour mettre à jour l&rsquo;image contenant les nuances de gris.<br />
Les évènements souris seront gérés par les fonctions mousePressEvent(), mouseMoveEvent() et mouseReleaseEvent().</li>
<li>Le changement de couleur principale et la sélection d&rsquo;une couleur utilisera le système de signaux et slots, pour faciliter l&rsquo;interaction entre les widgets.</li>
</ol>
<p>Pour dessiner les différentes nuances de gris d&rsquo;un couleur, deux méthodes sont envisageables :</p>
<ol>
<li>Dessiner deux gradients superposés : un premier gradient linéaire, horizontal, allant du blanc (à gauche) à la couleur principale (à droite) ; un second gradient linéaire, horizontal, allant du transparent (en haut) au noir (en bas).</li>
<li>Faire varier les composantes S (saturation) et V (valeur) d&rsquo;une couleur en fonction des coordonnées (x, y) d&rsquo;un pixel. La saturation permet d&rsquo;aller du blanc (S=0) à la couleur (S=255) et correspond donc à l&rsquo;axe horizontal. La valeur permet d&rsquo;aller du noir (V=0) à la couleur (V=255) et correspond donc à l&rsquo;axe vertical.</li>
</ol>
<p>Ces deux méthodes sont identique visuellement (mais présentent en réalité des petites différences) et permettent toute deux d&rsquo;afficher toutes les nuances de gris d&rsquo;une couleur.</p>
<h1>Interface</h1>
<p>Pour créer l&rsquo;interface de notre classe, on crée une classe GradientWidget héritant de Qwidget, avec son constructeur :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> GradientWidget <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> QWidget<br />
<span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> GradientWidget<span style="color: #008000;">&#40;</span>QWidget <span style="color: #000040;">*</span>parent <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Les fonctions de gestion des évènements surchargent les fonctions de même nom de QWidget :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;mouseMoveEvent<span style="color: #008000;">&#40;</span>QMouseEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;mousePressEvent<span style="color: #008000;">&#40;</span>QMouseEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;mouseReleaseEvent<span style="color: #008000;">&#40;</span>QMouseEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;paintEvent<span style="color: #008000;">&#40;</span>QPaintEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;resizeEvent<span style="color: #008000;">&#40;</span>QResizeEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>La connexion avec les autres widgets est assurée par le signal envoyé lors de la sélection d&rsquo;une couleur et le slot reçu lors du changement de couleur principale :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">signals<span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;colorSelected<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> QColor <span style="color: #000040;">&amp;</span>color<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">public</span> slots<span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;setMainColor<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> QColor <span style="color: #000040;">&amp;</span>color<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Les variables privées permettent de conserver les couleurs principale et sélectionnée, l&rsquo;image dans laquelle on dessine les nuances de gris, la position du curseur et une variable boolean indiquant si la mouvement de la souris correspond à un clic ou non :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; QColor &nbsp;m_main_color<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; QColor &nbsp;m_selected_color<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; QImage &nbsp;m_gradient_image<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; QPen &nbsp; &nbsp;m_cursor_pen<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> &nbsp; &nbsp; m_cursor_diameter<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; QPoint &nbsp;m_cursor_position<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">bool</span> &nbsp; &nbsp;m_tracking<span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Les variab Pour finir, deux fonctions privées, permettant de redessiner les nuances de gris et de mettre à jour la couleur sélectionnée :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #666666;">// private membres</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;updateGradientImage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">void</span> &nbsp; &nbsp;updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<h1>Implémentation</h1>
<p>Commençons par l&rsquo;implémentation de la fonction updateSelectedColor(). Celle-ci récupère simplement la couleur du pixel de m_gradient_image à la position m_cursor_position, émet le signal colorSelected() puis appelle la fonction update() pour mettre ajour le widget :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">updateSelectedColor</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; m_selected_color <span style="color: #000080;">=</span> m_gradient_image.<span style="color: #007788;">pixel</span><span style="color: #008000;">&#40;</span>m_cursor_position<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; emit colorSelected<span style="color: #008000;">&#40;</span>m_selected_color<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; update<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<h2>Création des nuances avec QLinearGradient</h2>
<p>La première version de la fonction updateGradientImage() utilise l&rsquo;approche à deux gradients :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">updateGradientImage</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span></div></td></tr></tbody></table></div>
<p>On crée une QPixmap de la taille du widget puis un QPainter pour dessiner dedans. Par défaut, nous n&rsquo;avons pas besoin de dessiner des traits donc on supprime le QPen :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; QPixmap pixmap<span style="color: #008000;">&#40;</span>size<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; QPainter painter<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>pixmap<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; painter.<span style="color: #007788;">setPen</span><span style="color: #008000;">&#40;</span>QPen<span style="color: #008000;">&#40;</span>Qt<span style="color: #008080;">::</span><span style="color: #007788;">NoPen</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Pour dessiner des gradients linéaires, Qt propose une classe QLinearGradient. Il suffit donc de préciser les positions des points du gradient et les couleurs de ces points. Pour le premier gradient, les couleurs doivent aller du blanc (Qt::white) à la position (0, 0) à la couleur m_main_color à la position (with, 0) :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; QLinearGradient h_gradient<span style="color: #008000;">&#40;</span>QPointF<span style="color: #008000;">&#40;</span><span style="color:#800080;">0.0</span>, <span style="color:#800080;">0.0</span><span style="color: #008000;">&#41;</span>, QPointF<span style="color: #008000;">&#40;</span>width<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, <span style="color:#800080;">0.0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; h_gradient.<span style="color: #007788;">setColorAt</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>, Qt<span style="color: #008080;">::</span><span style="color: #007788;">white</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; h_gradient.<span style="color: #007788;">setColorAt</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, m_main_color<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Puis on dessine un rectangle de la taille du widget :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; painter.<span style="color: #007788;">setBrush</span><span style="color: #008000;">&#40;</span>QBrush<span style="color: #008000;">&#40;</span>h_gradient<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; painter.<span style="color: #007788;">drawRect</span><span style="color: #008000;">&#40;</span>rect<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Pour le second gradient, les couleurs doivent aller du transparent (Qt::transparent) à la position (0, 0) au noir (Qt::black) couleur m_main_color à la position (0, height) :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; QLinearGradient v_gradient<span style="color: #008000;">&#40;</span>QPointF<span style="color: #008000;">&#40;</span><span style="color:#800080;">0.0</span>, <span style="color:#800080;">0.0</span><span style="color: #008000;">&#41;</span>, QPointF<span style="color: #008000;">&#40;</span><span style="color:#800080;">0.0</span>, height<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; v_gradient.<span style="color: #007788;">setColorAt</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>, Qt<span style="color: #008080;">::</span><span style="color: #007788;">transparent</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; v_gradient.<span style="color: #007788;">setColorAt</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, Qt<span style="color: #008080;">::</span><span style="color: #007788;">black</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; painter.<span style="color: #007788;">setBrush</span><span style="color: #008000;">&#40;</span>QBrush<span style="color: #008000;">&#40;</span>v_gradient<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; painter.<span style="color: #007788;">drawRect</span><span style="color: #008000;">&#40;</span>rect<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>On convertit ensuite la Qpixmap en Qimage et on la conserve dans m_gradient_image :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; m_gradient_image <span style="color: #000080;">=</span> pixmap.<span style="color: #007788;">toImage</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Pour finir, puisse que le gradient à été mis à jour, on met également à jour la couleur sélectionnée :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<h2>Création des nuances avec HSV</h2>
<p>La seconde version de updateGradientImage() utilise deux boucles imbriquées qui parcourent l&rsquo;ensemble des pixels de l&rsquo;image et qui calcul la couleur en faisant varier la saturation et la valeur en fonction de la position (x, y). Pour commencer, il faut redimensionner l&rsquo;image de destination si celle-ci n&rsquo;est pas identique aux dimensions du widget :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">updateGradientImage</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_gradient_image.<span style="color: #007788;">rect</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> rect<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_gradient_image <span style="color: #000080;">=</span> QImage<span style="color: #008000;">&#40;</span>size<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, Qimage<span style="color: #008080;">::</span><span style="color: #007788;">Format_RGB32</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>La teinte est obtenue à partir de la couleur principale :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #0000ff;">float</span> h <span style="color: #000080;">=</span> m_main_color.<span style="color: #007788;">hsvHueF</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>On parcourt l&rsquo;ensemble des pixels de l&rsquo;image à l&rsquo;aide de deux boucles imbriquées :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> s<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> s<span style="color: #000080;">&lt;</span>width<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>s<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> v<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> v<span style="color: #008000;">&#40;</span>height<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">/</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008080;">?</span> Qt<span style="color: #008080;">::</span><span style="color: #007788;">white</span> <span style="color: #008080;">:</span> Qt<span style="color: #008080;">::</span><span style="color: #007788;">black</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Il reste plus qu&rsquo;a dessiner un cercle à la position m_cursor_position :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; painter.<span style="color: #007788;">setPen</span><span style="color: #008000;">&#40;</span>m_cursor_pen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; painter.<span style="color: #007788;">setBrush</span><span style="color: #008000;">&#40;</span>QBrush<span style="color: #008000;">&#40;</span>Qt<span style="color: #008080;">::</span><span style="color: #007788;">NoBrush</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; painter.<span style="color: #007788;">drawEllipse</span><span style="color: #008000;">&#40;</span>m_cursor_position, defaut_diameter, defaut_diameter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Le diamètre du cercle est une constante définie en début du fichier d&rsquo;implémentation :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> defaut_diameter <span style="color: #000080;">=</span> <span style="color: #0000dd;">5</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Lors d&rsquo;un évènement souris de type mousePressEvent, on teste si l&rsquo;utilisateur a cliqué sur le bouton gauche :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">mousePressEvent</span><span style="color: #008000;">&#40;</span>QMouseEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> Qt<span style="color: #008080;">::</span><span style="color: #007788;">LeftButton</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span></div></td></tr></tbody></table></div>
<p>Si c&rsquo;est le cas, on active le suivi des mouvements de la souris, on récupère la positon de la souris dans m_cursor_position puis on met à jour la couleur sélectionnée :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; &nbsp; m_tracking <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_cursor_position <span style="color: #000080;">=</span> event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>pos<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Lors d&rsquo;un évènement de type mouseReleaseEvent, on déssactive le suivi de la souris et on met à jour la couleur sélectionnée :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">mouseReleaseEvent</span><span style="color: #008000;">&#40;</span>QMouseEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> Qt<span style="color: #008080;">::</span><span style="color: #007788;">LeftButton</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_tracking <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_cursor_position <span style="color: #000080;">=</span> event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>pos<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Les mouvements de la souris sont détectés par l’évènement mouseMoveEvent. Pour que ces événements soient pris en compte pour le widget, il faut les activer en utilisant la fonction setMouseTracking(true) dans le constructeur. Ces évènements mouseMoveEvent sont activés même lorsqu&rsquo;aucun bouton n&rsquo;est appuyé. C&rsquo;est la fonction de la variable m_tracking d&rsquo;indiquer si on déplace la souris en conservant un bouton cliqué ou non.<br />
Lorsque l&rsquo;on maintient appuyé un bouton de la souris et que l&rsquo;on déplace celle-ci en dehors du widget, des évènements mouseMoveEvent continuent d&rsquo;être envoyé. Si on prend en compte ces évènements, on risque de demander la couleur de pixels en dehors de la taille de m_gradient_image, ce qui provoquera des erreurs. Il faut donc tester si la position de la souris est dans le widget. Au final, le code de mouseMoveEvent sera :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">mouseMoveEvent</span><span style="color: #008000;">&#40;</span>QMouseEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_tracking <span style="color: #000040;">&amp;&amp;</span> rect<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">contains</span><span style="color: #008000;">&#40;</span>event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>pos<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_cursor_position <span style="color: #000080;">=</span> event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>pos<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; updateSelectedColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Lors d&rsquo;un changement de taille du widget, il suffit de remettre à jour le gradient :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">resizeEvent</span><span style="color: #008000;">&#40;</span>QResizeEvent <span style="color: #000040;">*</span>event<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; Q_UNUSED<span style="color: #008000;">&#40;</span>event<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; m_cursor_position <span style="color: #000080;">=</span> rect<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">center</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; updateGradientImage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Il ne reste plus qu&rsquo;a implémenter le constructeur :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">GradientWidget</span><span style="color: #008000;">&#40;</span>QWidget <span style="color: #000040;">*</span>parent<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; QWidget<span style="color: #008000;">&#40;</span>parent<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_cursor_position<span style="color: #008000;">&#40;</span>rect<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">center</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_tracking<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; setAttribute<span style="color: #008000;">&#40;</span>Qt<span style="color: #008080;">::</span><span style="color: #007788;">WA_OpaquePaintEvent</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; setMouseTracking<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; updateGradientImage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Ainsi que le slot setMainColor() :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span> GradientWidget<span style="color: #008080;">::</span><span style="color: #007788;">setMainColor</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> QColor <span style="color: #000040;">&amp;</span>color<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; m_main_color <span style="color: #000080;">=</span> color<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; updateGradientImage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<h1>Le résultat final</h1>
<p>Voici le rendu obtenu :</p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/1-degrade/gbdivers/gbdivers_capture_ecran.png" alt="null" /></p>
<p><a href="http://www.developpez.net/forums/attachments/p66806d1283512715/c-cpp/bibliotheques/qt/exercice-qt-color-picker-deuxieme-partie-lancee/colorpicker.zip/">Télécharger les sources de cet article.</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un ColorPicker avec Qt &#8211; Enoncé de l&#8217;exercice</title>
		<link>https://blog.developpez.com/gpu/?p=340</link>
		<comments>https://blog.developpez.com/gpu/?p=340#comments</comments>
		<pubDate>Fri, 15 Feb 2013 17:49:30 +0000</pubDate>
		<dc:creator><![CDATA[gbdivers]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Facile]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[QtQuick]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/gpu/?p=340</guid>
		<description><![CDATA[Cet article est une reprise des sujets écris par johnlamericain et des documents que j&#8217;avais rédigé pour un exercice Qt. Cette première partie est un rappel (copié-collé) du sujet de l&#8217;exercice, posté sur le forum. Première partie : créer une &#8230; <a href="https://blog.developpez.com/gpu/?p=340">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Cet article est une reprise des sujets écris par <a href="http://www.developpez.net/forums/u44506/johnlamericain/">johnlamericain</a> et des documents que j&rsquo;avais rédigé pour un <a href="http://www.developpez.net/forums/d965869/c-cpp/bibliotheques/qt/exercice-qt-color-picker-deuxieme-partie-lancee/">exercice Qt</a>. Cette première partie est un rappel (copié-collé) du sujet de l&rsquo;exercice, posté sur le forum.</p>
<p><span id="more-340"></span></p>
<h1>Première partie : créer une zone de sélection avec gradient</h1>
<p>Bonjour à tous,</p>
<p>Nous savons que vous attendez avec impatience le prochain défi Qt, cependant un défi de qualité prends du temps à organiser et mettre en place. Pour palier à votre envie de développer et de vous faire les dents sur un nouveau projet, nous vous proposons un nouveau concept : les exercices Qt.</p>
<h2>Le principe</h2>
<p>Des petits sujets réguliers pour lesquels vous pouvez apporter une solution en détaillant quelques étapes clés imposés. La durée de l&rsquo;exercice dépendra de la difficulté de l&rsquo;énoncé. Il est possible qu&rsquo;un sujet conséquent en travail soit proposé et ainsi découpé en plusieurs parties représentant une suite d&rsquo;exercices sur le même thème.</p>
<p>Tout le monde peut ainsi proposer une solution pour répondre à l&rsquo;exercice posé. Dans le cas d&rsquo;un exercice en plusieurs parties, la meilleure solution pourra être utilisée par les autres participants pour la suite de l&rsquo;exercice.</p>
<p>Il est impossible pour l&rsquo;équipe de réunir un jury et réaliser un barème aussi poussé que celui des défis Qt. La meilleure solution sera ainsi désignée d&rsquo;un point de vue plus subjectif que pour les défis Qt par les responsables de la rubrique Qt, à savoir dourouc05 et moi-même et éventuellement d&rsquo;autres membres de l&rsquo;équipe Qt en fonction des disponibilités de chacun.</p>
<p>Les exercices seront ainsi proposés le vendredi (vous permettant d&rsquo;y travailler dès le week end après avoir découvert le nouveau sujet). La fin du dépôt des propositions aura lieu le vendredi soir à 23h59, un certain nombre de semaines (dépendant de la difficulté de celui-ci) après la présentation du sujet et le vainqueur sera désigné dans la semaine suivante avant la proposition du nouvel exercice.</p>
<p>Nous essayerons de faire attention à ce qu&rsquo;il n&rsquo;y ait pas de copie entre les codes des participants en appliquant la règle que le premier code publié sur le forum &laquo;&nbsp;appartient&nbsp;&raquo; au membre l&rsquo;ayant posté. Il existe bien sur des réponses à ces solutions sur internet, mais quel est l&rsquo;intérêt pour vous de les utiliser ?</p>
<p>Le premier sujet !</p>
<h2>Le thème</h2>
<p>Ce premier exercice fait parti d&rsquo;un thème qui est la réalisation d&rsquo;un color picker. Ci-dessous, quelques color pickers connus mais libre à vous de faire travailler votre imagination pour nous donner une meilleure solution au final :</p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/ColorPicker1.png" alt="null" /></p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/ColorPicker2.png" alt="null" /></p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/ColorPicker3.png" alt="null" /></p>
<p>Ce thème est découpé en trois parties qui toutes durent deux semaines. Un nouvel énoncé d&rsquo;exercice sera donc publié toutes les trois semaines (en comptant la semaine de correction).</p>
<h2>Première partie : widget personnalisé pour affiche et sélectionner la nuance de gris d&rsquo;une couleur</h2>
<p>Création d&rsquo;un widget permettant de sélectionner la nuance de gris à partir d&rsquo;une couleur. Seul le widget affichant le gradient de la nuance de gris sur une couleur sera évalué mais votre fenêtre peut afficher la couleur en cours et les valeurs de celle-ci pour démontrer le bon fonctionnement de celui-ci.</p>
<p>Le widget peut être carré, rectangulaire, sphérique, en cercle, libre à votre imagination.</p>
<p>Les étapes d&rsquo;explications imposées :</p>
<ol>
<li>Mise en place de la structure du widget (héritage, composition&#8230;) ;</li>
<li>Réalisation du gradient ;</li>
<li> Sélection et récupération de la couleur à partir du gradient.</li>
</ol>
<p>Vous avez donc jusqu&rsquo;au vendredi 3 septembre 23h59 pour nous fournir une solution. Le dépôt des solutions ce fait sur le forum à la suite de ce message.</p>
<p>J&rsquo;espère que l&rsquo;idée vous plait, n&rsquo;hésitez pas également à nous faire part de votre participation à la suite de ce message, de présenter votre solution en avant première et je finirai par dire : à vos claviers !</p>
<h1>Seconde partie : accompagner le widget d&rsquo;un sélecteur de couleur et amélioration de celui-ci</h1>
<p>L&rsquo;objectif est de continuer le widget en l&rsquo;améliorant et ajoutant d&rsquo;autres fonctionnalités. Pour ceux qui n&rsquo;auraient pas un widget fonctionnel, voici une archive contenant la classe du widget du vainqueur de la première partie à savoir gbdivers, améliorée par mes soins pour prendre en compte les malus qui lui ont été mis à la correction !</p>
<p>La première amélioration requise pour la partie deux est la création d&rsquo;un slider permettant la création de la couleur principale (teinte ou hue en anglais). L&rsquo;image ci-jointe vous montre de quoi je parle :</p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/partie2_hue.png" alt="null" /></p>
<p>Ce slider peut faire partie du widget ou être un widget indépendant. Je vous conseille de regarder la classe QSlider et les paramètres pour la personnalisée.</p>
<p>De plus un ensemble de champ QLineEdit respectant un certain format QIntValidator devra permettre d&rsquo;afficher et de modifier la valeur de la teinte, saturation ou valeur. En cas de modification, le changement se répercutera sur le widget par le déplacement du point de sélection. Il existe donc une connexion dans les deux sens entre ces différents éléments.</p>
<p>Par la suite, il faudra modifier le widget existant pour permettre également d&rsquo;afficher les dégradés de la saturation et de la valeur (et non plus la teinte, hue en anglais).</p>
<p>Exemples : </p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/partie2_saturation.png" alt="null" /></p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/partie2_value.png" alt="null" /></p>
<p>C&rsquo;est tout pour les étapes imposées dans cette seconde partie qui durera deux semaines.</p>
<p>Pour les personnes qui ont de l&rsquo;avance, vous pouvez réfléchir à n&rsquo;afficher que les couleurs disponibles pour le web et la représentation des dégradés dans les autres espaces colorimétriques.</p>
<p style="text-align: center"><img src="http://qt.developpez.com/exercices/01-colorpicker/images/partie2_web.png" alt="null" /></p>
<p>Si vous avez besoin d&rsquo;explications supplémentaires, n&rsquo;hésitez pas à poser des questions à la suite de ce message. De plus la correction et le code source de l&rsquo;ensemble des candidats pour la première partie est disponible dans ce sujet.</p>
<p>Bon courage !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
