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

PyQt Python Discussion :

PyQt - Afficher html - Anchor et link


Sujet :

PyQt Python

  1. #1
    Nouveau membre du Club
    Profil pro
    DDD
    Inscrit en
    Février 2003
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DDD

    Informations forums :
    Inscription : Février 2003
    Messages : 55
    Points : 38
    Points
    38
    Par défaut PyQt - Afficher html - Anchor et link
    Avec Python3 et PyQt5.10.

    Bonjour à Tous,

    Dans le code ci dessous, je voudrais ouvrir une page html et pointer directement vers l'ancre voulue, puis pouvoir cliquer sur un lien contenu dans la page qui ouvre un fichier texte

    METHOD1: J'arrive à ouvrir la page html, puis à suivre le lien vers le fichier texte qui s'ouvre correctement et remplace la page html. Par contre la page html ne scrool pas vers l'ancre voulue, le code javascript ne fait rien.
    METHOD2: Je ne parvient pas à cliquer sur un lien, si la page en contient. Je n'ai pas trouver comment rendre un lien cliquable (et que la nouvelle page s'ouvre en remplacement de l'ancienne).
    METHOD3: Lorsque le lien pointe vers un fichier texte, celui s'ouvre mais les sauts de ligne ne sont pas interprétés (alors que dans la METHOD1, il n'y a pas ces problèmes d'interprétation).

    Si vous avez des idées pour ces pbs, je suis preneur.
    Merci d'avance.

    Olivier

    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
     
    class Aide(QtGui.QWidget):
        def __init__(self, nomFicAide, param=None, parent=None):
            super(Aide, self).__init__(parent)
     
            self.setWindowTitle(u"Help")
            self.resize(800, 600)
     
            # Give it a layout
            self.layout = QtGui.QVBoxLayout(self)
            self.layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(self.layout)
     
            # METHOD 1
            # Create and fill QWebEngineView
            self.view = QWebEngineView()
            self.view.load(QtCore.QUrl.fromLocalFile(nomFicAide))
            #TODO: jump to anchor
            print("location.hash = '#" + param + "';")
            self.view.page().runJavaScript("location.hash = '#" + param + "';")
     
    #        # METHOD 2
    #        # Create and fill QTextEdit
    #        self.view = QtGui.QTextEdit()
    ##        self.view.setReadOnly(True)
    #        self.view.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
    #
    #        _f = QtCore.QFile(nomFicAide)
    #        _f.open(QtCore.QFile.ReadOnly|QtCore.QFile.Text)
    #        _istream = QtCore.QTextStream(_f)
    #        self.view.setHtml(_istream.readAll())
    #        try: 
    #            self.view.scrollToAnchor(param)
    #        except:
    #            pass
    #        _f.close()
     
    #        # METHOD 3
    #        # Create and fill QTextBrowser
    #        self.view = QtGui.QTextBrowser()
    #        _f = QtCore.QFile(nomFicAide)
    #        _f.open(QtCore.QFile.ReadOnly|QtCore.QFile.Text)
    #        _istream = QtCore.QTextStream(_f)
    #        self.view.setHtml(_istream.readAll())
    #        try: 
    #            self.view.scrollToAnchor(param)
    #        except:
    #            pass
    #        _f.close()
     
     
     
            # Add the QWebView to the layout
            self.layout.addWidget(self.view)

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    C'est dommage: ton code est trop incomplet pour qu'on puisse l'essayer. Donc, si on n'y voit pas d'erreur grossière, on ne répond pas...

    Par ailleurs, tu ne travailles pas avec les dernières versions de PyQt5 puisque tu utilises encore QtGui pour QWidget, et je ne sais pas si le code que je te propose sera compatible chez toi. Il y aura peut-être à remplacer au moins "QtWidgets" par "QtGui".

    Tu verras si tu peux l'adapter. Voilà un code qui marche chez moi. J'affiche un fichier html qui s'appelle "aide.html", qui contient une ancre "#partiecommune":

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 3.5, PyQt5 v5.9.2
     
    import sys
    import os
    from PyQt5 import QtWidgets, QtCore, QtWebEngineWidgets
     
    #############################################################################
    class Aide(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
            self.setWindowTitle("Aide")
            self.resize(800, 600)
     
            self.view = QtWebEngineWidgets.QWebEngineView()
     
            layout = QtWidgets.QGridLayout(self)
            layout.addWidget(self.view, 0, 0)
            layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(layout)
     
            self.page = QtWebEngineWidgets.QWebEnginePage()
     
        #========================================================================
        def affiche(self, fichierweb):
            """affiche le fichier web donné
            """
            self.page.setUrl(QtCore.QUrl(fichierweb))
            self.view.setPage(self.page)
            self.view.show()
     
    #############################################################################
    if __name__ == '__main__':
     
        app = QtWidgets.QApplication(sys.argv)
     
        aide = Aide()
        aide.show()
     
        fichierweb = "file:///" + os.path.abspath("aide.html").replace("\\", "/") + "#partiecommune"
     
        aide.affiche(fichierweb)
     
        sys.exit(app.exec_())
    Avec ce code, la page demandée est affichée, avec la ligne contenant l'ancre en 1ère ligne d'affichage en haut de la fenêtre.

    Si je clique sur un lien avec une autre ancre, la page s'affiche de nouveau avec cette même ancre en haut de la fenêtre.

    Si je clique sur un lien externe du web, la page du web correspondante s'affiche.

    En ce qui concerne ce code, je n'ai pas réussi à utiliser "QUrl.fromLocalFile" avec une ancre, et c'est pour ça que j'ai construit directement l'adresse locale du fichier avec "file:///". Mais il faut aussi remplacer les '\' par '/' sous Windows.

    De ce fait, ce code permet d'afficher sans modification n'importe quelle page du web! Par exemple, essaie cette adresse:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fichierweb = "https://www.youtube.com/tv#/watch?v=bLhi6lppatw"
    Et tu auras la vidéo de "Stay" de Rihanna en plein écran dans la fenêtre. Mon seul regret est qu'il y a beaucoup trop d'eau dans cette baignoire...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Nouveau membre du Club
    Profil pro
    DDD
    Inscrit en
    Février 2003
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DDD

    Informations forums :
    Inscription : Février 2003
    Messages : 55
    Points : 38
    Points
    38
    Par défaut
    Bonsoir tyrtamos,

    Merci pour ta réponse. Je n'avais pas pensé à cette 4ème méthode, si simple, qu'est de faire passer directement dans l'url la position voulue.
    Cela solutionne mon problème.

    Pour le fun, si tu as, ou quelqu'un d'autre les raisons du non fonctionnement des autres méthodes, je suis preneur.

    Le mélange QtGui / QtWidgets (qui semble encore permis en Qt5.10) ne posait pas problème, néanmoins, ton code est plus propre et j'ai donc modifié mon code en conséquence.

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    J'ai essayé la "méthode 1" parce que je n'avais jamais exécuté de javascript comme ça, et j'ai réussi:

    La chose importante pour que ça marche est d'attendre que la page soit complètement chargée! Pour ça, on utilise le signal "loadFinished"

    Voilà un code d'essai:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 3
     
    import sys
    import os
    from PyQt5 import QtWidgets, QtCore, QtWebEngineWidgets
     
    #############################################################################
    class Aide(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, nomFicAide, param=None, parent=None):
            super().__init__(parent)
     
            self.setWindowTitle("Help")
            self.resize(800, 600)
     
            self.param = param
     
            self.view = QtWebEngineWidgets.QWebEngineView()
     
            self.layout = QtWidgets.QGridLayout(self)
            self.layout.addWidget(self.view)
            self.layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(self.layout)
     
            # METHOD 1
            self.view.load(QtCore.QUrl.fromLocalFile(nomFicAide))
            self.view.page().loadFinished.connect(self.finChargementPage)
     
        #========================================================================
        def finChargementPage(self, ok=False):
            """lancé après le chargement de la page (ok=True si pas d'erreur).
            """
            if ok:
                script = """
                window.location.hash = "{}"
                """.format(self.param)
                self.view.page().runJavaScript(script)
                self.view.show()
     
    #############################################################################
    if __name__ == '__main__':
     
        app = QtWidgets.QApplication(sys.argv)
     
        fichier = os.path.abspath("aide.html").replace("\\", "/")
        param = "partiecommune"
     
        aide = Aide(fichier, param)
        aide.show()
     
        sys.exit(app.exec_())
    Toujours avec mon fichier "aide.html" et l'une de ses ancres "partiecommune". A noter qu'il n'est pas nécessaire d'ajouter le '#' avant.

    Avec ce code, la ligne de l'ancre en question s'affiche en haut de la fenêtre comme demandé.

    Je regarde si je peux faire quelque chose avec tes autres méthodes...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Les méthodes 2 et 3 utilisent scrollToAnchor qui n'existent malheureusement que dans QTextEdit, et non dans QWebEngine.

    Or, QTextEdit, comme QTextBrowser qui en hérite, ne supporte pas le html complet, mais seulement un sous-ensemble appelé "RichText". Comme aucun éditeur html ne prend en compte le RichText, cela nécessite beaucoup d'opérations à la main pour écrire un texte html compatible. J'ai déjà fait ça, et je n'ai pas trouvé ça très amusant...

    J'utilise couramment l'affichage du html pour les fichiers d'aide de mes programmes. Et ces fichiers d'aide sont tout simplement créés et mis à jour avec un éditeur html comme BlueGriffon (gratuit): c'est très rapide et ça marche très bien, mais il s'agit d'un html complet, qui ne s'affiche pas bien dans un QTextEdit.

    Je n'ai pas poursuivi ma recherche avec QTextEdit ou QTextBrowser, mais il n'y a pas de raison que scrollToAnchor ne marche pas.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Pour la solution javascript (méthode 1), il y a une autre solution qui évite de créer la méthode "finChargementPage": il s'agit d'utiliser la classe QWebEngineScript, et de préciser le moment d'injection du script par la constante "QWebEngineScript.Deferred".

    Voilà le code:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 3
     
    import sys
    import os
    from PyQt5 import QtWidgets, QtCore, QtWebEngineWidgets
     
    #############################################################################
    class Aide(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, nomFicAide, param=None, parent=None):
            super().__init__(parent)
     
            self.setWindowTitle("Help")
            self.resize(800, 600)
     
            self.view = QtWebEngineWidgets.QWebEngineView()
     
            self.layout = QtWidgets.QGridLayout(self)
            self.layout.addWidget(self.view)
            self.layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(self.layout)
     
            # METHOD 1
            # charge la page
            self.view.load(QtCore.QUrl.fromLocalFile(nomFicAide))
     
            # crée un QWebEngineScript pour porter le script js
            qscript = QtWebEngineWidgets.QWebEngineScript()
            # fait que le script ne sera injecté qu'à la fin du chargement de la page
            qscript.setInjectionPoint(QtWebEngineWidgets.QWebEngineScript.Deferred)
            # code source du script js
            scriptjs = """
            window.location.hash = "{}"
            """.format(param)
            # charge le code source du script
            qscript.setSourceCode(scriptjs)
     
            # exécute le script js à la fin du chargement de la page
            self.view.page().profile().scripts().insert(qscript)
            self.view.show()
     
    #############################################################################
    if __name__ == '__main__':
     
        app = QtWidgets.QApplication(sys.argv)
     
        fichier = os.path.abspath("aide.html").replace("\\", "/")
        param = "partiecommune"
     
        aide = Aide(fichier, param)
        aide.show()
     
        sys.exit(app.exec_())
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  7. #7
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Pour le fun, avec mon 1er code, on peut facilement afficher un fichier pdf, en utilisant la même méthode que Firefox:

    Il faut d'abord télécharger "pdfjs" ici: https://mozilla.github.io/pdf.js/, le mettre quelque part sur le disque dur et le dézipper. On va utiliser le fichier web/viewer.html avec son chemin.

    Soit le fichier test.pdf à afficher. Voilà le code pour appeler l'affichage (le "replace" est nécessaire sous Windows):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        pdfjs = "file:///" + r'chemin_vers\web\viewer.html'.replace("\\", "/")
        fichierpdf = "file:///" + os.path.abspath("test.pdf").replace("\\", "/")
        fichierweb = '{}?file={}'.format(pdfjs, fichierpdf)
    Une fois qu'on a "fichierweb", on appelle aide.affiche(fichierweb) comme je l'ai fait dans mon 1er code ci-dessus (message 2 => https://www.developpez.net/forums/d1.../#post10022108).

    On peut même demander l'affichage du pdf à partir d'une page en particulier en terminant le chemin par "#page=5" pour avoir la page 5.

    Mais je ne sais pas afficher comme ça un fichier pdf situé sur le web. Peut-être faut-il d'abord le télécharger dans un répertoire temporaire?
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

Discussions similaires

  1. [SP-2013] Comment n'afficher que certains promoted links d'une liste
    Par yayalarafale dans le forum SharePoint
    Réponses: 6
    Dernier message: 13/09/2017, 15h29
  2. Besoin de conseils et d'aide pour affiche html
    Par Linux44 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 12
    Dernier message: 17/07/2012, 19h35
  3. Condition php pour afficher html
    Par granchef dans le forum Langage
    Réponses: 4
    Dernier message: 15/04/2010, 17h28
  4. Afficher HTML ou word dans une form
    Par rudbyman52 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 02/10/2007, 01h27
  5. [struts][]taglib bean] afficher html avec write
    Par mlequim dans le forum Struts 1
    Réponses: 6
    Dernier message: 04/11/2005, 18h44

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