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

Tkinter Python Discussion :

Identifier couleur du pixel sur lequel on clique


Sujet :

Tkinter Python

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Points : 273
    Points
    273
    Par défaut Identifier couleur du pixel sur lequel on clique
    Bonjour,

    j'ai une grille qui contient des cases colorées différemment. Je voudrais récupérer la couleur de la case sur laquelle je clique. Connaitriez-vous une formule simple qui permet de faire cela, svp?

    Je vous remercie d'avance,
    Cordialement,
    Arsène

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    Il faut utiliser les méthodes liées aux items, à première vue c'est itemcget avec l'option fill qu'il vous faut.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Points : 273
    Points
    273
    Par défaut
    Merci. C'est bien ça.

    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
    import tkinter as tk
    from tkinter import *
     
    root = tk.Tk()
     
    def myColor(evt):
     
        print(canvas.itemcget(rect_item,'fill'))
     
    canvas = Canvas(root, bg="pale goldenrod")
    canvas.grid()
     
    rect_item = canvas.create_rectangle(0,0,150,150, outline="blue", fill="green")
     
    canvas.bind('<Button-1>', myColor)
     
    root.mainloop()
    Maintenant, comme j'ai une grille avec plusieurs rectangle, il va me falloir récupérer le nom du rectangle sur lequel je clique.

  4. #4
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    Maintenant, comme j'ai une grille avec plusieurs rectangle, il va me falloir récupérer le nom du rectangle sur lequel je clique.
    Normalement non ! Il y a des méthodes à découvrir, il faut tenter de les utiliser, ça simplifiera énormément la vie...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def click(event):
        x, y = event.x, event.y
        item = canvas.find_closest(x, y)
       # traitement de l'item
    Simple non ?
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par Arsene12 Voir le message
    Maintenant, comme j'ai une grille avec plusieurs rectangle, il va me falloir récupérer le nom du rectangle sur lequel je clique.
    canvas.find_withtag('current') suffit. Ça ne retourne pas de nom mais un entier (l'identifiant de l'item courant) ou une liste vide. Et dans le code précédent, vous utilisiez déjà .find_overlapping(evt.x, evt.y, evt.x, evt.y) qui fait un peu la même chose (mais différemment).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Points : 273
    Points
    273
    Par défaut
    Bonjour,

    à ce sujet, je suis justement en train de m'interroger sur la différence entre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    canvas.find_overlapping(evt.x, evt.y, evt.x, evt.y)
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    canvas.find_closest(evt.x, evt.y, evt.x, evt.y)

    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
    import tkinter as tk
     
    DIM_GRILLE = (8, 8)
    DIM_CASE = 50
    DIM_LIGNE = 1
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASE + (DIM_GRILLE[0]+1)*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASE + (DIM_GRILLE[1]+1)*DIM_LIGNE
    )
     
     
    def destroyer(evt) :
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        print("CLOSEST = "+str(can.find_closest(evt.x, evt.y, evt.x, evt.y)))
        print("OVERLAPPING= "+str(r))
        print("CURRENT= "+str(can.find_withtag('current')))
        if not r :
            return
        rid = r[0]
     
        # Récupération des index ligne et colonne contenant l'id rectangle
        for il, ligne in enumerate(items) :
            if rid in ligne :
                ic = ligne.index(rid)
                break
     
        # Suppressions de la ligne et colonne du tableau items
        # Et suppression dans le canevas
        lid = items.pop(il)
        for oid in lid :
            can.delete(oid)
     
        for ligne in items :
            oid = ligne.pop(ic)
            can.delete(oid)
     
        if not any(items) :
            # Plus rien à faire, le tableau d'items est vide.
            return
     
        nombreLignes = len(items)
        nombreColonnes = len(items[0])
     
        # Calculs des dimensions de chaque lignes
        # Soustraction des lignes de la hauteur du canevas
        hautCan = DIM_CANEVAS[1] - (nombreLignes+1) * DIM_LIGNE
        # Répartition de la hauteur
        hauteurs = [hautCan // nombreLignes] * nombreLignes
        for i in range(hautCan % nombreLignes) :
            hauteurs[i] += 1
     
        # Calculs des dimensions de chaque colonnes
        largCan = DIM_CANEVAS[0] - (nombreColonnes+1) * DIM_LIGNE
        largeurs = [largCan // nombreColonnes] * nombreColonnes
        for i in range(largCan % nombreColonnes) :
            largeurs[i] += 1
     
        # Mises à jour des dimensions
        ih = 0
        y = DIM_LIGNE
        for ligne in items :
            il = 0
            x = DIM_LIGNE
            for oid in ligne :
                can.coords(oid, x, y, x+largeurs[il], y+hauteurs[ih])
                x += largeurs[il] + DIM_LIGNE
                il += 1
            ih += 1
            try :
                y += hauteurs[ih] + DIM_LIGNE
            except IndexError :
                # Dernier tour de boucle
                break
     
     
    fenetre = tk.Tk()
     
    can = tk.Canvas(
        fenetre,
        width=DIM_CANEVAS[0],
        height=DIM_CANEVAS[1],
        bg='black',
        highlightthickness=0,
    )
    can.grid()
     
    items = []
    colors = ['red', 'yellow']
    y = DIM_LIGNE
     
    for ligne in range(DIM_GRILLE[1]) :
        x = DIM_LIGNE
        ids = []
        colors.reverse()
        for col in range(DIM_GRILLE[0]) :
            i = can.create_rectangle(
                x, y, x+DIM_CASE, y+DIM_CASE,
                fill=colors[col % 2],
                width=0,
            )
            ids.append(i)
            x += DIM_CASE + DIM_LIGNE
        items.append(ids)
        y += DIM_CASE + DIM_LIGNE
     
    can.bind('<Button-1>', destroyer)
     
    fenetre.mainloop()
    Je pense que overlapping donne l'identifiant du rectangle sur lequel on clique tandis que closest donne l'identifiant du rectangle, crée par la méthode Canvas.create_rectangle(x0, y0, x1, y1, option, ...), qui possède les x0 et y0 les plus proches de evt.x et evt.y. Veuillez me rectifier si je me trompe.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par Arsene12 Voir le message
    Je pense que overlapping donne l'identifiant du rectangle sur lequel on clique tandis que closest donne l'identifiant du rectangle, crée par la méthode Canvas.create_rectangle(x0, y0, x1, y1, option, ...), qui possède les x0 et y0 les plus proches de evt.x et evt.y. Veuillez me rectifier si je me trompe.
    Que disent les descriptions des méthodes .find_overlapping et .find_closest?
    Ce que çà fait est d'abord décrit dans votre documentation préférée...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Points : 273
    Points
    273
    Par défaut
    Si je remplace Canvas.find_closest(x, y, halo=None, start=None) par Canvas.find_closest(evt.x, evt.y, halo=None, start=None)

    find_closest(evt.x,evt.y) retourne un tuple contenant l’identifiant numérique d’un seul item, celui qui est le plus proche du point (x, y).
    J'ai un peu de mal à comprendre closest dans le code ci-dessous. Je pensais qu'en cliquant sur n'importe quel rectangle, j'obtiendrai l'identifiant d'un rectangle mitoyen. Quand je fais le test, c'est pas le cas.

    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
    import tkinter as tk
     
    DIM_GRILLE = (8, 8)
    DIM_CASE = 50
    DIM_LIGNE = 1
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASE + (DIM_GRILLE[0]+1)*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASE + (DIM_GRILLE[1]+1)*DIM_LIGNE
    )
     
    def destroyer(evt) :
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        print("CLOSEST = "+str(can.find_closest(evt.x, evt.y, evt.x, evt.y)))
        print("OVERLAPPING= "+str(r))
        print("CURRENT= "+str(can.find_withtag('current'))) 
     
     
    fenetre = tk.Tk()
     
    can = tk.Canvas(
        fenetre,
        width=DIM_CANEVAS[0],
        height=DIM_CANEVAS[1],
        bg='black',
        highlightthickness=0,
    )
    can.grid()
     
    items = []
    colors = ['red', 'yellow']
    y = DIM_LIGNE
     
    for ligne in range(DIM_GRILLE[1]) :
        x = DIM_LIGNE
        ids = []
        colors.reverse()
        for col in range(DIM_GRILLE[0]) :
            i = can.create_rectangle(
                x, y, x+DIM_CASE, y+DIM_CASE,
                fill=colors[col % 2],
                width=0,
            )
            ids.append(i)
            x += DIM_CASE + DIM_LIGNE
        items.append(ids)
        y += DIM_CASE + DIM_LIGNE
     
    can.bind('<Button-1>', destroyer)
     
    fenetre.mainloop()

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Arsene12 Voir le message
    J'ai un peu de mal à comprendre closest dans le code ci-dessous. Je pensais qu'en cliquant sur n'importe quel rectangle, j'obtiendrai l'identifiant d'un rectangle mitoyen. Quand je fais le test, c'est pas le cas.
    Est-ce que l'item sur celui qu'on clique n'est pas le plus proche?
    Çà fait juste ce que çà dit... pas ce que vous pensez/voulez que çà fasse.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Points : 273
    Points
    273
    Par défaut
    Quand je clique sur la 1ère case en haut à gauche, j'obtiens tantôt 1 tantôt 2, 9 ou 10. Ce sont des cases mitoyennes, donc ça va. Quand ça répond 1 c'est même la case dans laquelle on clique, c'est encore mieux. Par contre, pour les suivantes rien ne va plus. Si je clique sur la case 20 par exemple, j'obtiens : 45, 46, 47, 52, 53 ou 54 qui sont des cases éloignées.

    Des exemples :
    CLOSEST = (64,)
    CURRENT= (46,)
    CLOSEST = (36,)
    CURRENT= (26,)
    CLOSEST = (46,)
    CURRENT= (12,)
    CLOSEST = (64,)
    CURRENT= (14,)
    CLOSEST = (56,)
    CURRENT= (16,)
    CLOSEST = (62,)
    CURRENT= (43,)
    CLOSEST = (64,)
    CURRENT= (45,)
    CLOSEST = (64,)
    CURRENT= (47,)
    CLOSEST = (64,)
    CURRENT= (62,)
    CLOSEST = (64,)
    CURRENT= (61,)

    J'ai testé aussi la méthode ENCLOSED avec laquelle j'ai pas de problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print("ENCLOSED = "+str(can.find_enclosed(evt.x, evt.y, 0, 0))) # donne les identifiants de toutes les cases situées au dessus et à gauche de la case sur laquelle on clique.
    En fait j'ai compris. Entre les parenthèses il faut mettre des 0 pour x2 et y2.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print("CLOSEST = "+str(can.find_closest(evt.x, evt.y, 0, 0)))
    Dans ce cas ça renvoie la même chose que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print("CURRENT= "+str(can.find_withtag('current')))

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Points : 273
    Points
    273
    Par défaut
    Je comprends mieux maintenant dans le cas où j'ai une grille qui contient des rectangles avec des champs de texte à l'intérieur :

    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
    import tkinter as tk
     
    DIM_GRILLE = (8, 8)
    DIM_CASE = 50
    DIM_LIGNE = 1
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASE + (DIM_GRILLE[0]+1)*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASE + (DIM_GRILLE[1]+1)*DIM_LIGNE
    )
     
    def destroyer(evt) :
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        print("CLOSEST = "+str(can.find_closest(evt.x, evt.y, 0, 0)))
        print("OVERLAPPING= "+str(r))
        print("CURRENT= "+str(can.find_withtag('current'))) 
        print("ENCLOSED = "+str(can.find_enclosed(evt.x, evt.y, evt.x, evt.y)))
     
    fenetre = tk.Tk()
     
    can = tk.Canvas(
        fenetre,
        width=DIM_CANEVAS[0],
        height=DIM_CANEVAS[1],
        bg='black',
        highlightthickness=0,
    )
    can.grid()
     
    items = []
    colors = ['red', 'yellow']
    y = DIM_LIGNE
     
    for ligne in range(DIM_GRILLE[1]) :
        x = DIM_LIGNE
        ids = []
        colors.reverse()
        for col in range(DIM_GRILLE[0]) :
            text_item = can.create_text(x+DIM_CASE/2, y+DIM_CASE/2, text="         ", fill="white")
            bbox = can.bbox(text_item)
            i = can.create_rectangle(bbox, outline="red", fill=colors[col % 2])
            can.tag_raise(text_item,i)
            ids.append(i)
            x += DIM_CASE + DIM_LIGNE
        items.append(ids)
        y += DIM_CASE + DIM_LIGNE
     
    can.bind('<Button-1>', destroyer)
     
    fenetre.mainloop()
    - print("CLOSEST = "+str(can.find_closest(evt.x, evt.y, 0, 0))) : Si je clique à l'extérieur du champs de texte, j'obtiens l'identifiant d'un rectangle.

    - print("OVERLAPPING= "+str(r)) : Si je clique à l'extérieur du champs de texte, j'obtiens rien mais si je clique sur le champs de texte j'obtiens l'identifiant du rectangle et l'identifiant du champs de texte (tuple).

    - print("CURRENT= "+str(can.find_withtag('current'))) : Si je clique à l'extérieur du champs de texte, j'obtiens l'identifiant du rectangle et si je clique sur le champs de texte j'obtiens l'identifiant du champs de texte.

    Par contre je pensais qu'en cliquant à l'extérieur d'un champs de texte, dans un rectangle, j'avais quand même la possibilité de récupérer l'identifiant du champs de texte en utilisant la méthode enclosed. Je sais pas comment faire.
    Canvas.find_enclosed(x1, y1, x2, y2)
    Retourne la liste des identifiants numériques des items situés entièrement à l’intérieur du rectangle déterminé par (x1, y1) (coin supérieur gauche) et (x2, y2) (coin inférieur droit).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 26/10/2012, 19h21
  2. Réponses: 12
    Dernier message: 09/06/2009, 10h26
  3. changer couleur de pixels sur PictureBox
    Par avigeilpro dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 30/06/2006, 23h09
  4. Réponses: 5
    Dernier message: 03/04/2006, 16h50
  5. Réponses: 3
    Dernier message: 15/02/2006, 17h27

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