#1 Thu 27 March 2025 23:08
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
QGIS: programme python affichage champ attribut sur clic
Bonjour,
En prenant comme exemple un tuto j'essaie d'afficher dans un champ type QLineEdit la valeur d'un champ de la couche active, en lien avec un click.
Code:
ef display_point(self, point, button): # Affiche les coordonnées du clic self.dlg.hide() # cache la boite de dialogue coords = "{:.3f}, {:.3f}".format(point.x(), point.y()) ## formatage des coordonnées self.dlg.lineEdit.setText(coords) # affichage des coordonnées self.dlg.NumParc.setText(coord2) # affichage des infos du champ de la couche active self.dlg.LineTest.append("Test") self.dlg.show() # affiche de nouveau la boite de dialogue
J'ai un code qui semble convenir mais mes compétences en python sont celles d'un débutant et j'ai du mal à insérer le code suivant à la place de la ligne ou se trouve NumParc. Le champ de la table attributaire que je veux afficher s'appelle id
Code:
layer = iface.activeLayer() layer.feature[id]
J'espère avoir été assez clair.
Merci de votre aide, Marcopololo
Hors ligne
#2 Sun 30 March 2025 18:04
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Je suis arrivé à afficher l'attribut d'un champ de ma couche "parcelles moyenmoutier".
Et j'ai plusieurs questions.
1. J'aurais aimé plutôt que de définir une couche précise, que le code s'applique à la couche active mais lorsque j’utilise
Code:
activeLayer()
cela ne fonctionne pas j'ai une erreur QgsProject' object has no attribute 'activeLayer'. a priori si j'ai bien compris c'est parce que activeLayer dépend de la class QgisInterface ?
2. J'ai tenté d'utilisé self.iface pour que se soit le id de la zone cliquée qui s'affiche et non pas le premier champ de la table ? Faut il rajouter un paramètre
dans def display_point ?
Merci d'avance de votre aide
Marcopololo
Code:
def display_point(self, point, button): # Affiche les coordonnées du clic self.dlg.hide() # cache la boite de dialogue coords = "{:.3f}, {:.3f}".format(point.x(), point.y()) ## formatage des coordonnées #coord2 = "{:.4f}, {:.4f}".format(point.x(), point.y()) ## formatage des coordonnées layer = self.iface.activeLayer() projet = QgsProject.instance() couches = projet.mapLayers() couchePAR = projet.mapLayersByName("parcelles moyenmoutier")[0] enregistrements = couchePAR.getFeatures() e = next(couchePAR.getFeatures()) numP = e.attributes()[1] self.dlg.lineEdit.setText(coords) # affichage des coordonnées self.dlg.NumParc.setText(numP) # affichage id parcelle self.dlg.LineTest.append("Test") self.dlg.show() # affiche de nouveau la boite de dialogue
Hors ligne
#3 Mon 31 March 2025 12:02
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Après de multiples recherches et d'un début apprentissage de python, j'ai enfin trouvé ce que je cherchais. Il me restera à récupérer les coordonnées sur un click. Par contre j'ai tout de même un soucis dans les tests effectués en console python. Ma couche pointDemo se créé bien ainsi que mon champ, mais la condition if avec within ne donne aucun résultat ? Es ce que cela peut être lié au type de couche geopackage ? J'ai testé avant d'utiliser la condition if et j'ai bien toute la liste de mes valeurs ?
J'ai essayé avec intersecs, contains et c'est j'ai le même soucis
Code:
projet = QgsProject.instance() coucheParcelles = projet.mapLayersByName("parcelles moyenmoutier")[0] entites = coucheParcelles.getFeatures() #création point en mémoire layer = QgsVectorLayer('Point?crs=epsg:4326&field=id:integer','pointDemo','memory') pr = layer.dataProvider() pointParc = QgsFeature() pointParc.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(48.3815098,6.9509046))) pr.addFeatures([pointParc]) layer.updateExtents() projet.addMapLayers([layer]) print(layer.sourceCrs()) #Recherche champ ou se trouve mon point for e in entites: if pointParc.geometry().within(e.geometry()): print(e.attributes()[1])
Dernière modification par Marcopololo (Mon 31 March 2025 12:04)
Hors ligne
#4 Mon 31 March 2025 16:06
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Bon, j'ai trouvé l'erreur, j'ai inversé les coordonnées X et Y.
Ca fonctionne. Maintenant reste à intégrer cela avec un click reccherche coordonnées
Hors ligne
#5 Mon 31 March 2025 23:34
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Je continue avec mes questions. J'ai réussi à créer une première partie dans laquelle je récupère les coordonnées x et y que j'affiche dans un champ et la seconde partie ci dessus.
Quel code me permettrait de réinjecter ces coordonnées sur click dans la ligne ci dessous à la place des coordonnées statiques ?
Elles sont sous la forme suivante :
Code:
def display_point(self, point, button): # Affiche les coordonnées du clic self.dlg.hide() # cache la boite de dialogue coords = "{}, {}".format(point.x(), point.y()) ## formatage des coordonnées
Code partie coordonnées statiques :
Code:
pointParc.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(48.3815098,6.9509046)))
Merci d'avance de votre aide
Hors ligne
#6 Tue 01 April 2025 07:26
- Benoit D
- Participant assidu
- Date d'inscription: 17 Jul 2018
- Messages: 158
Re: QGIS: programme python affichage champ attribut sur clic
Ne vous découragez pas si vous n’avez pas de réponse c’est peut-être un peu loin de nos expériences ou dans une période où les uns et les autres ne disposent peut-on pas de temps. et merci de nous faire partager votre cheminement.
En espérant que vous trouverez.
Je ne suis pas sûr d’avoir compris. Vous voulez utiliser les coordonnées cliquées pour les enregistrer dans votre couche d’entités ? Avez-vous essayé
Code:
pointParc.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(point.x(),point.y())))
Hors ligne
#7 Tue 01 April 2025 08:42
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Merci de votre réponse. J'avance tout doucement et ce n'est pas en me mâchant tout le travail que je vais comprendre.
en fait je souhaite réutiliser les coordonnées cliquées pour afficher la valeur du champ id de ma parcelle. Pour l'instant je n'y arrive qu'en mettant une coordonnées statique.
Je cherche une fonction qui me permettrait de remplacer les coordonnées fixes dans mon code par une fonction. Peut-être aspoint ?
Hors ligne
#8 Tue 01 April 2025 11:46
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Je suis arrivé en utilisant dans la console
Code:
print(pointParc.geometry().asPoint())
à afficher les coordonnées, mais je n'arrive pas à l'écrire dans un QLineEdit d'e ma boite de dialogue ?
Merci de votre aide
Hors ligne
#9 Fri 04 April 2025 09:28
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Je pense que je me rapproche de la solution (avec de nombreuses approximations de codage, mais je ne vois pas comment rendre lisible mes coordonnées, j'ai une erreur "AttributeError: 'QgsPointXY' object has no attribute 'setGeometry"
Code:
class CoordClick: """QGIS Plugin Implementation.""" def display_point(self, point, button): # Affiche les coordonnées du clic #Instances recherche id parcelle projet = QgsProject.instance() coucheParcelles = projet.mapLayersByName("parcelles moyenmoutier")[0] entites = coucheParcelles.getFeatures() self.dlg.hide() # cache la boite de dialogue coords = "{}, {}".format(point.x(), point.y()) ## formatage des coordonnées pc = QgsGeometry.fromPointXY(QgsPointXY(point.x(), point.y())) point.setGeometry(pc) # Affichage point et numéro parcelle correpondante self.dlg.coordClick.setText(coords) # affichage des coordonnées dans la boite de dialogue print(coords) #Recherche id parcelle correspondant aux coordonnées for e in entites: if point.geometry().within(e.geometry()): print(e.attributes()[1]) # affiche l'attribut id self.dlg.show() # affiche de nouveau la boite de dialogue
Pourtant si je remplace par une coordonnée statique cela fonctionne :
Code:
point.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6.9509046,48.3815098)))
Dernière modification par Marcopololo (Fri 04 April 2025 09:32)
Hors ligne
#10 Fri 04 April 2025 10:27
- Gabi63
- Juste Inscrit !
- Date d'inscription: 3 Apr 2016
- Messages: 9
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Je ne suis pas sur de comprendre ce que vous voulez.
De ce que je comprends vous voulez :
- Cliquer sur une géométrie de la couche active dans le canvas ;
- Que le champ id de la géométrie s'affiche dans un bandeau ou dans une fenêtre pop-up ?
Ou vous voulez éditer un champ de manière interactive lorsque vous cliquez sur une entité ?
Cordialement.
Hors ligne
#11 Fri 04 April 2025 11:32
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Lorsque je clique sur une zone géométrique je souhaite récupérer le champ id associé à ma couche active et l'afficher dans ma boite de dialogue où j'ai déjà affiché mes coordonnées.
Marcopololo
Hors ligne
#12 Sun 06 April 2025 12:19
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
J'avance petit à petit. A riori je prend bien en compte les coordonnées cliquées pour rechercher mon id de parcelle mais ce n'est pas la bonne valeur du champ qui sort. Quelle que soit le point cliqué, le point s'affiche toujours au même endroit et l'id est celui du point et non pas des coordonnées ?
si quelqu'un a une idée.
Merci
Marcopololo
Code:
def display_point(self, point, button): # Affiche les coordonnées du clic #Instances recherche id parcelle projet = QgsProject.instance() coucheParcelles = projet.mapLayersByName("parcelles moyenmoutier")[0] entites = coucheParcelles.getFeatures() self.dlg.hide() # cache la boite de dialogue coords = "{}, {}".format(point.x(), point.y()) ## formatage des coordonnées print("coordo:",coords) pc = QgsGeometry.fromPointXY(QgsPointXY(point.x(), point.y())) pc2 = pc.asPoint() print("ptpc2",pc2) #point.setGeometry(pc) # Affichage point et numéro parcelle correpondante recup = self.dlg.coordClick.setText(coords) # affichage des coordonnées dans la boite de dialogue print("pc2 :",str(pc2)) self.dlg.coord2.setText(str(pc2)) # création point en mémoire layer = QgsVectorLayer('Point?crs=epsg:4326&field=id:integer', 'pointDemo', 'memory') pr = layer.dataProvider() point = QgsFeature() point.setGeometry(pc) #point.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6.952679,48.381057))) pr.addFeatures([point]) layer.updateExtents() QgsProject.instance().addMapLayers([layer]) for e in entites: if point.geometry().within(e.geometry()): print(e.attributes()[1]) self.dlg.numParc.setText(e.attributes()[1]) self.dlg.show() # affiche de nouveau la boite de dialogue
Hors ligne
#13 Mon 07 April 2025 00:32
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Mon code fonctionne à peu près, mais il boucle deux fois au lieu d'une et je n'arrive pas à en trouver l'origine...
Merci de votre aide
Code:
# -*- coding: utf-8 -*- """ /*************************************************************************** CoordClick A QGIS plugin Affichage coordonnées sur click souris Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ ------------------- begin : 2025-03-31 git sha : $Format:%H$ copyright : (C) 2025 by Marc GROSJEAN email : marc.grosjean@wanadoo.fr ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ """ from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtWidgets import QAction from qgis.gui import QgsMapToolEmitPoint from qgis.core import ( QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsPointXY, )#imports pour partie programme recherche parcelle # Initialize Qt resources from file resources.py from .resources import * # Import the code for the dialog from .coord_click_dialog import CoordClickDialog import os.path class CoordClick: """QGIS Plugin Implementation.""" def display_point(self, point, button): # Affiche les coordonnées du clic #Instances recherche id parcelle projet = QgsProject.instance() coucheParcelles = projet.mapLayersByName("parcelles moyenmoutier")[0] entites = coucheParcelles.getFeatures() self.dlg.hide() # cache la boite de dialogue coords = "{}, {}".format(point.x(), point.y()) ## formatage des coordonnées print("coordo:",coords) pc = QgsGeometry.fromPointXY(QgsPointXY(point.x(), point.y())) pc2 = pc.asPoint() # Affichage point et numéro parcelle correpondante # création point en mémoire layer = QgsVectorLayer('Point?crs=epsg:4326&field=id:integer', 'pointDemo', 'memory') pr = layer.dataProvider() point = QgsFeature() point.setGeometry(pc) #point.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6.952679,48.381057))) pr.addFeatures([point]) #layer.updateExtents() # Création couche pointDemo #QgsProject.instance().addMapLayers([layer]) for e in entites: if point.geometry().within(e.geometry()): print(e.attributes()[1]) print(e.attributes()[4],e.attributes()[5]) self.dlg.coordClick.setText(coords) # affichage des coordonnées dans la boite de dialogue self.dlg.numParc.setText(e.attributes()[1]) self.dlg.coord2.setText((e.attributes()[4]) + (e.attributes()[5])) self.dlg.show() # affiche de nouveau la boite de dialogue def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) ## Récupération du canvas courant self.canvas = self.iface.mapCanvas() ## Création d'un outil émettant un point au clic self.point_tool = QgsMapToolEmitPoint(self.canvas) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'CoordClick_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Coordonnées sur click') # Check if plugin was started the first time in current QGIS session # Must be set in initGui() to survive plugin reloads self.first_start = None # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('CoordClick', message) # Création de la boite de dialogue (après les traductions) self.dlg = CoordClickDialog() def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/coord_click/icon.png' self.add_action( icon_path, text=self.tr(u'Infos parcelle et coordonnées'), callback=self.run, parent=self.iface.mainWindow()) # will be set False in run() self.first_start = True # connecte le signal que le canvas a été cliqué self.point_tool.canvasClicked.connect(self.display_point) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Coordonnées sur click'), action) self.iface.removeToolBarIcon(action) def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False #création boite de dialogue self.dlg = CoordClickDialog() # connecte le signal que le canvas a été cliqué self.point_tool.canvasClicked.connect(self.display_point) # Défini coorclick comme étant l'outil de carte actif self.canvas.setMapTool(self.point_tool) # show the dialog # self.dlg.show() # Run the dialog event loop #result = self.dlg.exec_() # See if OK was pressed #if result: # Do something useful here - delete the line containing pass and # substitute with your code. #pass
Hors ligne
#14 Mon 07 April 2025 09:35
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Vous connectez 2 fois votre signal canvasClicked. Une fois dans la méthode initGui et une fois dans méthode run au premier lancement.
C'est pour cela que votre slot (display_point) s'éxécute 2 fois.
Vous devriez sans doute retirer la ligne
Code:
self.point_tool.canvasClicked.connect(self.display_point)
de la méthode initGui et ne conserver que celle qui est dans run. En effet, il me semble plus logique que votre outil s'exécute si l'utilisateur active votre plugin (clique sur le bouton) plutôt que dés qu'il le charge... (mais peut être que je me trompe, à vous de voir).
Vous devriez également prévoir de déconnecter votre signal dans la méthode unload sinon vous risquez d'avoir des comportements étonnants lorsque vous désactiverez votre plugin .
Hors ligne
#15 Mon 07 April 2025 09:39
- Gabi63
- Juste Inscrit !
- Date d'inscription: 3 Apr 2016
- Messages: 9
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Tant mieux si vous arrivez à vos fins.
Je ne peux pas reproduire le code chez moi, il me manque l'import CoordClickDialog. Je ne peux donc pas reproduire vos problèmes.
Néanmoins, il me semble que votre code tourne deux fois car vous connectez deux signaux différents à votre méthode display_point : ligne 233 et ligne 256 (appelé dans la déclaration de add_action l. 224).
Quelques suggestions qui, j'espère, vous serons utiles :
Pour récupérer les attributs, si la couche est active vous pouvez récupérer directement l'entité sélectionné, le code suivant est écrit de mémoire, je n'ai pas QGIS pour tester le fonctionnement :
Code:
def show_attr(): """ """ feature = layer.selectedFeatures() if bool(feature): feature = feature[0] # Introduire self.dlg sinon, le code suivant affichera un bandeau en haut du canvas qui ne disparaîtra pas (duration=0) msg_level = Qgis.MessageLevel(Qgis.Info) iface.messageBar().pushMessage(title="Displaying attributes", text=f"{feature['attr1']}, {feature['attr2']}", level=msg_level, duration=0) global layer # A éviter si le script est exécuté dans un projet plus important layer = QgsProject.instance().mapLayersByName(name)[0] layer.selectionChanged.connect(show_attr)
Si la couche n'est pas active je vous suggère d'utiliser des requêtes lors du getFeatures() pour accélérer le code en cas de couche avec un nombre important d'entité :
- QgsFeatureRequest.setFilterRect(pc.boundingBox()) : récupérera toutes les entités intersectant la boundingBox de votre point.
- QgsFeatureRequest.setDistaneWithin(pc, 20) : récupérera toutes les entités dans une distance de 20 mètres de votre point.
Les requêtes sont à déclarer en amont puis à appeler dans le get de la manière suivante :
Code:
request = QgsFeatureRequest.setFilterRect(point.boundingBox()) entites = coucheParcelles.getFeatures(request)
Bon courage.
Dernière modification par Gabi63 (Mon 07 April 2025 09:41)
Hors ligne
#16 Mon 07 April 2025 12:13
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Merci beaucoup de votre aide.
Effectivement il y a plus de 7000 entités dans une couche donc le code est long (plus de 5s).
Donc si je comprend bien je créé une requète qui va gérer le for in en amont ?
Et concernant le code def show, dois je le glisser dans la def display_point ou alors avant ?
Encore merci
Marcopololo
Hors ligne
#17 Mon 07 April 2025 13:56
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
Bonjour,
Voici une version de votre fichier avec quelques améliorations:
- deconnection du signal dans le unload
- une seule connection au signal dans le run
- simplification de display_point
- ajout d'une requete pour filtrer les entités renvoyées par getFeatures
- suppression de quelques lignes inutiles
- récupération des valeurs d'attributs par le nom de l'attribut plutôt que par son index (à vous de modifier les lignes 218 et 219 en fonction de vos vrais nom d'attributs)
Code:
# -*- coding: utf-8 -*- """ /*************************************************************************** CoordClick A QGIS plugin Affichage coordonnées sur click souris Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ ------------------- begin : 2025-03-31 git sha : $Format:%H$ copyright : (C) 2025 by Marc GROSJEAN email : marc.grosjean@wanadoo.fr ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ """ from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtWidgets import QAction from qgis.gui import QgsMapToolEmitPoint from qgis.core import ( QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsPointXY, QgsFeatureRequest, )#imports pour partie programme recherche parcelle # Initialize Qt resources from file resources.py from .resources import * # Import the code for the dialog from .coord_click_dialog import CoordClickDialog import os.path class CoordClick: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) ## Récupération du canvas courant self.canvas = self.iface.mapCanvas() ## Création d'un outil émettant un point au clic self.point_tool = QgsMapToolEmitPoint(self.canvas) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'CoordClick_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Coordonnées sur click') # Check if plugin was started the first time in current QGIS session # Must be set in initGui() to survive plugin reloads self.first_start = None # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('CoordClick', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/coord_click/icon.png' self.add_action( icon_path, text=self.tr(u'Infos parcelle et coordonnées'), callback=self.run, parent=self.iface.mainWindow()) # will be set False in run() self.first_start = True def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Coordonnées sur click'), action) self.iface.removeToolBarIcon(action) self.point_tool.canvasClicked.disconnect(self.display_point) def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False #création boite de dialogue self.dlg = CoordClickDialog() # connecte le signal que le canvas a été cliqué self.point_tool.canvasClicked.connect(self.display_point) # Défini coorclick comme étant l'outil de carte actif self.canvas.setMapTool(self.point_tool) def display_point(self, point, button): """Affiche les coordonnées du clic""" self.dlg.hide() # cache la boite de dialogue couche_parcelles = QgsProject.instance().mapLayersByName("parcelles moyenmoutier")[0] req = QgsFeatureRequest.setFilterRect(QgsGeometry.fromPointXY(point).boundingBox()) entites = couche_parcelles.getFeatures(req) for e in entites: self.dlg.coordClick.setText(f"{point.x()}, {point.y()}") # affichage des coordonnées dans la boite de dialogue self.dlg.numParc.setText(e['nom_de_attribut_1']) self.dlg.coord2.setText(e['nom_de_attribut_4'] + e['nom_de_attribut_5']) self.dlg.show() # affiche de nouveau la boite de dialogue
Dernière modification par YoLecomte (Mon 07 April 2025 14:36)
Hors ligne
#18 Mon 07 April 2025 14:26
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Merci beaucoup de votre aide, je vais pouvoir comparer et comprendre certaines subtilités.
Par contre j'ai l'erreur suivante : AttributeError: 'QgsPointXY' object has no attribute 'boundingBox'
Je suis en train de chervcher mais il semble que l'attribut point ne soit pas déclaré. Je vais essayé de trouver le manque
Hors ligne
#19 Mon 07 April 2025 14:38
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
Oui, en effet, Désolé.
Est ce que vous pourriez fournir l'ensemble de votre plugin afin de pouvoir tester? Sinon, nous sommes obligés d'appliquer nos propositions sans pouvoir vérifier ce genre de subtilités...
J'ai corrigé dans mon message précédent (ligne 214).
Hors ligne
#20 Mon 07 April 2025 15:04
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Votre mail ne passe pas, j'ai essayé de vous envoyé le fichier compressé.
a priori toujours une erreur : QgsFeatureRequest.setFilterRect(): first argument of unbound method must have type 'QgsFeatureRequest'
Es ce que la requète est censé chercher les infos de la geometry de la zone cliquée ou récupérer les attributs de la zone cliquée
Dernière modification par Marcopololo (Mon 07 April 2025 15:47)
Hors ligne
#21 Mon 07 April 2025 15:29
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
ah oui... remplacer la ligne 214 par:
Code:
req = QgsFeatureRequest().setFilterRect(QgsGeometry.fromPointXY(point).boundingBox())
Ne m'envoyez pas votre plugin par mail. Je n'ai pas vocation a faire du support privé (à moins que vous ne souhaitiez me rémunérer).
Vous pouvez joindre votre zip à un message afin que d'autre utilisateurs puissent également vous aider.
Hors ligne
#22 Mon 07 April 2025 15:57
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
Ok merci.
je viens de tester, pour moi ca semble fonctionnel.
J'ai refais quelques modifications mineures:
voici le code auquel j'aboutis:
Code:
# -*- coding: utf-8 -*- """ /*************************************************************************** CoordClick A QGIS plugin Affichage coordonnées sur click souris Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ ------------------- begin : 2025-03-31 git sha : $Format:%H$ copyright : (C) 2025 by Marc GROSJEAN email : marc.grosjean@wanadoo.fr ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ """ from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtWidgets import QAction from qgis.gui import QgsMapToolEmitPoint from qgis.core import ( QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsPointXY, QgsFeatureRequest, ) # imports pour partie programme recherche parcelle # Initialize Qt resources from file resources.py from .resources import * # Import the code for the dialog from .coord_click_dialog import CoordClickDialog import os.path class CoordClick: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) ## Récupération du canvas courant self.canvas = self.iface.mapCanvas() ## Création d'un outil émettant un point au clic self.point_tool = QgsMapToolEmitPoint(self.canvas) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'CoordClick_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Coordonnées sur click') # Check if plugin was started the first time in current QGIS session # Must be set in initGui() to survive plugin reloads self.first_start = None # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('CoordClick', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/coord_click/icon.png' self.add_action( icon_path, text=self.tr(u'Infos parcelle et coordonnées'), callback=self.run, parent=self.iface.mainWindow()) # will be set False in run() self.first_start = True def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Coordonnées sur click'), action) self.iface.removeToolBarIcon(action) try: self.point_tool.canvasClicked.disconnect(self.display_point) except: pass def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False # création boite de dialogue self.dlg = CoordClickDialog() # connecte le signal que le canvas a été cliqué self.point_tool.canvasClicked.connect(self.display_point) # Défini coorclick comme étant l'outil de carte actif self.canvas.setMapTool(self.point_tool) def display_point(self, point, button): """Affiche les coordonnées du clic""" self.dlg.hide() # cache la boite de dialogue couche_parcelles = QgsProject.instance().mapLayersByName("parcelles moyenmoutier")[0] req = QgsFeatureRequest().setFilterRect(QgsGeometry.fromPointXY(QgsPointXY(point.x(), point.y())).boundingBox()) entites = couche_parcelles.getFeatures(req) for e in entites: self.dlg.coordClick.setText( f"{point.x()}, {point.y()}") # affichage des coordonnées dans la boite de dialogue self.dlg.numParc.setText(e['id']) self.dlg.coord2.setText(e['section'] + e['numero']) self.dlg.show() # affiche de nouveau la boite de dialogue
Hors ligne
#23 Mon 07 April 2025 17:20
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
C'est tout bon. Maintenant il me reste à l'étudier et mieux comprendre Python.
Hors ligne
#24 Tue 08 April 2025 08:52
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
Parfait.
Si des éléments vous semblent obscurs n'hésitez pas
Hors ligne
#25 Tue 08 April 2025 10:56
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
OK, j'aurai surement de nouvelles questions. Je vais maintenant regarder pour créer un menu puisque ce petit plugin va faire parti d'un ensemble. Un plugin ouvrant un autre plugin...ou alors une fenêtre qui ouvre une autre fenêtre mais à priori assez compliqué à traiter comme un seul plugin.
Marcopololo
Hors ligne
#26 Tue 08 April 2025 12:11
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Alors j'ai une petite question. Si dans la continuité de ce plugin je souhaite par exemple ajouter une liste des essences d'arbres qu'il y a dans la parcelle tout en précisant si elle est vide du type "aucune essence saisie" faut il créer une nouvelle fonction def pour la lisibilité ou la laisser dans la fonction display point ? Il y aura plusieurs ligne à mettre en œuvre sous forme array donc un plus plus de code.
Merci
Marcopololo
Hors ligne
#27 Tue 08 April 2025 12:42
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 275
Re: QGIS: programme python affichage champ attribut sur clic
Votre question est très vague. La réponse courte est que les deux approches sont possibles sans soucis.
Maintenant, en programmation informatique il y a des bonnes pratiques qu'il est intéressant de respecter. En général, on essaye de coder de la manière la plus simple et lisible possible. Cela passe par:
- donner un nom explicite aux fonctions, variables, objets...
- éviter les pavés de codes qui s'occupent de faire beaucoup de choses
- découper le programme en briques réutilisables
- commenter les parties de code qui ne peuvent pas être explicitement décrites par le nommage des objets
Pour votre cas spécifique des essences d'arbres, vous pouvez ajouter un widget dans votre interface grâce à Qt designer puis dans la fonction qui alimente cette interface en données à afficher (aujourd'hui c'est votre fonction display_point), remplir ce widget.
Le choix du widget dépend de la façon dont vous voulez afficher cette liste.
Il y a des centaines de plugins pour QGIS dont le code est accessible. Vous pouvez vous en inspirer librement pour mettre en place les mécanismes dont vous avez besoin. A partir du moment où vous aurez compris la logique de fonctionnement de ces programmes, vous pourrez faire à peu près tout ce que voudrez en terme de fonctionnalités.
Si vous rencontrez une problématique spécifique du parcours de développement de votre outil, je vous invite à ouvrir un sujet traitant de cette problématique en particulier. Le topic actuel n'a pas vocation a devenir un espace d'échanges sur des problématiques générales de développement informatique.
PS: Je vois que vous êtes vosgien. Si vous passez par Epinal à l'occasion, n'hésitez à m'envoyer un message en privé pour convenir d'une éventuelle rencontre. Je suis toujours content de faire connaissance avec des collègues géomaticien
Hors ligne
#28 Tue 08 April 2025 14:16
- Marcopololo
- Participant actif
- Lieu: Etival Clairefontaine
- Date d'inscription: 23 Nov 2021
- Messages: 87
Re: QGIS: programme python affichage champ attribut sur clic
Se sera avec plaisir. Je suis d'Etival clairefontaine, pays du papier et du bois...
Hors ligne