Plusieurs Widgets sur un QFrame. Ordre d'affichage.

jijiz
Plusieurs Widgets sur un QFrame. Ordre d'affichage.

Salut à tous,

J'instancie plusieurs QWidget dans une QFrame, je souhaiterais definir l'ordre de visibilité des widgets sur la fenêtre. Savez-vous comment fait-on cela?

Merqui.

Ju.

fredericmazue

C'est une question qui concerne Python ça ? Ou alors tu codes en PyQT sans rien dire à personne ? ;)

Quoi qu'il en soit, comment ça ordre de visibilité ? Tu veux qu'il apparaissent les uns après les autres tes widgets ? Dans quel but ?

jijiz

fredericmazue wrote:
C'est une question qui concerne Python ça ? Ou alors tu codes en PyQT sans rien dire à personne ? ;)

Quoi qu'il en soit, comment ça ordre de visibilité ? Tu veux qu'il apparaissent les uns après les autres tes widgets ? Dans quel but ?

Hmm désolé ne ne pas avoir précisé, oui c'est du pyQT

Je dessine dans des qwidget, je peux déplacer avec la souris ces qwidget dans la qframe. Sauf que lorsque 2 qwidgets se superposent celui qui reste visible est le dernier à avoir été instancié. J'aimerais pouvoir donner la visibilité à celui qui est en mouvement.

fredericmazue

Quote:
je peux déplacer avec la souris ces qwidget dans la qframe

Hum, ça aussi tu aurais pu le préciser dans ta première question.
Qu'est-ce que tu nous cache d'autres, pour être bien sûr qu'on ne puisse pas t'aider? ;) :lol:
jijiz

fredericmazue wrote:
Quote:
je peux déplacer avec la souris ces qwidget dans la qframe

Hum, ça aussi tu aurais pu le préciser dans ta première question.
Qu'est-ce que tu nous cache d'autres, pour être bien sûr qu'on ne puisse pas t'aider? ;) :lol:

Alors pour illustrer un peu mes dires, voici une capture de mon appli
C'est un peu le même fonctionnement que simulink pour matlab

Lorsque je déplace un bloc, je souhaite qu'il soit au dessus de tous les autres.

fredericmazue

Quote:
Lorsque je déplace un bloc, je souhaite qu'il soit au dessus de tous les autres.

Sans doute mais tu es quand même un cachotier :D
Plus haut tu as écrit:
Quote:
Je dessine dans des qwidget

*Je* dis tu. Moi je ne pense pas. Parce que si tu dessinais, le widget serait dessiné en vertu du principe fondamental de La Palice :D

Donc tu nous caches sans doute que tu appelles une routine de rafraîchissement de la fenêtre. Je veux dire que tu demandes à QT de dessiner au lieu de le faire toi même. Et sans doute aussi que QT maintient une liste des widgets ordonnés dans l'ordre de leur création et les redessine systématiquement dans cet ordre. Et c'est AMHA ton approche du *je* dessine qui est a repenser.
J'ai t'y raison ?
Mais bon va savoir, parce que petit cachotier que tu es, ton code aussi tu le caches soigneusement. Pas un petit bout, pas une ligne, rien, nada, (void *)null.
Ca ne fait pas beaucoup pour déterminer ce qui ne va pas :twisted: :D

jijiz

fredericmazue wrote:
Quote:
Lorsque je déplace un bloc, je souhaite qu'il soit au dessus de tous les autres.

Sans doute mais tu es quand même un cachotier :D
Plus haut tu as écrit:
Quote:
Je dessine dans des qwidget

*Je* dis tu. Moi je ne pense pas. Parce que si tu dessinais, le widget serait dessiné en vertu du principe fondamental de La Palice :D

Donc tu nous caches sans doute que tu appelles une routine de rafraîchissement de la fenêtre. Je veux dire que tu demandes à QT de dessiner au lieu de le faire toi même. Et sans doute aussi que QT maintient une liste des widgets ordonnés dans l'ordre de leur création et les redessine systématiquement dans cet ordre. Et c'est AMHA ton approche du *je* dessine qui est a repenser.
J'ai t'y raison ?
Mais bon va savoir, parce que petit cachotier que tu es, ton code aussi tu le caches soigneusement. Pas un petit bout, pas une ligne, rien, nada, (void *)null.
Ca ne fait pas beaucoup pour déterminer ce qui ne va pas :twisted: :D

Ca fait plaisir d'avoir des méssages comme le tiens, tu n'es pas modérateur pour rien je pense !! Et ça donne envie de s'abonner ^^...

Tous mes objets graphiques dessinés dérivent de cette classe :

