#1 Thu 27 March 2025 23:08
- Marcopololo
- Participant actif
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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
- Date d'inscription: 23 Nov 2021
- Messages: 72
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 Hier 12:19
- Marcopololo
- Participant actif
- Date d'inscription: 23 Nov 2021
- Messages: 72
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 Aujourd'hui 00:32
- Marcopololo
- Participant actif
- Date d'inscription: 23 Nov 2021
- Messages: 72
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 Aujourd'hui 09:35
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 268
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 Aujourd'hui 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 (Aujourd'hui 09:41)
Hors ligne