1
votes

PyQt5 - Pourquoi mes widgets ne se mettent-ils pas à jour à moins que je ne passe à une fenêtre différente?

J'ai donc commencé à travailler avec PyQt5. Pour le moment, je n'ai programmé qu'un seul bouton qui est censé prendre le texte d'une modification de ligne, le stocker dans une variable globale et le mettre dans un navigateur de texte. Maintenant, il le fait ... mais avec des problèmes. Le navigateur de texte ne se met PAS à jour tant que je ne clique pas sur un autre programme / fenêtre, puis que je clique à nouveau sur mon application Lorsque l'édition de ligne est effacée, il y a un bogue qui est essentiellement du texte qui n'est pas effacé correctement mais seulement la moitié supérieure. Cela disparaît lorsque je tape à nouveau.

J'ai essayé d'appeler les méthodes .update () pour les widgets et QApplication.process_events ()

Voici le code

from PyQt5 import QtCore, QtGui, QtWidgets

lyrics = ''
adlib = ' (Placeholder adlib)'

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(742, 680)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.addLineBtn = QtWidgets.QPushButton(self.centralwidget)
        self.addLineBtn.setGeometry(QtCore.QRect(530, 0, 91, 51))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setItalic(True)
        self.addLineBtn.setFont(font)
        self.addLineBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.addLineBtn.setObjectName("addLineBtn")
        self.deleteBtn = QtWidgets.QPushButton(self.centralwidget)
        self.deleteBtn.setGeometry(QtCore.QRect(120, 80, 91, 32))
        self.deleteBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.deleteBtn.setObjectName("deleteBtn")
        self.saveBtn = QtWidgets.QPushButton(self.centralwidget)
        self.saveBtn.setGeometry(QtCore.QRect(30, 80, 91, 32))
        self.saveBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.saveBtn.setObjectName("saveBtn")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(30, 20, 501, 51))
        self.lineEdit.setObjectName("lineEdit")
        self.dialLabel = QtWidgets.QLabel(self.centralwidget)
        self.dialLabel.setGeometry(QtCore.QRect(640, 20, 71, 16))
        self.dialLabel.setObjectName("dialLabel")
        self.rtdSlider = QtWidgets.QSlider(self.centralwidget)
        self.rtdSlider.setGeometry(QtCore.QRect(620, 40, 101, 22))
        self.rtdSlider.setOrientation(QtCore.Qt.Horizontal)
        self.rtdSlider.setObjectName("rtdSlider")
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect(20, 120, 701, 501))
        self.textBrowser.setObjectName("textBrowser")
        self.noadlibBtn = QtWidgets.QPushButton(self.centralwidget)
        self.noadlibBtn.setGeometry(QtCore.QRect(530, 50, 91, 51))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setItalic(True)
        self.noadlibBtn.setFont(font)
        self.noadlibBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.noadlibBtn.setObjectName("noadlibBtn")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 742, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.addLineBtn.clicked.connect(self.addLineAdlib)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.addLineBtn.setText(_translate("MainWindow", "Adlib"))
        self.deleteBtn.setText(_translate("MainWindow", "Delete"))
        self.saveBtn.setText(_translate("MainWindow", "Save"))
        self.dialLabel.setText(_translate("MainWindow", "RTD Level"))
        self.noadlibBtn.setText(_translate("MainWindow", "No Adlib"))

    def addLineAdlib(self):
        global lyrics
        lyrics += self.lineEdit.text() + adlib + '\n'
        self.lineEdit.clear()
        self.textBrowser.setText(lyrics)
    def addLineNoAdlib(self):
        pass

    def save(self):
        pass

    def deleteLine(self):
        pass


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())


3 commentaires

D'accord, votre premier problème est que vous avez utilisé le concepteur au lieu de créer l'interface graphique à partir de zéro comme vous auriez dû et maintenant vous essayez de dépanner le code de déchets qu'il a craché - ce qui rend les choses 5 fois plus difficiles à résoudre. Je vais regarder cela et voir si je ne peux pas extraire le bogue. Mais peut-être que vous pourriez essayer de concevoir cela à partir de zéro plutôt que d'utiliser le concepteur qui pourrait non seulement corriger le bogue, mais vous donner une bien meilleure compréhension de la facilité à partir de zéro


@DennisJensen bien, a noté. Je suppose que je vais essayer de repenser cette chose à partir de zéro. Utilisera probablement le concepteur pour tracer la façon dont je veux que tout soit, puis copiez les coordonnées / dimensions des widgets et l'écrivez à partir de zéro. Croisons les doigts que cela résoudra le problème. Merci pour les commentaires


Travailler sur une réécriture structurée J'ai déjà fait plusieurs d'entre eux, donc cela ne devrait pas me prendre trop de temps, vous pouvez l'utiliser pour construire à partir de et comme modèle à partir de maintenant


4 Réponses :


0
votes


1. Le navigateur de texte ne se met PAS à jour tant que je n'ai pas cliqué sur un autre programme / fenêtre, puis à nouveau sur mon application - ce problème peut être lié à votre système d'exploitation. J'ai un comportement PyQT5 incorrect sur Ubuntu 16.04 tandis que sur Ubuntu 18.04, tout fonctionnait bien. Pouvez-vous partager plus d'informations?
Remarque: j'ai testé votre script sur Ubuntu 18.04, je n'ai pas eu besoin de cliquer sur un autre programme / fenêtre pour le rafraîchir

2. Lorsque l'édition de ligne est effacée, il y a un bogue qui est essentiellement du texte qui n'est pas effacé correctement, mais seulement la moitié supérieure. Cela disparaît lorsque je tape à nouveau. - Pouvez-vous expliquer ce que vous entendez par c'est la moitié supérieure ? Si vous vouliez dire qu'il y a encore du texte (Placeholder adlib) , vous devez modifier votre fonction pour vérifier la zone de texte lineEdit avant d'ajouter quelque chose à la variable lyrics. Par exemple, comme ceci:

def addLineAdlib(self):
        if self.lineEdit.text():
                global lyrics
                lyrics += self.lineEdit.text() + adlib + '\n'
                self.lineEdit.clear()
                self.textBrowser.setText(lyrics)


4 commentaires

1. J'ai un Mac avec Mac OS Mojave 10.14.1 pourrait être lié à cela. 2. Je veux dire que lorsque j'entre le texte dans l'édition de ligne et que je clique pour l'ajouter au reste, au lieu d'effacer complètement l'édition de ligne, je peux toujours voir des PARTIES de lettres comme le mot entier a été coupé en deux horizontalement. Donc, si je tapais «Salut», je verrais alors les 3 lignes verticales qui resteraient si vous coupiez le mot «Salut» en deux horizontalement. Difficile à expliquer mais j'espère que vous l'avez compris. C'est purement un bug visuel et je soupçonne que c'est lié au fait que ma fenêtre ne se met pas à jour correctement Modifier: voici ce que je veux dire imgur.com/ a / mb80hqh


Je vous comprends, pouvez-vous faire une capture d'écran de ce bug visuel?


Oui, déjà fait, vérifiez le commentaire auquel vous venez de répondre pour une modification.


Je pense que j'ai trouvé la réponse, essayez d'appeler la méthode .repaint () sur la zone de texte. Pour en savoir plus, cliquez ici - stackoverflow .com / questions / 56553257 /…



0
votes

Voici une version plus propre et plus classifiée (pyqt plus pythonique) de votre programme.J'ai laissé des commentaires pour que vous puissiez voir où cela aurait été mais j'ai supprimé votre système de coordonnées et l'ai remplacé par la mise en page plus standard style de création d'une interface graphique.

J'ai testé cela en utilisant python 3.7 pyqt5 sur win10 donc s'il y a un problème de système d'exploitation, vous le saurez mais je suppose (sans creuser dans ce désordre laid) est qu'il y a eu une déconnexion quelque part qui a créé le problème que vous rencontrez.

De plus, votre bouton tel que conçu ne créera jamais de ligne vide car il met toujours quelque chose sur une ligne - j'ai testé cela en cliquant simplement sur le bouton sans rien entrer

from sys import exit as sysExit

from PyQt5.QtCore import Qt
from PyQt5.QtGui  import QFont, QCursor
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QDockWidget, QStyleFactory
from PyQt5.QtWidgets import QPushButton, QLineEdit, QLabel, QSlider, QTextBrowser, QMenuBar, QStatusBar