class ObjectUI(QtGui.QWidget):
    """ Graphical Objects wich are displayed on the screen (virtual object) """
    def __init__(self, _QSSize, _QPPosition, parent=None):
        super (ObjectUI, self).__init__ (parent)
        self.QPPosition = _QPPosition
        self.QSSize = _QSSize
        
        # Properties of the font
        newFont = self.font()
        newFont.setPixelSize(12)
        self.setFont(newFont)
        self.setFixedSize(self.getSize())     
        fontMetrics = QtGui.QFontMetrics(newFont)
        
        self.QPaint = QtGui.QPainter()
      
#=================================
# Public accessors
#=================================
    def setPosition(self,P):
        """ set the position of the action object block """
        self.QPPosition = P
    
    def getPosition(self):
        """ return the position of the action object block """
        return self.QPPosition   

    def setSize(self,_QSSize):
        """ set the size of the current object user interface """
        self.QSSize = _QSSize
    
    def getSize(self):
        """ return the size of the current object user interface """
        return self.QSSize
    
    def getPainter(self):
        """ return the qpainter """
        return(self.QPaint)
    
#=================================
# Manage the mouse
#=================================
    def mousePressEvent(self, event): 
        """ action performed when the mouse is clicked """
        raise NotImplementedError("Method mousePressEvent not defined in class " + self.__class__.__name__)   

    def mouseMoveEvent(self, event): 
        """ action performed when the mouse is moved """
        raise NotImplementedError("Method mouseMoveEvent not defined in class " + self.__class__.__name__)   
    
    def mouseReleaseEvent(self, event): 
        """ action performed when the mouse is released """
        raise NotImplementedError("Method mouseReleaseEvent not defined in class " + self.__class__.__name__)   

Et voici le code d'un widget graphique qui dessine un carré:

#==================================
# Import modules
#==================================
from PyQt4 import QtGui, QtCore
from ObjectUI import ObjectUI
#==================================
# Constructor
#==================================
class PlaceObjectUI(ObjectUI, QtGui.QLabel):
    colorFix = QtCore.Qt.darkGray
    colorMoving = QtCore.Qt.gray
    colorFill = QtCore.Qt.gray
    """ Graphical Objects of places (represent variables """
    def __init__(self, _QPPosition, parent=None):
        ObjectUI.__init__(self, QtCore.QSize(10, 10), _QPPosition, parent)
        # Attributes
        self.m_place = 0
        self.m_ascendant = 0
        self.m_ascPosition = 0
        self.m_descendants = []
        
        # Color of the picture drawn
        self.color = self.colorFix
               
        # get the painter
        self.painter = self.getPainter()
        
        # Draw the shape
        self.setupShape()

        
#=================================
# Public painting
#=================================         
    def paintEvent(self, event):
        # Go to the position where to draw the object
        self.move(self.getPosition().x(), self.getPosition().y())
        
        self.painter = QtGui.QPainter()
        self.painter.begin(self)
        #painter.setRenderHint(QtGui.QPainter.Antialiasing)
        self.painter.fillRect(event.rect(), QtGui.QBrush(self.colorFix))
        self.drawShape(self.painter)
        self.painter.end()

    def drawShape(self, painter):
        self.painter.fillPath(self.shape, QtGui.QBrush(self.colorFix))

    def setupShape(self):
        QPpath = QtGui.QPainterPath()
        QPpath.setFillRule(QtCore.Qt.OddEvenFill)
        
        QPpath.addRect(0, 0, self.getSize().width(), self.getSize().height())    
        self.shape = QPpath
        
#=================================
# Public accessors
#=================================  
    def setPlace(self, _place):
        self.m_place = _place
    
    def getPlace(self):
        return self.m_place
    
    def setAscendant(self, _asc):
        self.m_ascendant = _asc
        
    def addDescendant(self, _desc):
        self.m_descendants.append(_desc)
    
    def getAscendant(self):
        return self.m_ascendant

#=================================
# Public functions
#=================================  
    def getNbDescendants(self):
        return len(self.m_descendants)
    
    def getDescendant(self, _position):
        return self.m_descendants[_position]
    
    def removeAscendant(self):
        self.m_ascendant = 0

#=================================
# Manage the mouse
#=================================
    def mouseMoveEvent(self, event):
        """ Redraw the current block when the mouse is being moved """
        # shape of the cursor
        self.setCursor(QtCore.Qt.SizeAllCursor)
        # Catch the position of the mouse
        position = event.pos()
        # newPosition is the new position of the QLabel
        newPosition = QtCore.QPointF(self.getPosition().x()+position.x(),self.getPosition().y()+position.y())
        # Move to the current position of the mouse
        self.move(newPosition.x(),newPosition.y())
        # update the position of the QLabel
        self.QPPosition = newPosition
        self.color = self.colorMoving
        self.update()
        
    def mousePressEvent(self, event):
        return 
    
    def mouseReleaseEvent(self, event):
        # shape of the cursor
        self.setCursor(QtCore.Qt.SizeAllCursor)
        self.color = self.colorFix
        self.update()             
fredericmazue

Quote:
Ca fait plaisir d'avoir des méssages comme le tiens, tu n'es pas modérateur pour rien je pense !! Et ça donne envie de s'abonner ^^...

