PyQt5-除非将开关切换到其他窗口,为什么我的小部件不更新?

时间:2019-07-23 18:04:05

标签: python python-3.x pyqt pyqt5

所以我刚开始使用PyQt5。现在,我只编程了一个按钮,该按钮应该从行编辑中获取文本,将其存储在全局变量中,然后将其放入文本浏览器中。现在,它可以执行此操作...但是存在问题。 直到我单击另一个程序/窗口,然后再次单击我的应用程序,文本浏览器才会更新 清除行编辑后,会出现一个错误,该错误基本上是文本无法正确清除,而只是上半部分。当我再次键入时,这种情况消失了。

我尝试为小部件和QApplication.process_events()调用.update()方法

这是代码

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_())

4 个答案:

答案 0 :(得分:3)

我发现了与您相同的问题,并且使用了MacOS Mojave 10.14.6。此问题可能是由于操作系统引起的,但我将pyqt5从最新的5.14.1降级到了稳定的版本5.9.2,此问题已解决。

答案 1 :(得分:0)


1. The text browser does NOT update until I click another program/window and then click my app again-此问题可能与您的操作系统有关。我在Ubuntu 16.04上有不正确的PyQT5行为,而在Ubuntu 18.04上一切正常。您可以分享更多信息吗?
注意:我在Ubuntu 18.04上测试了您的脚本,不需要单击其他程序/窗口来刷新它

2. When the line edit is cleared there is a bug which is basically text not being cleared properly but only it's top half. This goes away when I type again.-您能解释it's top half是什么意思吗?如果您表示仍然有(Placeholder adlib)个文本,则应在将某些内容添加到歌词变量之前修改函数以检查lineEdit文本框。例如,像这样:

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

答案 2 :(得分:0)

这是程序的更干净,更分类的版本(更加pythonic pyqt),我在其中留下了一些注释,供您查看它的位置,但我删除了坐标系,并用更标准的Layout替换了它。创建GUI的样式。

我在win10上使用python 3.7 pyqt5进行了测试,因此,如果有操作系统问题,您将知道它,但我的猜测(不深入探讨这一丑陋的麻烦)是某些地方存在断开连接,从而造成了您遇到的问题。 / p>

按设计,您的按钮也不会创建空行,因为它总是在一行上放东西-我通过单击按钮而不输入任何内容来对此进行了测试

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_())

编辑:我的屏幕上出现了一个奇怪的箭头,它似乎删除了QStyleFactory调用,并且我将StatusBar声明调整为更具模块化,以防以后要对其进行类化

答案 3 :(得分:0)

macos 10.15.6 + pyqt 5.15.0也会发生此问题。 我使用qtdesigner创建了一个小示例(带有1个lineEdit框,1个标签框,1个按钮),然后使用pyuic5和pyside2-uic创建了python文件。

两个生成的python文件都存在相同的问题-按下“单击”时,我必须移出窗口并再次返回以查看结果。但是,如果我只在输入文本后按Enter键,它就会立即显示。

通过在主类中添加额外的一行以重新绘制GUI,可以解决该问题,如下所示:

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_())