【初体验pyqt5】动态添加删除控件你会了吗

前段时间基于pyqt5开发了一个小软件,虽然之前没有接触过qt,但是使用过一段时间的python,主要写一些功能性脚本。

小软件的功能是在屏幕上美观地实时显示键盘的输入,主要适用于视频/直播教学的使用环境。

在这里插入图片描述

开发用时不到一天,期间查了许多的文章与文档,翻过了许多的坑,而且看到的一些教程还有pyqt4的,还得查询最新的官方文档进行新版本的兼容。

当时翻阅的主要是qt的官方文档(因为pyqt的文档不太好找),虽然是C++的,但内容基本一致,几乎没有转换到python的门槛。

问题一:因为使用了time.sleep()而导致的各种bug(如窗口尺寸刷新不及时等)

解决方法:使用pyqt自带的QTimer,包括窗口渐隐之类的动画,都需要用QTimer实现,否则会导致线程阻塞。

问题二:动态增加、删除控件(widget)

首先,对于动态增加控件,查阅官方文档后,应使用

self.layout.addWidget(widget)

对于动态删除控件,应使用

self.layout.itemAt(i).widget().deleteLater()

官方文档中仅有deleteLater()方法,其余的delete()以及sip.delete(widget)经试验都是不对的。

具体效果请参照下面的例子:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
'''pyqt5动态添加删除控件'''

class DynAddObject(QDialog):
    def __init__(self, parent=None):
        super(DynAddObject, self).__init__(parent)
        self.widgetList = []
        addButton = QPushButton(u"添加控件")
        delBUtton = QPushButton(u"删除控件")
        self.layout = QGridLayout()
        self.layout.addWidget(addButton, 1, 0)
        self.layout.addWidget(delBUtton, 2, 0)
        self.setLayout(self.layout)
        addButton.clicked.connect(self.add)
        delBUtton.clicked.connect(self.delete)

    def add(self):
        btncont= self.layout.count()
        widget = QPushButton(str(btncont-1), self)
        self.layout.addWidget(widget)
        
    def delete(self):
        for i in range(self.layout.count())[2:]:
            self.layout.itemAt(i).widget().deleteLater()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = DynAddObject()
    form.show()
    app.exec_()

在这里插入图片描述
一个明显的问题:被撑大的窗口无法复原,在下面中解决。

问题三:窗口大小不能自适应内部layout与widget的大小

在动态生成layout与widget的过程中,一开始窗口能够自适应内部的元素,以合适的尺寸显示,但是当窗口被撑大之后无法自动缩小复原。
解决方法:添加一个QTimer以循环执行,在QTimer中使用self.resize(self.sizeHint())。这个sizeHint()能够自动给出该widget的建议的尺寸。
对于上面给出的例子,可以修改如下:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
'''pyqt5动态添加删除控件'''

class DynAddObject(QDialog):
    def __init__(self, parent=None):
        super(DynAddObject, self).__init__(parent)
        self.widgetList = []
        addButton = QPushButton(u"添加控件")
        delBUtton = QPushButton(u"删除控件")
        self.layout = QGridLayout()
        self.layout.addWidget(addButton, 1, 0)
        self.layout.addWidget(delBUtton, 2, 0)
        self.setLayout(self.layout)
        addButton.clicked.connect(self.add)
        delBUtton.clicked.connect(self.delete)

    def add(self):
        btncont= self.layout.count()
        widget = QPushButton(str(btncont-1), self)
        self.layout.addWidget(widget)
        
    def delete(self):
        for i in range(self.layout.count())[2:]:
            self.layout.itemAt(i).widget().deleteLater()
        # 在这里设置了timer
        self.timer = QTimer(self)
        self.timer.timeout.connect(lambda:self.resize(self.sizeHint()))
        self.timer.start(1)
    

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = DynAddObject()
    form.show()
    app.exec_()

在这里插入图片描述
在最终的项目中,我使用了60hz的刷新率执行这个timer,其中不仅包含了窗口的resize,还有淡入淡出的动画处理等。

总结

pyqt5带给我的感受尚可,但查询众多资料的过程真的很令人头疼,最后使用pyinstaller打包的exe达到了臃肿的41MB,其实对于追求简洁美的我来说是不太能够接受的,并且在我的印象中qt的封装结果也是同样臃肿,且丑。万幸的是可以通过setStyleSheet()稍微挽救一些颜值。

这是我第一次使用pyqt,大概也会是最后一次。在朋友的推荐下,估计今后会在业余时间学习了解一下electron。同时也希望这篇文章能够帮助到一些学习者,祝早日跳出这些坑。

未来我还是比较看好JavaSript/TypeSript。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值