Comment dois-je le prendre ? Au premier ou second degré ?
jijiz

Premier bien sur, il n'y a pas d'ironie dans ce que j'ai dit.

Tu as pris le temps de me répondre ainsi que d'éclaircir mon post ! J'ai peine à trouver des forums python avec des forumeurs actifs. D'autant plus que dans la boite dans laquelle je suis (stagiaire), personne ne fait directement du graphique pythonQT.

fredericmazue wrote:
Quote:
Ca fait plaisir d'avoir des méssages comme le tiens, tu n'es pas modérateur pour rien je pense !! Et ça donne envie de s'abonner ^^...

Comment dois-je le prendre ? Au premier ou second degré ?
fredericmazue

A lire (pas très attentivement je le confesse :oops: ) ton code, il me semble que ton problème est bel et bien dans le *je* de "je dessine".
Si je comprends bien tu ne dessines pas mais chaque composant réagit à un paintEvent et se redessine à ce moment. Le problème est que tu n'es pas maître que l'ordre dans lequel QT envoie les événements. Je ne pense pas que l'on puisse avoir la maîtrise là-dessus. Je dirais même au contraire (si je me rappelle un bout de doc de Qt que j'ai lu il y a longtemps) Pour résoudre le problème Il me semble que tu dois (par exemple) capturer les mouvements de la souris en amont,, c'est à dire au dessus de la fenêtre sans te soucier des widgets et à chaque déplacement tu dois appeler les méthodes drawShape de tes composants (dans un sandwich QtGui.QPainter(), etc ce la va de soit) . Comme ça tu pourras les dessiner comme tu voudras, surtout si tu maintiens une liste dans laquelle ils seront classés selon leur z-order.

jijiz

fredericmazue wrote:
A lire (pas très attentivement je le confesse :oops: ) ton code, il me semble que ton problème est bel et bien dans le *je* de "je dessine".
Si je comprends bien tu ne dessines pas mais chaque composant réagit à un paintEvent et se redessine à ce moment. Le problème est que tu n'es pas maître que l'ordre dans lequel QT envoie les événements. Je ne pense pas que l'on puisse avoir la maîtrise là-dessus. Je dirais même au contraire (si je me rappelle un bout de doc de Qt que j'ai lu il y a longtemps) Pour résoudre le problème Il me semble que tu dois (par exemple) capturer les mouvements de la souris en amont,, c'est à dire au dessus de la fenêtre sans te soucier des widgets et à chaque déplacement tu dois appeler les méthodes drawShape de tes composants (dans un sandwich QtGui.QPainter(), etc ce la va de soit) . Comme ça tu pourras les dessiner comme tu voudras, surtout si tu maintiens une liste dans laquelle ils seront classés selon leur z-order.

Ok je pense voir ce que tu m'as expliqué.
Je dois donc redessiner tout le graphe même si je ne déplace qu'un seul widget ?

J'ai un autre soucis, mon widget "lien" qui représente le trait sur l'image se redessine à chaque déplacement d'une boite, ça marche mais il y à des scintillements. Je me demande si ma conception est bien adaptée pour ce que je souhaite faire? Je n'ai trouvé sur le net aucun tutorial pour faire du dessin interactif un peu évolué avec pyQT, je trouve ceci fort domage car python à l'air d'être puissant mais pas encore utilisé dans les entreprises.

ps: pour mon problème de "Z", on m'a parlé de QStackedWidget, mais la doc dit que ca sert à n'afficher que le widget en tete de la liste. Peux-tu m'en dire un peu plus sur ses fonctionnalités.

ps: j'espere ne pas abuser avec mes questions de débutant, mais j'ai fait pas mal de recherches google et RTFM...

fredericmazue

Quote:
Je dois donc redessiner tout le graphe même si je ne déplace qu'un seul widget ?

C'est ça, et en dessinant dans le bon ordre, donc en classant au préalable les widgets dans une liste selon leur z-order (ordre de superposition).
Quote:
marche mais il y à des scintillements. Je me demande si ma conception est bien adaptée pour ce que je souhaite faire?