class MenuToolBar(QDockWidget):
    def __init__(self, MainWin):
        QDockWidget.__init__(self)
        self.MainWin = MainWin
        self.MainMenu = MainWin.menuBar()

        # ******* Create the Help Menu *******
        self.HelpMenu  = self.MainMenu.addMenu('Help')

class CenterPanel(QWidget):
    def __init__(self, parent):
        QWidget.__init__(self)

    # General Font Object for a couple of Buttons
        btnFont = QFont()
        btnFont.setFamily('Arial')
        btnFont.setItalic(True)

    # First Item Horizontal Box 1 Containing the AddLib Entry and Button
        self.lnAdlibEntry = QLineEdit(self)
#        self.lnAdlibEntry.setGeometry(QRect(30, 20, 501, 51))
#        self.lnAdlibEntry.resize(501, 51)

        self.btnAddLine = QPushButton(self)
#                                       Left, Top, Width, Height
#        self.btnAddLine.setGeometry(QRect(530, 0, 91, 51))
#                            Width, Height
#        self.btnAddLine.resize(91, 51)
        self.btnAddLine.setFont(btnFont)
        self.btnAddLine.setCursor(QCursor(Qt.PointingHandCursor))
        self.btnAddLine.setText('Adlib')
        self.btnAddLine.clicked.connect(parent.AddLineAdlib)

        HBox1 = QHBoxLayout()
        HBox1.addWidget(self.lnAdlibEntry)
        HBox1.addWidget(self.btnAddLine)

    # Second Item Vertical Box 1 Containing the AdlibEntry LineEdit and RTD Label and RTD Slider

        self.lblDial = QLabel(self)
#        self.lblDial.setGeometry(QRect(640, 20, 71, 16))
#        self.lblDial.resize(71, 16)
        self.lblDial.setText("RTD Level")

        self.sldrRtd = QSlider(self)
#        self.sldrRtd.setGeometry(QRect(620, 40, 101, 22))
#        self.sldrRtd.resize(101, 22)
        self.sldrRtd.setOrientation(Qt.Horizontal)

        VBox1 = QVBoxLayout()
        VBox1.addWidget(self.lblDial)
        VBox1.addWidget(self.sldrRtd)

    # Third Item Horizontal Box 2 containing the Save, No Adlib and Delete buttons
        self.btnNoAdlib = QPushButton(self)
#        self.btnNoAdlib.setGeometry(QRect(530, 50, 91, 51))
#        self.btnNoAdlib.resize(91, 51)
        self.btnNoAdlib.setFont(btnFont)
        self.btnNoAdlib.setCursor(QCursor(Qt.PointingHandCursor))
        self.btnNoAdlib.setText("No Adlib")

        self.btnSave = QPushButton(self)
#        self.btnSave.setGeometry(QRect(30, 80, 91, 32))
#        self.btnSave.resize(91, 32)
        self.btnSave.setCursor(QCursor(Qt.PointingHandCursor))
        self.btnSave.setText('Save')

        self.btnDelete = QPushButton(self)
#        self.btnDelete.setGeometry(QRect(120, 80, 91, 32))
#        self.btnDelete.resize(91, 32)
        self.btnDelete.setCursor(QCursor(Qt.PointingHandCursor))
        self.btnDelete.setText('Delete')

        HBox2 = QHBoxLayout()
        HBox2.addWidget(self.btnSave)
        HBox2.addStretch(1)
        HBox2.addWidget(self.btnNoAdlib)
        HBox2.addStretch(1)
        HBox2.addWidget(self.btnDelete)

    # Sixth Item Text Browser
        self.txtBrowser = QTextBrowser(self)
#        self.txtBrowser.setGeometry(QRect(20, 120, 701, 501))
#        self.txtBrowser.resize(701, 501)

        VBox2 = QVBoxLayout()
        VBox2.addLayout(HBox1)
        VBox2.addLayout(VBox1)
        VBox2.addLayout(HBox2)
        VBox2.addWidget(self.txtBrowser)

        self.setLayout(VBox2)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.Lyrics = ''
        self.Adlib = ' (Placeholder adlib)'

        self.setWindowTitle('Main Window')
        self.resize(742, 680)

        self.CenterPane = CenterPanel(self)
        self.setCentralWidget(self.CenterPane)

        self.MenuBar = MenuToolBar(self)
