刷新QLCDNumber并实现通用函数

时间:2017-11-05 18:25:48

标签: python python-3.x pyqt pyqt5

我在开始使用pyqt5编程GUI之前做了一些初步测试,今天我发现了一些我无法解决的问题。

我的代码如下:

from PyQt5 import QtCore, QtGui, QtWidgets
import time

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(398, 398)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(30, 40, 131, 61))
        self.lineEdit.setText("")
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_2.setGeometry(QtCore.QRect(30, 120, 131, 61))
        self.lineEdit_2.setText("")
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcdNumber.setGeometry(QtCore.QRect(180, 40, 64, 23))
        self.lcdNumber.setObjectName("lcdNumber")
        self.lcdNumber_2 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcdNumber_2.setGeometry(QtCore.QRect(180, 120, 64, 23))
        self.lcdNumber_2.setObjectName("lcdNumber_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 398, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)


        self.number = 0
        self.number_2 = 0
        self.lcdNumber.display(self.number)
        self.lcdNumber_2.display(self.number_2)


        self.lineEdit.returnPressed.connect(self.change_number)


        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


    def change_number(self):
        ip = int(self.lineEdit.text())

        if ip > self.number:
            count = 1
        elif ip < self.number:
            count = -1
        else:
            count = 0

        while self.number != ip :
            self.number += count
            self.lcdNumber.display(self.number)
            time.sleep(1)





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

如您所见,我有两个QLineEdit框和两个QLCDNumber,用于显示我在相应QLineEdit中写的数字。

问题1

我可以使用以下代码在QLCDNumber中显示数字:

self.lineEdit.returnPressed.connect(self.change_number)

...

def change_number(self):
    self.lcdNumber.display(int(self.lineEdit.text()))

但是,如果我想以一定的时间延迟逐个更改显示的数字,我的代码并不像我期望的那样工作。

例如,如果当前数字为0并且我在QLineEdit中键入10,则程序冻结10秒,然后数字10显示在QLCDNumber上,而我希望它会逐秒更新。我真的无法弄清楚问题出在哪里。

问题2

我有两个QLineEdit和两个QLCDNumber,写两个不同的函数change_number没有多大意义。 但是,我找不到一种编写通用函数的方法,该函数将作为QLCDNumber将被更新的输入以及哪个QLineEdit将作为输入。 在伪代码中,它将是这样的:

self.LINEEDIT_NAME.returnPressed.connect(self.change_number(LINEEDIT_NAME,QLCD_NAME))

...

def change_number(self,LINEEDIT_NAME,QLCD_NAME):
    ip = int(self.LINEEDIT_NAME.text())

    if ip > self.number:
        count = 1
    elif ip < self.number:
        count = -1
    else:
        count = 0

    while self.number != ip :
        self.number += count
        self.QLCD_NAME.display(self.number)
        time.sleep(1)

但我无法将LINEEDIT_NAME和QLCD_NAME用作功能的变量。

1 个答案:

答案 0 :(得分:0)

time.sleep()是阻止PyQt循环的任务,因此不建议使用它,可以使用QTimer轻松替换该任务。

为方便工作,我们将创建一个继承自QLCDNumber并使用QTimer更新值的类

<强> TimerLCDNumber.py

from PyQt5 import QtCore, QtGui, QtWidgets

class TimerLCDNumber(QtWidgets.QLCDNumber):
    def __init__(self, *args, **kwargs):
        QtWidgets.QLCDNumber.__init__(self, *args, **kwargs)
        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.onTimeout)
        self.finished = self.value()

    def setValue(self, value):
        self.finished = value
        self.timer.start()

    def onTimeout(self):
        current = self.value()
        if self.finished != current:
            count  = 1 if self.finished > current else -1
            self.display(current + count)
        else:
            self.timer.stop()

可以通过Qt Designer推广此任务,或者只需更改,假设Qt Designer生成的文件名为design.py:

<强> design.py

self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
self.lcdNumber_2 = QtWidgets.QLCDNumber(self.centralwidget)

为:

self.lcdNumber = TimerLCDNumber(self.centralwidget)
self.lcdNumber_2 = TimerLCDNumber(self.centralwidget)

此外,必须导入TimerLCDNumber类:

from TimerLCDNumber import TimerLCDNumber

建议将设计与逻辑分开,以便创建一个名为main.py的新文件,用于导入设计类并实现逻辑:

<强> main.py

from PyQt5 import QtCore, QtGui, QtWidgets
from design import Ui_MainWindow


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.lineEdit.returnPressed.connect(lambda: self.lcdNumber.setValue(int(self.lineEdit.text())))
        self.lineEdit_2.returnPressed.connect(lambda: self.lcdNumber_2.setValue(int(self.lineEdit_2.text())))
        self.lcdNumber.display(0)
        self.lcdNumber_2.display(0) 


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

在我们文件夹的最后,我们必须具有以下结构:

.
├── design.py
├── main.py
└── TimerLCDNumber.py

第二个问题的可能解决方案是使用lambda函数:

第一个选项:

self.lineEdit.returnPressed.connect(lambda: self.lcdNumber.setValue(int(self.lineEdit.text())))
self.lineEdit_2.returnPressed.connect(lambda: self.lcdNumber_2.setValue(int(self.lineEdit_2.text())))

第二个选项:

    self.lineEdit.returnPressed.connect(lambda: change_number(self.lineEdit, self.lcdNumber))
    self.lineEdit_2.returnPressed.connect(lambda: change_number(self.lineEdit_2, self.lcdNumber_2))


def change_number(self,LINEEDIT_NAME,QLCD_NAME):
    QLCD_NAME.setValue(int(LINEEDIT_NAME.text()))

可以在以下link找到完整的代码。