En effet je pense qu'il y a une petite faute de conception. Ce n'est pas la bonne approche je pense de provoquer le dessin des widgets en boucle (même si tu appelles toi même la méthode drawShape.A cause du sandwich "sandwich QtGui.QPainter()" en compagnie ça peut pas se dessiner proprement -> Ca scintille.
A priori et dans un premeir temps, tu peux employer la technique du double buffering. Ca consiste à tout dessiner en arrière plan dans une image. En arrière plan ça veut dire qu'on ne voit rien du tout à l'écran pendant cette phase. Puis dès que l'image d'arrière plan est constitutée, tu l'affiches d'un coup. Cette technique ultra classique permet d'éviter les scintillements.
En ce qui concerne le QStackedWidget, je n'en vois pas l'intérêt ici. AMHA celui qui t'a parlé de ça, n'a pas saisi le problème.
Quote:

ps: j'espere ne pas abuser avec mes questions de débutant,

Pas de pb. Si j'ai une solution à te proposer et du temps pour le faire, je réponds, sinon peut être quelqu'un d'autre le fera. Un forum ça sert à ça. Et puis... ->
Quote:
je trouve ceci fort domage car python à l'air d'être puissant mais pas encore utilisé dans les entreprises.

-> ... Toi je t'aime bien :)
Tu es un garçon de bon goût, et en ce moment où tout le monde se noie dans un imbuvable café américain, tu es un vrai oiseau rare :D :lol:
jijiz

J'éssaye de m'attaquer au Double Buffer en premier pour une v0, je verrai ensuite de revoir la conception.

        image = QtGui.QImage(sizeX, sizeY, QtGui.QImage.Format_ARGB32_Premultiplied)
        self.painter.begin(self)
        # dessin
        self.painter.setPen(QtCore.Qt.black)
        self.painter.drawLine(QtCore.QPoint(0,0), QtCore.QPoint(sizeX, sizeY))
        self.setPixmap(QtGui.QPixmap.fromImage(image))
        self.painter.end()

Je ne suis pas sur d'appliquer la bonne méthode du double buffer. Sur certains sites ils parlent de la fonction bitblt qui existe uniquement avec qt3, or j'utilise qt4. Avec qt4 il paraitrait que la technique du double buffer ne sert à rien puisque qt le ferait tout seul comme un grand, je n'en suis pas convaincu.

Est-ce que je procède bien pour faire un double buffer avec mon code, pas sur...car ca scintille encore !

fredericmazue

Quote:
Je ne suis pas sur d'appliquer la bonne méthode du double buffer

En effet. L'idée est de dessiner TOUS les composants dans UNE image. Je t'ai parlé d'une boucle de dessin de tous les widgets d'un coup en réponse aux événements souris.
Si, au contraire, d'une manière ou d'une autre, tu provoques un repaint de la fenêtre ça scintillera toujours.

Quote:
Avec qt4 il paraitrait que la technique du double buffer ne sert à rien puisque qt le ferait tout seul comme un grand, je n'en suis pas convaincu.

"il paraîtrait"... Moi je connais pas les "il paraîtrait".
Mais qu'une image QT4 soit double-bufferisée n'implique pas que ça te dispense de coder la boucle que j'essaie de t'expliquer. Si tu afficher n images double-bufferisées dans ta fenêtre, tu ne fais pas ce qu'il faut. Ce qu'il faut est que le fond de ta fenêtre soit constitué d'une seule image double-bufferisée entièrement dessinée en arrière plan.
jijiz

fredericmazue wrote:
Quote:
Je ne suis pas sur d'appliquer la bonne méthode du double buffer

En effet. L'idée est de dessiner TOUS les composants dans UNE image. Je t'ai parlé d'une boucle de dessin de tous les widgets d'un coup en réponse aux événements souris.
Si, au contraire, d'une manière ou d'une autre, tu provoques un repaint de la fenêtre ça scintillera toujours.

Quote:
Avec qt4 il paraitrait que la technique du double buffer ne sert à rien puisque qt le ferait tout seul comme un grand, je n'en suis pas convaincu.

"il paraîtrait"... Moi je connais pas les "il paraîtrait".
Mais qu'une image QT4 soit double-bufferisée n'implique pas que ça te dispense de coder la boucle que j'essaie de t'expliquer. Si tu afficher n images double-bufferisées dans ta fenêtre, tu ne fais pas ce qu'il faut. Ce qu'il faut est que le fond de ta fenêtre soit constitué d'une seule image double-bufferisée entièrement dessinée en arrière plan.

Ok je me lance dans le dessin sur une seule image double buffeurisée.

J'ai un soucis pour afficher un simple carré. Lorsque ce code marchera, j'aurais compris comment fonctionne exactement les qpainterpath et je pourrais alors me lancer dans la nouvelle conception.

from PyQt4 import QtGui, QtCore
import sys

class DrawWidget(QtGui.QLabel):
    def __init__(self, parent=None):
        super (DrawWidget, self).__init__ (parent)
        
        QPath = QtGui.QPainterPath()
        painter = QtGui.QPainter()
        
        QPath.setFillRule(QtCore.Qt.OddEvenFill)

       # Partie qui sera encapsulee dans les fonctions setupShape de mes objets graphiques
        QPath.lineTo(0.0,87)
        QPath.lineTo(0.0,60)
        QPath.lineTo(10.0,60)
        QPath.lineTo(35,35)
        QPath.lineTo(100.0,35)
        QPath.lineTo(100, 87)
        QPath.lineTo(0.0, 87)
                
        painter.begin(self)

# Utile ou pas? :
        painter.fillRect(0,0,800,600, QtCore.Qt.white)

        painter.fillPath(QPath, QtGui.QBrush(QtCore.Qt.BDiagPattern))
        painter.end()

class DrawGraph(QtGui.QFrame):
    def __init__(self, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.move(0, 0)
        self.setMinimumSize(800, 600)
        self.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.StyledPanel)
        self.setWindowTitle(self.tr("Test AFPy Objets Graphique"))
        dw = DrawWidget(self)
        
                
      

        
        
               
if __name__ == "__main__":
    
    app = QtGui.QApplication(sys.argv)
    window = DrawGraph()
    window.show()
    sys.exit(app.exec_())

Avec tout ça rien ne s'affiche...
*
Merci encore

fredericmazue

Quote:
Avec tout ça rien ne s'affiche...

Je ne vois aucun appel à drawPath. C'est normal ?
jijiz

fredericmazue wrote:
Quote:
Avec tout ça rien ne s'affiche...

Je ne vois aucun appel à drawPath. C'est normal ?

Juste, mais toujours pas ! Rah, je vais faire des tutos à la fin de mon stage en francais et complets.

class DrawWidget(QtGui.QLabel):
    def __init__(self, parent=None):
        super (DrawWidget, self).__init__ (parent)
        
        QPath = QtGui.QPainterPath()
        painter = QtGui.QPainter()
        
        QPath.setFillRule(QtCore.Qt.OddEvenFill)
        QPath.lineTo(0.0,87)
        QPath.lineTo(0.0,60)
        QPath.lineTo(10.0,60)
        QPath.lineTo(35,35)
        QPath.lineTo(100.0,35)
        QPath.lineTo(100, 87)
        QPath.lineTo(0.0, 87)
        QPath.addRect(0,0,100,100)
                
        painter.begin(self)
        painter.fillRect(0,0,800,600, QtCore.Qt.white)
        painter.fillPath(QPath, QtGui.QBrush(QtCore.Qt.BDiagPattern))
        painter.drawPath(QPath)
        painter.end()

class DrawGraph(QtGui.QFrame):
    def __init__(self, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.move(0, 0)
        self.setMinimumSize(800, 600)
        self.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.StyledPanel)
        self.setWindowTitle(self.tr("Test AFPy Objets Graphique"))
        dw = DrawWidget(self)
jijiz

oui, ok ca marche chui naze des fois (ou plutot chui pas trop bête de temps en temps rarement)

Bon allé reconcevons.... :lol:

fredericmazue

Quote:
je vais faire des tutos à la fin de mon stage en francais et complets.

Ma foi....
N'oublie quand même pas de m'envoyer un chèque. Avec beaucoup de zéros.
Et puis surtout...

Quote:
painter = QtGui.QPainter()

...faudra quand même penser à avoir la tête un peu moins dure.
Qu'est-ce qu'on essaie de faire déjà ? De dessiner dans une Pixmap. Où est elle ?
Qu'est-ce qu'on essaie de faire déjà ? De dessiner sans que ça soit en réponse à un événement de dessin.
Alors avec painter = QtGui.QPainter() tu dessines dans quoi la ?
Si c'est en réponse à un événement le QPaintDevice est implicitement construit en amont et painter = QtGui.QPainter() suffit.
Mais si tu dessines sans répondre à un événement (ce que je te répète depuis au moins 3 posts), alors faut peut être bien donner un QPaintDevice à manger au constructeur de Painter tu ne crois pas?

painter = QtGui.QPainter(***un_QPaintDevice_ici***)

jijiz

Je viens de comprendre à quoi servait le parametre du contructeur QPainter.

Maintenant je fais passer en parametre ma qpixmap à mon qpainter,
ensuite j'ajoute un rectangle au qpainterpath, ce qpainterpath je le dessine dans le qpainter qui est sensé le dessiner dans mon qpixmap, puis je termine par demander le dessin du qpixmap....

Rien...

J'ai du oublier quelque chose, même si ce que j'ai codé me semble logique...

class DrawGraph(QtGui.QFrame):
    def __init__(self, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.move(0, 0)
        self.setMinimumSize(800, 600)
        self.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.StyledPanel)
        self.setWindowTitle(self.tr("Test AFPy Objets Graphique"))
        
        QS1 = QtCore.QSize(100, 200)
        QPPosition = QtCore.QPointF(20+20, 20+15)
        
         
        self.QPath = QtGui.QPainterPath()
        self.QPixMap = QtGui.QPixmap(800,600)
        self.QPainter = QtGui.QPainter(self.QPixMap)
        #AO1 = ActionObjectUI(QS1, QPPosition, self)
        
        self.QPath.addRect(100,10,10,10)
        self.QPainter.fillPath(self.QPath, QtGui.QBrush(QtCore.Qt.black))    
        self.QPainter.drawPath(self.QPath)  
        
        self.QPainter.drawPixmap(QtCore.QPointF(0,0), self.QPixMap) 
        self.QPainter.end() 

fredericmazue wrote:
Quote:
je vais faire des tutos à la fin de mon stage en francais et complets.

Ma foi....
N'oublie quand même pas de m'envoyer un chèque. Avec beaucoup de zéros.
Et puis surtout...

Quote:
painter = QtGui.QPainter()

...faudra quand même penser à avoir la tête un peu moins dure.
Qu'est-ce qu'on essaie de faire déjà ? De dessiner dans une Pixmap. Où est elle ?
Qu'est-ce qu'on essaie de faire déjà ? De dessiner sans que ça soit en réponse à un événement de dessin.
Alors avec painter = QtGui.QPainter() tu dessines dans quoi la ?
Si c'est en réponse à un événement le QPaintDevice est implicitement construit en amont et painter = QtGui.QPainter() suffit.
Mais si tu dessines sans répondre à un événement (ce que je te répète depuis au moins 3 posts), alors faut peut être bien donner un QPaintDevice à manger au constructeur de Painter tu ne crois pas?

painter = QtGui.QPainter(***un_QPaintDevice_ici***)

fredericmazue

Quote:
Maintenant je fais passer en parametre ma qpixmap à mon qpainter,

Voilà :)
Quote:
puis je termine par demander le dessin du qpixmap....

Quote:
self.QPainter.drawPixmap(QtCore.QPointF(0,0), self.QPixMap)

Tu ne dessinerais pas l'image sur elle même là par hasard ? ;)

:lol:

jijiz

Hmm, j'ai du mal à interpreter le role de la fonction drawpixmap, pour moi elle doit dessiner le qpixmap passé en paramètres dans l'objet sur lequel on appelle la méthode soit le qpainter.

Me trompais-je? ^^

fredericmazue

Quote:
Me trompais-je? ^^

Apparament (si j'ose dire) oui, puisque sur ton écran rien n'apparaît :)
Ou plutôt non tu ne te trompes pas, mais l'objet qui a servi à construire le Painter est cette même QPixmap, ce me semble.
fredericmazue

Quote:
self.QPixMap

Ah au fait, une petite remarque, si tu me le permets:
self.QPixMap
Il existe comme tu le sait, un type QPixmap. Déclarer un membre du nom de QPixMap, même nom à une majuscule près, ça s'appelle de l'obfuscation, c'est à dire un très mauvais style d'écriture.

En programmation nommer des variables, c'est un vrai art :)

jijiz

fredericmazue wrote:
Quote:
Me trompais-je? ^^

Apparament (si j'ose dire) oui, puisque sur ton écran rien n'apparaît :)
Ou plutôt non tu ne te trompes pas, mais l'objet qui a servi à construire le Painter est cette même QPixmap, ce me semble.

Je suis entierement d'accord avec toi pour le nom self.QPixMap, j'ai corrigé dans mon code.

D'apres ta remarque, je pense que je ne dois pas faire de drawpixmap ou bien creer un autre qpixmap temporaire puis le copier dans celui du qpainter?
Non, désolé, mais je ne vois pas la logique. Je donne ma langue au chat

fredericmazue

Quote:
D'apres ta remarque, je pense que je ne dois pas faire de drawpixmap ou bien creer un autre qpixmap temporaire puis le copier dans celui du qpainter?

Lol :lol:
Ton pixmap temporaire c'est pas déjà des fois un peu par harsard celui que tu as constitué ? Si tu en fais encore un autre, puis un autre, jusqu'où t'arrêteras tu ? :lol:
Quote:
Non, désolé, mais je ne vois pas la logique. Je donne ma langue au chat

Fais gaffe, j'ai un chat à côté de moi là :)

Lol :lol:
Pardonne moi de me marrer, mais :lol:
Bon on a dit au tout début des explications sur le double-buffering que ton image, une fois constituée en arrière plan (ce qui est fait présentement et à priori), doit être dessinée **DANS LA FENETRE** screugneugneu.
Alors comment ?
Maintenant tu as ta Pixmap.
La doc Qt dit

Quote:
The QPainter class performs low-level painting on widgets and other paint device

Toute la magie est dans le OTHER.
Une fenêtre est (par héritage) un QPaintDevice. Si tu instancies un **AUTRE** QPainter en passant la fenêtre en argument au constructeur, quand tu feras

self.autre.drawPixmap(QtCore.QPointF(0,0), self.QPixMap)

Dans la fenêtre tu dessineras

:lol:

jijiz

Hmm, je commence à comprendre la logique !
Je sens que j'y suis presque, MAIS... ça n'affiche toujours rien et je commence à culpabiliser de monopoliser ton temps pour ces broutilles.

class DrawGraph(QtGui.QFrame):
    def __init__(self, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.move(0, 0)
        self.setMinimumSize(800, 600)
        self.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.StyledPanel)
        self.setWindowTitle(self.tr("Test AFPy Objets Graphique"))       
         
        self.QPath = QtGui.QPainterPath()
        self.qpm = QtGui.QPixmap(800,600)
        
        self.QPainter = QtGui.QPainter(self.qpm)     
        self.QPath.addRect(10,10,10,10)
        self.QPainter.fillPath(self.QPath, QtGui.QBrush(QtCore.Qt.black))    
        self.QPainter.drawPath(self.QPath)  
        self.QPainter.end()
        
        newQP = QtGui.QPainter(self)
        newQP.drawPixmap(QtCore.QPointF(0,0), self.qpm) 
        
        
if __name__ == "__main__":
    
    app = QtGui.QApplication(sys.argv)
    window = DrawGraph()
    window.show()
    sys.exit(app.exec_())
fredericmazue

Quote:
je commence à culpabiliser de monopoliser ton temps pour ces broutilles.

Abonne toi à Programmez!, envoie moi un (très) gros chèque, et surtout adresse toi à moi avec la déférence que je mérite. Appelle moi Maître, ou même Vénérable Maître et ça ira :lol:

Quote:
window.show()

Y en a quand même qui ont la tête dure. Ah ça oui.
Dans l'idée du dessin en double-buffering, je t'ai dit et répété *** QUE TU DEVAiS TRACER TOI MEME EN DEHORS DE LA ROUTINE D'EVENEMENT DE DESSIN DE LA FENETRE ***
:twisted: :twisted: :twisted: :twisted: :twisted:

Je cris fort, mais j'ai l'impression que c'est un minimum là :lol:

Et toi kektufé ?

Tu fait ta petite bidouille comme ca dans le constructeur.
Alors si ça se trouve ta pixmap elle est dessinée au moment de la construction et tu ne la vois JAMAIS, même pas pendant une fraction d'éclair atomisé.

parce que:

window.show ça fait apparaître la fenêtre avec sa routine de dessin par défaut et ta bidouille hein où est-elle ? A la trappe, aux oubliettes, dans un trou noir.

Faut structurer code comme ça

class DrawGraph(QtGui.QFrame):
    def __init__(self, parent=None): 
      # peu importe ici
    
    def ma_methode_de_dessin():
       self.QPath = QtGui.QPainterPath()
       self.qpm = QtGui.QPixmap(800,600) 
       # etc, etc.

if __name__ == "__main__":
   
    app = QtGui.QApplication(sys.argv)
    window = DrawGraph()
    window.show()
    window.ma_methode_de_dessin() #!!!!!!!!!!
    sys.exit(app.exec_())

Réfléchi à ce profond enseignement petit scarabée et la lumière t'apparaîtra ... et ta Pixmap aussi :lol:

jijiz

okok, je vois mieux, mais je dois avoir une mauvaise vision car je le trouve pas ce :evil: :evil: :evil: :evil: :evil: de carré.

#==================================
# Constructor
#==================================
class DrawGraph(QtGui.QFrame):
    def __init__(self, parent=None):
        QtGui.QFrame.__init__(self, parent)
        self.move(0, 0)
        self.setMinimumSize(800, 600)
        self.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.StyledPanel)
        self.setWindowTitle(self.tr("Test AFPy Objets Graphique"))       
    
    def dessine_moi_le_carre_stp(self):
        self.QPath = QtGui.QPainterPath()
        self.qpm = QtGui.QPixmap(800,600)
        
        self.QPainter = QtGui.QPainter(self.qpm)     
        self.QPath.addRect(10,10,10,10)
        self.QPainter.fillPath(self.QPath, QtGui.QBrush(QtCore.Qt.black))    
        self.QPainter.drawPath(self.QPath)  
        self.QPainter.end()
        
        self.newQP = QtGui.QPainter(self)
        self.newQP.drawPixmap(QtCore.QPointF(0,0), self.qpm)
        self.newQP.end()
        
        
if __name__ == "__main__":
    
    app = QtGui.QApplication(sys.argv)
    window = DrawGraph()
    window.show()
    window.dessine_moi_le_carre_stp()
    
    sys.exit(app.exec_())
             
        
            
:evil: :evil: :oops: :roll: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil:
fredericmazue

lol et re-lol :lol:

Quand tu auras fini, tu pourras en effet écrire un tutorial. Mais pas sur PyQT; Sur l'art de ne pas en louper une.

Tiens pendant que j'y pense, les appeles aux méthode end comme self.newQP.end() n'ont rien à faire dans le code si tu lis *bien* la doc de QT.

Quote:
self.QPainter

keskondizai au fait, à propos de l'obfuscation :?:

Quote:
self.QPath.addRect(10,10,10,10)

un carré 10*10. Lol Microscopique.
Si ça se trouve il est dessiné (en 10,10) dans la barre de la fenêtre.

Bon tu ne t'es pas addressé à moi avec le respect qui m'est du, je me retire méditer dans ma grotte au Tibet :)

jijiz

Oh grand magnat pythonesque...

Si je n'appelle pas la fonction end sur mes deux qpainter, lorsque je ferme la fenêtre un warning apparait :