#        self.MenuBar.setGeometry(QRect(0, 0, 742, 22))

        self.SetStatusBar(self)
        self.setStyle(QStyleFactory.create('Cleanlooks'))

    def SetStatusBar(self, parent):
        StatusMsg = ''
        parent.StatBar = parent.statusBar()

        if len(StatusMsg) < 1:
            StatusMsg = 'Ready'

        parent.StatBar.showMessage(StatusMsg)

    def AddLineAdlib(self):
      # This statement retains everything previously in Lyrics and 
      # everything in the AdlibEntry box and everything in Adlib which
      # I am not sure is what you are wanting but it is what you had
        self.Lyrics += self.CenterPane.lnAdlibEntry.text() + self.Adlib + '\n'
        self.CenterPane.lnAdlibEntry.clear()
        self.CenterPane.txtBrowser.setText(self.Lyrics)

    def AddLineNoAdlib(self):
        pass

    def Save(self):
        pass

    def DeleteLine(self):
        pass

if __name__ == "__main__":
    MainThred = QApplication([])

    MainGUI = MainWindow()
    MainGUI.show()

    sysExit(MainThred.exec_())

Modifié: une flèche étrange apparaissant sur mon écran apparaît que l'appel QStyleFactory supprime et j'ajuste la déclaration StatusBar pour qu'elle soit plus modulaire au cas où vous voudriez la classer plus tard p >


4 commentaires

Oh mon dieu merci. Je ne peux pas croire que quelqu'un prendrait son temps pour refaire mon code merdique. Malheureusement, le problème est toujours là, mais au moins maintenant je suis sûr à 100% que le problème est causé par Mac OS. De plus, je suis conscient qu'il mettra toujours quelque chose dans la ligne, il y a un bouton 'No Ad-lib' si vous ne voulez pas qu'il ajoute quoi que ce soit. La fonctionnalité est bien sûr loin d'être terminée, je voulais juste voir si je pouvais au moins faire fonctionner quelque chose. À votre santé!


De plus, votre code est vraiment utile, je l'ai sauvegardé pour référence future


@ Expected2BlankLines note que j'ai apporté quelques modifications à ce qui précède que vous voudrez peut-être enregistrer car ils auraient dû être là pour commencer, les oubliant. Oh et ce truc QStyleFactory pourrait résoudre le problème, je ne sais pas exactement ce qu'il fait encore en apprenant pyqt5 moi-même


merci pour la mise à jour, l'édition a en fait éliminé le visuel, mais dans l'édition de ligne, je n'ai que le texte non mis à jour à m'inquiéter. Je pense que je pourrais le réduire une fois plus à l'aise avec PyQt5



3
votes

J'ai trouvé le même problème que le vôtre et j'utilise MacOS Mojave 10.14.6. Ce problème est peut-être dû au système d'exploitation, mais j'ai rétrogradé pyqt5 de la dernière version 5.14.1 à une version stable 5.9.2, le problème a été résolu.


1 commentaires

C'est certainement la combinaison de la version OS \ PyQt qui le provoque, je suis depuis passé principalement au codage sur mon PC Windows et je ne l'ai jamais rencontré.



0
votes

Ce problème se produit également avec macos 10.15.6 + pyqt 5.15.0. J'ai créé un petit exemple avec qtdesigner (avec 1 boîte lineEdit, 1 boîte d'étiquette, 1 bouton), puis j'ai créé un fichier python avec pyuic5 ainsi qu'avec pyside2-uic.

Les deux fichiers python générés ont le même problème - quand "clic" est pressé Je dois sortir de la fenêtre et revenir en arrière pour voir les résultats. Mais si j'appuie simplement sur Entrée après le texte d'entrée, il apparaît immédiatement.

Le problème est résolu en ajoutant une ligne supplémentaire dans la classe principale, pour repeindre l'interface graphique, comme indiqué ci-dessous:

import sys
from PyQt5.QtWidgets import QDialog, QApplication
from demo_ui_pyuic5 import *

class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.buttonClick.clicked.connect(self.dispmessage)
        self.show()
    def dispmessage(self):
        self.ui.labelResponse.setText("Hello " + self.ui.lineEditName.text())
        self.ui.labelResponse.repaint() # this line added to fix the problem

if __name__=="__main__":
    app = QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())


0 commentaires