Comment rendre une widget cliquable? (Qt/c++) - C++ - Programmation
Marsh Posté le 15-11-2005 à 01:32:42
Salut,
Comme tu l'as deviné, il faut surcharger QWidget::mousePressEvent ( QMouseEvent * e ).
Il y a un clic avec le bouton gauche si e->button() est égal à Qt::LeftButton. A partir de là, tu n'as plus qu'à émettre un signal click() que tu auras créé.
Perso, je préfére utiliser mouseReleaseEvent pour laisser la possibilité à l'utilisateur de ne pas cliquer si quelque chose ne va pas.
Selon ce que tu veux faire, tu peux aussi définir un QStyle qui correspond à tes besoins?
Marsh Posté le 15-11-2005 à 13:59:56
ok merci à toi!
J'ai un dernier petit problème :
lorsque je lance mon application, je fais appel à des classes (derivé de QPushButton) qui ont une methode "paintEvent(QPaintEvent * /* event */)" :
****************************************
void MyWidget::paintEvent(QPaintEvent * /* event */)
{
QPainter painter(this);
{
painter.setPen(Qt::white);
painter.setBrush(Qt::white);
painter.drawEllipse(20,20,50,50);
}
}
****************************************
appelée lors de la construction de l'objet. ça marche mais j'ai ce message explicite à l'execution pour chaque MyWidget crée :
"QPainter::begin: Widget painting can only begin as a result of a paintEvent"
Est-ce que j'utilise mal paintEvent ??
Merci.
Marsh Posté le 15-11-2005 à 21:29:18
C'est toi qui l'appelles toi-même? Si oui, il faut utiliser appeler update ou quelque chose de semblable. Sinon, est-ce que tu peux poster les lignes qui générent ce message stp?
PS: peux-tu utiliser les balises de code?
Marsh Posté le 15-11-2005 à 23:30:50
Ben c'est bizarre, le programme marche bien, c'est lorsque je le lance à partir d'un console que j'ai ce message de 128 lignes identiques :
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::begin: Widget painting can only begin as a result of a paintEvent
... 128 fois
sans numero de ligne, rien.
128 n'est pas un hasard : mon programme creer au debut un 'plateau' de 64 'case' (case -> classe où est apelé la fonction paintEvent),
et je fais 64 autres new Case, autre part (pour remplir un tableau de reference de ces cases).
et 64 *2 = 128!
Marsh Posté le 16-11-2005 à 01:33:53
Ok, mais la question principale est : où est appelée la fonction paintEvent?
Le message te dit que la fonction paintEvent est appelée sans que l'événement de dessin est été généré par Qt me semble-t-il.
Poste un peu plus de code stp, genre le constructeur et/ou l'initialisateur dont tu te sert.
Marsh Posté le 16-11-2005 à 14:19:35
Voici mon .cpp :
**********************************
#include "OthCase.h"
#define VIDE 0
#define NOIRE 1
#define BLANCHE 2
OthCase::OthCase(int ligne, int colonne)
{
setFixedSize(84,84);
this->ligne = ligne;
this->colonne = colonne;
this->coul = 0;
}
OthCase::OthCase(int ligne, int colonne, int couleur)
{
setFixedSize(84,84);
this->ligne = ligne;
this->colonne = colonne;
this->coul = couleur;
connect(this,SIGNAL(clicked()),this,SLOT(slotCase()));
}
void OthCase::setCouleur(int couleur)
{
coul=couleur;
}
void OthCase::paintEvent(QPaintEvent * /* event */)
{
QPainter painter(this);
if (coul!=VIDE)
{
if (coul==BLANCHE)
{
painter.setPen(Qt::white);
painter.setBrush(Qt::white);
painter.drawEllipse(20,20,50,50);
}
else
if (coul==NOIRE)
{
painter.setPen(Qt::black);
painter.setBrush(Qt::black);
painter.drawEllipse(20,20,50,50);
}
}
}
void OthCase::slotCase()
{
emit signalCase(this->ligne, this->colonne);
}
*********************************
mon .h :
*********************************
#ifndef OTHCASE_H
#define OTHCASE_H
#include <QPainter>
#include <QPushButton>
#include <QWidget>
#include <QtGui>
class OthCase : public QWidget
{
Q_OBJECT
public:
OthCase(int ligne, int colonne); // case vide (coul = 0)
OthCase(int ligne, int colonne, int couleur); //1 -> noire, 2 -> blanche
void setCouleur(int couleur);
protected:
void paintEvent(QPaintEvent *event);
public:
int ligne;
int colonne;
int coul;
public slots:
void slotCase();
signals :
void signalCase(int, int);
};
#endif
**********************************
et je construit mes OthCase d'une autre classe en faisant un :
OthCase *laCase = new OthCase(row, column, couleur);
et ceci 128 fois.
J'en profite pour poser 2 petites question :
- Est-ce qu'il faut forcement QT d'installé pour exécuter une appli faite avec Qt (j'ai essayé, il m'a dit qu'il manquait une librairie ...qt...lib.h je sais plus trop)
- Quel est le moyen le plus simple d'afficher un popup (eventuellement bouton) avec un petit texte et 2 boutons.
Merci beaucoup pour votre aide.
Marsh Posté le 16-11-2005 à 16:05:45
i'n'i a écrit : |
voilà mon message exact lors de l'exécution :
./monappli: error while loading shared libraries: libQtGui_debug.so.4: cannot o pen shared object file: No such file or directory
Marsh Posté le 16-11-2005 à 19:55:41
Pitié, utilise les balises de code! C'est limite illisible sans ça...
Jusque là je n'ai pas vu d'erreur. Ce qui m'interesse finalement, ce serai plutôt les quelques lignes qui suivent celle-ci
Code :
|
Ou toutes les lignes qui manipulent des cases à l'initialisation de ton appli. Tu fais un appel à une fonction de dessin trop tôt. Le tout est de savoir où est appelée cette fonction
Marsh Posté le 17-11-2005 à 16:15:20
En fait je creer une classe 'plateau' qui contient toute mes 'OthCase', et une matrice qui contient les refenreces sur toutes les cases
Donc après
OthCase *laCase = new OthCase(row, column, couleur);
j'ai juste
plateau->grid->addWidget(laCase, row, column);
et
matrice->ajouterCase(row, column, laCase);
Voilà, je n'appelle jamais de methode de dessin sur une case, les methodes de dessin des case sont donc juste appelées lors du
OthCase *laCase = new OthCase(row, column, couleur);
dans ma classe plateau !
Marsh Posté le 18-11-2005 à 14:23:39
Vraiment strange...
Je viens de voir que tu ne transmettais pas le moindre parent. Je suis pas sûr que ça règle le problème, mais ce serait sans doute plus propre. Essaies à tout hasard??
Marsh Posté le 18-11-2005 à 23:44:16
ok, merci bien je vais essayer ça dimanche.
-A tout hasard, tu ne saurais pas à tout hasard comment faire pour pouvoir inclure les modules ftp, xml,... au sein de QT? J'ai essayer #include <leNomDuModule>
mais apparemment ce n'est pas ça car il me dit 'no such file...' lors de la compilation.
-De plus :
Est-ce qu'il faut forcement QT d'installé pour exécuter une appli faite avec Qt (j'ai essayé, il m'a dit qu'il manquait une librairie :
voilà mon message exact lors de l'exécution :
"./monappli: error while loading shared libraries: libQtGui_debug.so.4: cannot o pen shared object file: No such file or directory"
Merci.
Marsh Posté le 19-11-2005 à 16:58:43
i'n'i a écrit : -A tout hasard, tu ne saurais pas à tout hasard comment faire pour pouvoir inclure les modules ftp, xml,... au sein de QT? J'ai essayer #include <leNomDuModule> |
Essaye plutôt #include <Module/Classe>, i.e. <QtXml/QXmlReader>
i'n'i a écrit : -De plus : |
Il faut absolument que les bibliothèques utilisées soient installées, mais pas forcément le SDK. Par contre, si tu distribues ton exécutable, distribue plutôt la version release que la debug.
Pour revenir sur ton histoire de popup, regarde du côté de QMessageBox.
Marsh Posté le 21-11-2005 à 10:10:33
IrmatDen a écrit : Essaye plutôt #include <Module/Classe>, i.e. <QtXml/QXmlReader> |
Comment dois-je faire pour installer seulement les bibliotheques et que entends-tu par version release et debug de mon executable?
merci
Marsh Posté le 21-11-2005 à 11:09:37
Pour mon problème, j'ai essayer de transmettre les parents mais ça ne marche pas non plus.
En fait, j'ai 3 classes (qui derivent de widget) : Une Interface qui contient un Plateau qui contient 64 Cases.
J'ai essayer de creer, et donc d'afficher une case directement à partir de mon Interface, et la pas de problème, je n'ai pas le message
"QPainter::begin: Widget painting can only begin as a result of a paintEvent"
Par contre moi ce que je veux c'est que les cases soit dans Plateau, et non dans Interface. Mais là, ça coince et j'ai ce message.
En fait lorsque je creer mon Plateau, il n'est pas encore afficher dans mon Interface, et donc les Qpainter::begin de mes cases ne peuvent pas s'afficher d'où le message.
Il faudrait peut-être que le Qpainter ne se fasse pas lors de la creation des cases, mais seulement lorsque mon plateau est bien attaché à mon Interface, et peut donc être dessiner.
Qu'en penses-tu?
Marsh Posté le 25-11-2005 à 00:16:16
Pour gérer ton plateau, tu peux plutôt passer par un QGridLayout (http://doc.trolltech.com/4.0/qgridlayout.html). Ce sera sans doute plus propre. Voire même aussi pour ton interface...
A voir si ça supprime ton warning
Marsh Posté le 14-11-2005 à 23:07:52
Tout est dans le titre. En QT4, comment faire qu'un widget soit cliquable, c-a-d que lorsqu'on clique dessus, ça génère un signal click(). Je sais que QPushButton le fait (le slot click() est implémenté pour QPushButton) mais je ne veux pas que ma widget soit un bouton. Faut-il utiliser QWidget::mousePressEvent ( QMouseEvent * e ) ? si oui, comment cela fonctionne?
Merci.