Quote:
It is dangerous to leave painters active on a widget outside of the PaintEvent

Même avec un gros gros rectangle, il n'affiche rien :
self.QPath.addRect(50,50,400,400)

Le truc c'est que je comprends lentement au début, mais après lorsque j'ai compri je roxxe ^^ :evil:

Traduction : je comprends vite mais il faut m'expliquer longtemps. Le soucis c'est que je n'ai certains reflexes ou mécanismes pour comprendre ou utiliser la doc à 100 %.

fredericmazue

Quote:
Oh grand magnat

Pas terrible ça...
Quote:
pythonesque...

Et beaucoup trop limitatif

Quote:
Si je n'appelle pas la fonction end sur mes deux qpainter, lorsque je ferme la fenêtre un warning apparait :

To be or no to be, self or not self, telle est la question à ta *portée*.
Sauras tu comprendre cela petit scarabée ?
Quote:
window.show()
window.dessine_moi_le_carre_stp()

Hier pressé par le temps j'ai voulu donner l'idée mais je me suis mal exprimé et je l'avoue sans réfléchir. :oops: et sans beaucoup de temps à y consacrer non plus.
Entre show et exec, il y a de grandes chance que les widgets ne soient pas, ou pas complètement, réalisés, donc finalement ton dessin sera écrasé à l'apparition de la fenêtre sur l'écran.
Il faut:
- bien comprendre comme est organisée une application de ce genre, PyQt, wxPython, Gtk, etc, le principe est toujours le même. Essaie de te renseigner sur le Net, tu en tireras profit (tu as une lacune là je pense)

- il faut réorganiser ton code. Dessiner en dehors de l'événement de dessin oui, je l'ai dit et je le maintiens. Mais essaie de dessiner en réponse à un clic ou un déplacement de souris. (D'ailleurs au final c'est bien ce que tu veux avoir alors raison de plus pour essayer comme ça)
Et là tu devrais avoir satisfaction.
Si j'ai le temps j'essaierai d'écrire un petit bout de code, mais je ne peux pas promettre. Toujours le problème du temps.

Monsieur Tomate
Re: Plusieurs Widgets sur un QFrame. Ordre d'affichage.

jijiz wrote:
Salut à tous,

J'instancie plusieurs QWidget dans une QFrame, je souhaiterais definir l'ordre de visibilité des widgets sur la fenêtre. Savez-vous comment fait-on cela?

Merqui.

Ju.

Salut,

Je tenais à apporter quelques précisions suite à ces posts, parce que je me suis heurté aux mêmes problèmes.

Premièrement, on dit Qt et non QT... on ne parle pas de QuickTime, ici. Quitte à être rigoureux, autant l'être jusqu'au bout. Non mais !

Ensuite, attention : je fais partie de la masse qui s'est noyée dans l'imbuvable café américain et il se trouve que la solution à ce problème est d'utiliser la méthode "raise" du widget correspondant pour l'envoyer en avant-plan. C'est super simple, efficace et mis en place en 30 secondes... mais en Java avec Qt Jambi, donc.

Cette méthode est-elle disponible avec PyQt ? Je pense que ce serait intéressant de vérifier.

Au plaisir...

fredericmazue

Quote:
Premièrement, on dit Qt et non QT... on ne parle pas de QuickTime, ici. Quitte à être rigoureux, autant l'être jusqu'au bout. Non mais !

Ah mais oui :)
En théorie...
Parce qu'en pratique la touche Q est bien près de la touche Caps Lock.... :lol:

Quote:
Ensuite, attention : je fais partie de la masse qui s'est noyée dans l'imbuvable café américain

Là question rigueur c'est quand même un peu moins bien (Non mais! ;) :) )

Quote:
Ensuite, attention : je fais partie de la masse qui s'est noyée dans l'imbuvable café américain et il se trouve que la solution à ce problème est d'utiliser la méthode "raise" du widget correspondant pour l'envoyer en avant-plan. C'est super simple, efficace et mis en place en 30 secondes... mais en Java avec Qt Jambi, donc.

Je ne connais pas Jambi pour le moment.
Mais raise est une méthode de QWdiget dans Qt (avec t minuscule), donc raise n'a rien à voir avec Jambi intrinsèquement à priori.
En Qt, raise place le widget concerné au dessus des autres. Il y a aussi la méthode cousine stackUnder qui place le widget au dessous de celui passé en argument.
Donc on peut arranger avec ça l'ordre des widgets.
Mais si cela te convient, je ne pense pas que cela réponde à la question originale qui était (pour autant que je me souvienne) grosso modo de faire une "animation de widgets".

Quote:
Cette méthode est-elle disponible avec PyQt ? Je pense que ce serait intéressant de vérifier.

Sans l'avoir vérifié, je parierai très volontiers que raise et stackUnder existe sous PyQt.

Quote:
Au plaisir...

Au plaisir également :)