返回
Featured image of post Python - PYQT 踩坑记

Python - PYQT 踩坑记

一年里两次用PYQT,满脚是血,记录一些踩过的坑.

首先要踩一下 PYQT,如果使用 Python 过程中有 GUI 方面的需求,请一定一定先看有没有 QT 之外的选择 (Django不好吗?)。用过 PYQT 的都知道,QT 提供的不仅仅是 GUI 组件库,而是从线程到网络通信的一整套 QObject ,个人认为对于 Python 而言这实在是过于不实际了,我觉得大多数人对于 Python 开发的期望都是每一个模块各司其职,项目能够“高内聚,低耦合”,Python 在这方面也是非常令人满意的,然而在 QT 中除外。

PYQT 来源于 C++ QT,其理念就是将众多组件耦合到一起,如果你在一个团队中进行开发,这会导致——无论是图形界面方面的责任,还是业务逻辑方面的问题都会堆到你这里,成为你的压力,而如果你作为个人进行开发,这会使你写 GUI 的时候无时无刻不得顾及业务需求,两边都得顾得上,两边都得一起调。出了问题的话,非常不幸,网上能找到的 PYQT 资料非常之有限,甚至官方文档中都有大量的 TODO ,且完全没有要补上的迹象,我写代码过程中基本都只能参考 QT 的官方文档,因为他实在是比 PyQt 官方提供的要友好得多。

如果在确认了这些问题之后,还是要入门 PYQT,推荐几个 Github:PyQt Examples 提供了大部分常用 GUI 组件的使用 Deemo,虽然 PyQt 对于这些组件基本都有大量复杂数倍的替代品,供你完成非常繁杂的需求,但是,没有谁想从那入手的。

顺便提一下,有个非常不错(指功能上)的 PyQt 音乐播放器 FeelUOwn 项目。当时看到这个小项目是很感动的,非常兴奋地下下来源码,然后确信自己看的是天书——项目代码不是给人读的,PyQt 极大放大了代码可读性差的问题

接下来是正片——


开始 PyQt 项目,你要知道这些

  • 如果用 PyCharm 构建 PyQt 项目,你在点下 Run/Debug 之前请务必检查一下 Debug 配置

    Run 和 Debug 图标左边那个下拉菜单,其中的 Edit Configurations,请检查一下 Configuration 下的 Excution 栏,确保 Emulate terminal in output console 这个选项勾上。否则即使你的程序挂掉,控制台也不会抛出一个异常来,没有什么比程序跑不起来,甚至连哪里出了问题都无法追溯更让人头疼的事情了。


使用 QSS ,你要知道这些

QSS 看似很美好,但也是重灾区。

  • QSS Style Sheet 会自动由父框架传递给子框架

    什么意思呢?就是说你可能想给 QWidget 设个好看的边框,于是写下这么一段内容:

    QWidget {
        background: lightGray;
        border: 3px solid blue;
    }
    

    然后发现所有 Widget 下所有的 QLabel 都诡异地多了个框而父框架反而没有。为什么呢?因为 QLabel 也是 QWidget 的一种,QWidget 的样式表会自动传递到它,并且生效。然而 QWidget 自己却不能生效,因为 QWidget 天生无法让自己的显式样式生效,它们只是用来传递给子框架的,换句话说,Qt 就这么设计的。

    如果想让父框架有边框之类的设置,请用 QFrame ,它不仅有同样的参数而且几乎能替代 QWidget

  • 请尽量使用对象的 objectName 来区分子对象的样式

    如果你想要你的设置仅仅对最外层,或子对象中的一个生效,请这么写:

    QWidget[objectName='OutsidePanel'] {
        background: lightGray;
        border: 3px solid blue;
    }
    

    那什么是 objectName 呢?它是 QObject 的一个成员变量,没错,PyQt 在最不需要解耦的地方做了一次解耦,让 objectName 需要单独设置。所以接下来,在这个你想让它有边框的 QWidget 的构造函数中写下:self.setObjectName("OutsidePanel")

    不推荐将组件的样式表颗粒化,在初始化过程中单独 setStyleSheet() ,还是推荐将一整个 Panel 的样式整合成一个文件,在父框架进行设置,而避免在运行过程中还要动态加载。我认为 Qt 的设计者也是这样希望的,应当有相应的优化。

    关于 QSS ,网上其实能查到很多内容,比方有人说可以直接跟据对象名和 CSS 一样用 # 设置对象的样式,实测并不行,推测可能是 PyQt 版本不同,能力也有所不同,很多网上提供的 QSS 属性也并不能生效。虽然 QSS 想让做 GUI 的人尽量用熟悉的方法——CSS来设计,但功能属实有限,不能达到 CSS 的效果不说,还给了有 CSS 使用经验的人过多不切实际的幻想,只能说是将 PyQt 本就有限的样式设置从 GUI 设计中部分解耦出来。

【未完,对 PyQt ,想吐槽的点实在是如涛涛江水一般】

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus