IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec Python Discussion :

PyGTK, Drawing Area et rafra�chissement de fen�tre.


Sujet :

GTK+ avec Python

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre confirm�
    Profil pro
    Inscrit en
    D�cembre 2011
    Messages
    65
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 65
    Par d�faut PyGTK, Drawing Area et rafra�chissement de fen�tre.
    Bonjour � tous,

    Je suis en plein parcours initiatique de Python. Pour m'aider, j'utilise le livre de M.SWINNEN qui utilise la librairie Tkinter pour r�aliser des interfaces graphiques. Moi, je pr�f�re plut�t GTK et je me suis donc mis en t�te de faire les exercices et de les adapter � GTK. Dans l'un des premiers exercices, un petite interface permet de dessiner des lignes dans une zone de dessin avec un bouton pour tracer et un bouton pour choisir une couleur al�atoire. Jusque l� pas de probl�me, je m'en suis sorti (je n'utilise pas encore les classes car je n'ai pas encore abord� ce chapitre).

    J'ai toutefois une chose qui m'agace profond�ment. Lorsque je redimensionne ma fen�tre, tout mon dessin s�efface, idem si je la cache par une autre fen�tre.

    J'ai fais des recherches sur Internet et trouver une s�rie de ligne de code qui devrait r�soudre mon probl�me. Mais apr�s plusieurs essais, je n'arrive � rien de concret. Mon niveau n'�tant pas assez �lev�. Quelqu'un pourrait-il m'expliquer comment y arriver. Notamment qu'elles sont les arguments � passe r et me donner quelques explications sur les signaux utilis�es. Fa�on gros neuneu.

    - J'ai aussi entendu parler de double_buffering. Peut-t-on l'utiliser pour �a?
    - Par la suite,est-ce que je peux cr�er un module sp�cifique d�di� au rafra�chissement de ma fen�tre?

    Merci d'avance pour votre aide. Je d�j� fais une recherche sur le site et trouv� des exemples. Une des astuces utilis�es et de rappeler la fonction qui a servi � dessiner l'objet. Mais cela ne fonctionne que dans le cas d'un dessin enti�rement pr�d�fini.

    NOTA: Si vous avez d'autres petites astuces pour am�liorer mon code, je suis preneur.

    Ci-dessous, le code que j'ai fais o� je essay� d'ajouter la gestion de ma fen�tre. (J'ai fait des copier-coller, mais j'admets ne pas bien saisir � quoi tout cela correspond)

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
     
    #!/usr/bin/python
     
    import gtk
    from random import randrange
     
    # Dessiner une ligne sur la zone de dessin   
    def expose(widget, data):
        global x1, x2, y1, y2, couleur
        cr = data.window.cairo_create()
        cr.set_source_rgb(couleur[0], couleur[1], couleur[2]) 
        cr.set_line_width(2)
     
        #w = data.allocation.width
        #h = data.allocation.height
        #print w, h
     
        cr.move_to(x1, y1)
        cr.line_to(x2, y2)
        cr.stroke()
     
        y2, y1 = y2+10, y1-10 
     
    # Choisir une couleur au hasard
    def color(widget):
        'test'
        global couleur
        i = 0
        while i<3:
            couleur[i] = randrange(0,255)/255.0
            i += 1
     
    ############ Gestion Pixmap 
    # Create a new backing pixmap of the appropriate size
    def configure_event(widget, event):
        global pixmap
     
        x, y, width, height = widget.get_allocation()
        pixmap = gtk.gdk.Pixmap(widget.window, width, height)
        pixmap.draw_rectangle(widget.get_style().white_gc,
                              True, 0, 0, width, height)
     
        return True
     
    # Redraw the screen from the backing pixmap
    def expose_event(widget, event):
        x , y, width, height = event.area
        widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL],
                                    pixmap, x, y, x, y, width, height)
        return False
     
    def button_press_event(widget, event):
        if event.button == 1 and pixmap != None:
            expose(widget, event.x, event.y)
        return True
     
    def motion_notify_event(widget, event):
        if event.is_hint:
            x, y, state = event.window.get_pointer()
        else:
            x = event.x
            y = event.y
            state = event.state
     
        if state & gtk.gdk.BUTTON1_MASK and pixmap != None:
            expose(widget, x, y)
     
        return True
    #################
     
     
    # Initialisation des variables
    couleur = [0, 0, 0]
    x1, y1, x2, y2 = 30, 30, 570, 570
    # Backing pixmap for drawing area
    pixmap = None
     
     
    # Cr?ation de l'interface
    PyApp = gtk.Window()
    PyApp.set_title("Formes")
    PyApp.set_size_request(800, 600)
    PyApp.set_border_width(20)
    PyApp.set_position(gtk.WIN_POS_CENTER)
    PyApp.connect("destroy", gtk.main_quit)
     
    darea = gtk.DrawingArea()
     
    ###################### Copier-coller pour gestion de l'affichage
    # Signals used to handle backing pixmap
    darea.connect("expose_event", expose_event)
    darea.connect("configure_event", configure_event)
     
    # Event signals
    darea.connect("motion_notify_event", motion_notify_event)
    darea.connect("button_press_event", button_press_event)
     
    darea.set_events(gtk.gdk.EXPOSURE_MASK
                            | gtk.gdk.LEAVE_NOTIFY_MASK
                            | gtk.gdk.BUTTON_PRESS_MASK
                            | gtk.gdk.POINTER_MOTION_MASK
                            | gtk.gdk.POINTER_MOTION_HINT_MASK)
     
    ##################
     
     
    # Suite de l'interface
    button1 = gtk.Button(label="Tracer une ligne")
    button1.set_size_request(130, 35)
    button1.connect("clicked", expose, darea)
     
    button2 = gtk.Button(label="Changer de couleur")
    button2.set_size_request(130, 35)
    button2.connect("clicked", color)
     
    button3 = gtk.Button(label="Quitter")
    button3.set_size_request(130, 35)
    button3.connect("clicked", gtk.main_quit)
     
    vbox = gtk.VBox(False, 5)
    hbox = gtk.HBox(False, 3)
     
    vbox.pack_start(button1, False, True, 3)
    vbox.pack_start(button2, False, False, 3)
    vbox.pack_end(button3, False, False, 3)
     
    hbox.pack_start(darea, True, True)
    hbox.pack_end(vbox, False, False)
     
    PyApp.add(hbox)
    PyApp.show_all()
    gtk.main()

  2. #2
    Membre chevronn�
    Inscrit en
    Janvier 2007
    Messages
    329
    D�tails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 329
    Par d�faut
    Salut,

    Citation Envoy� par austin57 Voir le message
    Lorsque je redimensionne ma fen�tre, tout mon dessin s�efface, idem si je la cache par une autre fen�tre.
    ...
    Je d�j� fais une recherche sur le site et trouv� des exemples. Une des astuces utilis�es et de rappeler la fonction qui a servi � dessiner l'objet. Mais cela ne fonctionne que dans le cas d'un dessin enti�rement pr�d�fini.
    Effectivement, ca ne fonctionne pas du tout pareil entre pygtk et Tkinter.
    Sous PyGTK, tu dois m�moriser toutes tes lignes � tracer et les redessiner lorsque tu captes le signal 'expose-event'.


    Citation Envoy� par austin57 Voir le message
    - J'ai aussi entendu parler de double_buffering. Peut-t-on l'utiliser pour �a?
    - Par la suite,est-ce que je peux cr�er un module sp�cifique d�di� au rafra�chissement de ma fen�tre?
    Le double-buffering, c'est uniquement utilis� par gtk en interne pour �viter le flickering. Il est d�sactivable pour �ventuellement am�liorer un peu les performances par rapport au rendu. �a ne concerne en rien ton probl�me.

    Tu peux effectivement reprogrammer un module ou une classe qui impl�mente le canevas de Tkinter en GTK, � savoir qui m�morise la liste d'objets (des lignes color�es dans ton cas) et les redessine en cas de redimensionnement. C'est m�me une tr�s bonne id�e (et un bon exercice) !


    -

  3. #3
    Membre confirm�
    Profil pro
    Inscrit en
    D�cembre 2011
    Messages
    65
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 65
    Par d�faut
    @ monnomamoi
    Merci pour ces premiers �l�ments de r�ponse.
    Je vais effectivement me cr�er, pour cet exercice, un module pour redessiner et/ou redimensionner les lignes trac�es. Je crois que ce sera un excellent entra�nement.



    Toutefois, j'aimerai quand m�me trouver une solution plus g�n�rale, qui fonctionnerai quelque soit le type de dessin. Je pense que les lignes de codes r�cup�r�es de l'exemple PyGTK scribble.py et que j'ai int�gr� dans mon programme en sont la cl�. Il me reste � savoir comment bien les int�grer et c'est l� que j'aurai besoin de votre aide. Merci d'avance pour vos conseils.

  4. #4
    Membre chevronn�
    Inscrit en
    Janvier 2007
    Messages
    329
    D�tails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 329
    Par d�faut
    Tu peux aussi t'inspirer de cet exemple :
    http://www.eurion.net/python-snippet...h%20Cairo.html

    �a donne d�j� un bon aper�u des bases.

  5. #5
    Membre confirm�
    Profil pro
    Inscrit en
    D�cembre 2011
    Messages
    65
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 65
    Par d�faut
    J'ai encore fouin� � travers le web et je pense avoir trouv� un exemple int�ressant. Toujours en utilisant Cairo. 2 fichiers.
    Si j'ai bien compris, le premier fichier, � nommer framework.py cr�e un widget d�riv� de 'drawing area' g�rant le redimensionnement et le masquage de la fen�tre. L'autre fichier �tant le programme lui-m�me faisant appel � framework.py

    Il me reste � trouver comment faire le lien entre mon programme et framework.py ?!! Et pour l'instant, je s�che, �a fait bien 1h que je me retourne l'esprit l�-dessus.

    L'adresse du site o� j'ai trouv��a : http://www.tortall.net/mu/wiki/PyGTKCairoTutorial

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #! /usr/bin/env python
    import pygtk
    pygtk.require('2.0')
    import gtk, gobject, cairo
     
    # Create a GTK+ widget on which we will draw using Cairo
    class Screen(gtk.DrawingArea):
     
        # Draw in response to an expose-event
        __gsignals__ = { "expose-event": "override" }
     
        # Handle the expose-event by drawing
        def do_expose_event(self, event):
     
            # Create the cairo context
            cr = self.window.cairo_create()
     
            # Restrict Cairo to the exposed area; avoid extra work
            cr.rectangle(event.area.x, event.area.y,
                    event.area.width, event.area.height)
            cr.clip()
     
            self.draw(cr, *self.window.get_size())
     
        def draw(self, cr, width, height):
            # Fill the background with gray
            cr.set_source_rgb(0.5, 0.5, 0.5)
            cr.rectangle(0, 0, width, height)
            cr.fill()
     
    # GTK mumbo-jumbo to show the widget in a window and quit when it's closed
    def run(Widget):
        window = gtk.Window()
        window.connect("delete-event", gtk.main_quit)
        widget = Widget()
        widget.show()
        window.add(widget)
        window.present()
        gtk.main()
     
    if __name__ == "__main__":
        run(Screen)
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #! /usr/bin/env python
    import framework
    from math import pi
     
    class Transform(framework.Screen):
        def draw(self, cr, width, height):
            cr.set_source_rgb(0.5, 0.5, 0.5)
            cr.rectangle(0, 0, width, height)
            cr.fill()
     
            # draw a rectangle
            cr.set_source_rgb(1.0, 1.0, 1.0)
            cr.rectangle(10, 10, width - 20, height - 20)
            cr.fill()
     
            # set up a transform so that (0,0) to (1,1)
            # maps to (20, 20) to (width - 40, height - 40)
            cr.translate(20, 20)
            cr.scale((width - 40) / 1.0, (height - 40) / 1.0)
     
            # draw lines
            cr.set_line_width(0.01)
            cr.set_source_rgb(0.0, 0.0, 0.8)
            cr.move_to(1 / 3.0, 1 / 3.0)
            cr.rel_line_to(0, 1 / 6.0)
            cr.move_to(2 / 3.0, 1 / 3.0)
            cr.rel_line_to(0, 1 / 6.0)
            cr.stroke()
     
            # and a circle
            cr.set_source_rgb(1.0, 0.0, 0.0)
            radius = 1
            cr.arc(0.5, 0.5, 0.5, 0, 2 * pi)
            cr.stroke()
            cr.arc(0.5, 0.5, 0.33, pi / 3, 2 * pi / 3)
            cr.stroke()
     
    framework.run(Transform)

  6. #6
    Membre chevronn�
    Inscrit en
    Janvier 2007
    Messages
    329
    D�tails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 329
    Par d�faut
    Ton exemple fait la m�me chose que le mien, mais en plus compliqu� puisqu'il coupe le programme en 2 fichiers.

    La seule astuce � retenir, c'est le "cr.scale()" qui permet de changer l'�chelle du canevas (ou plut�t du cairo context) au lieu de changer les dimensions du dessin.

    Un petit exemple (vite fait mal fait) de canevas qui impl�mente la m�thode "create_line" comme avec Tkinter :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    import gtk
    import cairo
     
    class Canevas(gtk.DrawingArea):
        def __init__(self, w, h):
            gtk.DrawingArea.__init__(self)
            self.dim = (w, h)
            self.set_size_request(*self.dim)
            self.lines = []
            self.context = None
            self.connect('expose-event', self.expose)
            self.show()
     
        def expose(self, area, event):
            self.context = area.window.cairo_create()
            self.context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
            self.context.clip()
            self.context.scale(event.area.width/float(self.dim[0]), event.area.height/float(self.dim[1]))
            self.context.set_line_width(2.0)
            for l in self.lines:
                self.draw_line(*l)
            return False
     
        def draw_line(self, x1, y1, x2, y2, c):
            if self.context is None:
                return
            self.context.set_source_rgb(*c)
            self.context.move_to(x1, y1)
            self.context.line_to(x2, y2)
            self.context.stroke()
            return
     
        def create_line(self, x1, y1, x2, y2, c):
            self.lines.append( (x1, y1, x2, y2, c) )
            self.draw_line(*self.lines[-1])
            return
     
     
     
    if __name__ == '__main__':
        win = gtk.Window()
        win.connect('destroy', gtk.main_quit)
        can = Canevas(400, 300)
        win.add(can)
        can.create_line(20, 50, 350, 300, [1.0,0.0,0.0])
        can.create_line(20, 20, 200, 200, [0.0,1.0,0.0])
        can.create_line(100, 0, 100, 200, [0.0,0.0,1.0])
        win.show()
        gtk.main()
    -

  7. #7
    Membre confirm�
    Profil pro
    Inscrit en
    D�cembre 2011
    Messages
    65
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 65
    Par d�faut
    Merci monnomamoi

    Je t'avoue ne pas avoir encore tout compris � 100%.
    Mais j'avance dans ma compr�hension de PyGTK, notamment l'importance des signaux tel que "expose". Idem pour l'astuce Scale de Cairo qui est vraiment pratique et simplifie r�ellement les choses.

    Je vais essayer de r�aliser mon propre petit module afin de tester cela.

    Cordialement,

Discussions similaires

  1. Pygtk: comment utiliser le widget Drawing Area
    Par leousch dans le forum GTK+ avec Python
    R�ponses: 9
    Dernier message: 23/08/2009, 12h44
  2. Dessiner sur une drawing area
    Par Fibus dans le forum GTK+ avec C & C++
    R�ponses: 8
    Dernier message: 19/12/2007, 16h57
  3. drawing area et it�rations
    Par Rniamo dans le forum GTK+ avec C & C++
    R�ponses: 7
    Dernier message: 07/11/2007, 19h00
  4. Drawing area
    Par Blackshade dans le forum GTK+ avec PHP
    R�ponses: 4
    Dernier message: 06/06/2007, 16h51
  5. Image de fond dans un drawing area
    Par smux dans le forum GTK+ avec C & C++
    R�ponses: 1
    Dernier message: 15/09/2006, 11h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo