跳转至

hyqt 库

点击这里,边看视频讲解 边学习下面的教程


我开发了一个 python Qt 的开发库: hyqt, 方便大家更快速的开发 Python Qt 程序。

其中的一个重要功能就是:更方便地设置样式和布局

目前 hyqt 只支持 PySide6,将来可能会加入对 PyQt6的支持


该库永远开源免费,GitHub网址是:https://github.com/jcyrss/hyqt

用下来如果觉得好的,请给我加一颗星 :)

安装

hyqt 需要 Python版本 >=3.11

执行 pip install hyqt 即可

界面布局 Row/Column

Qt的界面经常是 由水平/垂直 layout 构成,所以这个库的重点之一就是提供水平/垂直布局的快速实现。

包括:元素的的排布方式,对齐,间隔, 容器控件的颜色,扩展策略,等等


使用 库中的 Row 对象进行水平布局, Column 对象进行垂直布局

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Row(
    s__(bgColor='aliceblue',width=300, height=100,paddings=5),        
    QLabel('姓名'),
    QLineEdit('白月黑羽'),
)

win.show()
app.exec()

运行后界面如下


上面代码中,使用 Row 指定了一个水平布局的容器控件。

代码第7行,它的第一个参数是 设定布局容器控件(实际上是Qt的 Frame 控件)的样式 。

后面的参数是Row里面的子控件。

第7行 样式参数里面指定 Row的 背景色为 aliceblue, 固定宽度为 300px, 固定高度为100px, 内边距 5px


类似的,下面是使用 Column 指定的一个垂直布局的例子

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
        s__(bgColor='aliceblue', paddings=5, size=(400,300),
            itemsJustify='start',itemsAlign='center'),     

        Row(s__(vExpanding=False), QLabel('姓名'), QLineEdit('白月黑羽')),
        Row(s__(vExpanding=False), QLabel('年龄'), QLineEdit('32')),
        Row(s__(vExpanding=False), QLabel('身高'), QLineEdit('170')),
    )

win.show()
app.exec()

运行后界面如下


ColumnRow 是可以互相嵌套的

itemsJustify='start' 指定了 子控件 的主轴对齐方式是 开头对齐。对于column来说, 也就是元素尽量挤到上面。 你可以把它换成 center and 看一下效果。

itemsAlign='center' 指定了 子控件 的从轴对齐方式是 中间对齐。对于column来说, 也就是元素水平方向中间对齐 。 你可以把它换成 left right ,看一下效果。


容器控件的样式都是在第一个参数中设定的。

全部的样式设置,有如下这些

Row/Column 样式参数

windowTitle : str
    如果 Row/Column 为顶级窗口可以用 windowTitle 直接设置窗口标题

itemsJustify : str
    设置子控件的主轴对齐
    取值为 start, center, end even, None

    如果为 even 表示平均间隔类似 css flex justify space-between 的效果            
    | ele |  | ele |  | ele |   | ele |   
     even  spacing 的值强制为0


itemsAlign : str
    设置子控件的从轴对齐

    Column 取值为 top, center, bottom, None
    Row 取值为 left, center, right, None

    注意 如果设置了 itemsAlign 会阻止子控件的 sizepolicy Expanding


spacing : int
    子控件之间的间隔单位 px, 缺省为 10px 

    如果为 -1 表示平均间隔类似 css flex justify space-between 的效果            
    | ele |  | ele |  | ele |   | ele |   
     -1  justify的值无效

size: list | tuple
    设置自身的尺寸比如 (300, 200) 就是宽度300px高度200px

width : int
    设置自身的固定宽度
height : int
    设置自身的固定高度

minWidth : int
    设置最小宽度
minHeight : int
    设置最小高度
maxWidth : int
    设置最大宽度
maxHeight : int
    设置最大高度

stretchFactor : int
    设置容器控件自身 在上级容器中的扩展权重

align : str
    设置容器控件自身 在上级容器中的对齐

color : str
    字体颜色
bgColor : str
    背景颜色
fontSize : int
    字体大小 
fontFamily : str
    字体比如 "微软雅黑"

border : str
    边框比如 "1px solid #367fa9"

paddings : int | list
    内边距单位 px可以是整数或者是列表
    比如 paddings=10 表示四边距都是 10px
    paddings=[10, 20, 30, 40] 表示 左10px上20px右30px下40px

hExpanding : bool
    是否横向扩展缺省为 True
vExpanding : bool
    是否纵向扩展缺省为 True

name : str
    setObjectName 设置的名称

styleSheet : str
    该控件的styleSheet用来设置其它参数没有设置的样式

注意:

Row/Column 的水平/垂直 扩展策略, 缺省都是 扩展


有时我们想在子控件之间加上 额外的空白间隔 ,这时可以使用 spacing(间隔数值)

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
    s__(itemsJustify='center', spacing=20, paddings=10, 
        bgColor='aliceblue',width=300, height=300),

    QLabel('第1行'),
    QLabel('第2行'),
    QLabel('第3行'),
    spacing(100), #额外垂直间隔区
    QLabel('第4行'),

)

win.show()
app.exec()

运行效果如下

末尾添加子控件 append

如果要在 Row/Column 内部子控件 末尾添加 新子控件,使用 append 方法

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
        s__(bgColor='aliceblue', paddings=5, size=(400,300),
            itemsJustify='start',itemsAlign='center'),     

        Row(s__(vExpanding=False), QLabel('姓名'), QLineEdit('白月黑羽')),
        Row(s__(vExpanding=False), QLabel('年龄'), QLineEdit('32')),
        Row(s__(vExpanding=False), QLabel('身高'), QLineEdit('170')),
    )

win.append( Row(s__(vExpanding=False), QLabel('体重'), QLineEdit('60') ) )

win.show()
app.exec()

插入子控件 insert

如果要在 Row/Column 内部子控件 插入 新子控件,使用 insert 方法

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
        s__(bgColor='aliceblue', paddings=5, size=(400,300),
            itemsJustify='start',itemsAlign='center'),     

        Row(s__(vExpanding=False), QLabel('姓名'), QLineEdit('白月黑羽')),
        Row(s__(vExpanding=False), QLabel('年龄'), QLineEdit('32')),
        Row(s__(vExpanding=False), QLabel('身高'), QLineEdit('170')),
    )

# 在原来的第3个(次序从0开始)控件前面插入
win.insert(2, Row(s__(vExpanding=False), QLabel('体重'), QLineEdit('60')) )

win.show()
app.exec()

删除子控件 delete

如果要在 Row/Column 内部子控件 删除 子控件,使用 delete 方法

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
        s__(bgColor='aliceblue', paddings=5, size=(400,300),
            itemsJustify='start',itemsAlign='center'),     

        Row(s__(vExpanding=False), QLabel('姓名'), QLineEdit('白月黑羽')),
        Row(s__(vExpanding=False), QLabel('年龄'), QLineEdit('32')),
        h := Row(s__(vExpanding=False), QLabel('身高'), QLineEdit('170')),
    )

win.delete(h)

win.show()
app.exec()

清空所有子控件 clear

如果要在 Row/Column 内部 清空所有 子控件,使用 clear 方法

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
        s__(bgColor='aliceblue', paddings=5, size=(400,300),
            itemsJustify='start',itemsAlign='center'),     

        Row(s__(vExpanding=False), QLabel('姓名'), QLineEdit('白月黑羽')),
        Row(s__(vExpanding=False), QLabel('年龄'), QLineEdit('32')),
        Row(s__(vExpanding=False), QLabel('身高'), QLineEdit('170')),
    )

win.clear()

win.show()
app.exec()

hyqt封装控件

为了方便我们快速地设置qt控件的样式和行为, hyqt提供了ss函数和 hyqt控件

ss函数

hyqt 提供了 ss (set style)函数,封装Qt已经存在的控件

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
        s__(bgColor='aliceblue', paddings=5, size=(400,300),
            itemsJustify='start',itemsAlign='center'),     

        Row(
            ss(QLabel('姓名'), fontFamily='微软雅黑', fontSize=14, color='#666'), 
            ss(QLineEdit('白月黑羽'),  color='#32779f' ,bgColor='#e8f0fe', width=280,height=30),
        ),

        Row(
            ss(QLabel('身高'), fontFamily='微软雅黑', fontSize=14, color='#666'), 
            ss(QLineEdit('170'),  color='#32779f' ,bgColor='#e8f0fe', width=280,height=30),
        ),
    )

win.show()
app.exec()


ss 函数的所有参数说明如下

    widget : QWidget
        需要设置样式的控件

    size : tuple[int,int]
        设置控件的尺寸
    width : int
        设置控件的固定宽度
    height : int
        设置控件的固定高度

    minWidth : int
        设置最小宽度
    minHeight : int
        设置最小高度
    maxWidth : int
        设置最大宽度
    maxHeight : int
        设置最大高度

    stretchFactor : int
        设置控件 在上级容器中的扩展权重

    align : str
        设置控件 在上级容器中的对齐

    color : str
        字体颜色
    bgColor : str
        背景颜色
    hoverColor : str 
        鼠标悬浮时的颜色
    hoverBgColor : str
        鼠标悬浮时的背景颜色

    fontSize : int
        字体大小 
    fontFamily : str
        字体比如 "微软雅黑"

    border : str
        边框比如 "1px solid #367fa9"

    padding : string
        设置控件的 QSS padding比如 "13px"
        "15px 16px 17px 18px" 是上右下左的顺序设置

        注意和RowColumn 容器控件  paddings 设置不一样
        那个是数字或者是数字列表而且是左上右下次序

    hExpanding : bool
        是否横向扩展缺省为 False
    vExpanding : bool
        是否纵向扩展缺省为 False

    name : str
        setObjectName 设置的名称

    styleSheet : str
        该控件的styleSheet用来设置其它参数没有设置的样式

注意:

封装控件 的水平/垂直 扩展策略, 缺省都是 不扩展

Label

Labelhyqt 封装的 QLabel 控件

除了 可以直接在初始化参数中设置 ss 函数里面的样式参数 之外, 还可以设置 显示图片和图片的size

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Row(
        Label(labelImg='icons/logo.png', labelImgSize=30) ,
        Label('白月 SMS 系统', fontSize=28, fontWeight='bold', color='#32779f'),
    )

win.show()
app.exec()

Button

Buttonhyqt 封装的 QPushButton 控件

除了 可以直接在初始化参数中设置 ss 函数里面的样式参数 之外, 还可以直接参数设置 点击回调函数

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Row(
    s__(paddings=10),
    Button('登录', color='white', bgColor='#367fa9', width=280, height=32, 
        border='1px solid #367fa9', 
        onClick=lambda: print('点击登录回调函数')
    ),        
)

win.show()
app.exec()

ButtonF

扁平风格按钮,如下, 其它和 Button 用法一致

ButtonNB

是无边框按钮,除了没有边框,其它和 Button 用法一致

Input

Inputhyqt 封装的 QLineEdit 控件

除了 可以直接在初始化参数中设置 ss 函数里面的样式参数 之外, 还可以直接设置 如下参数

placeholder : str
    输入提示占位符

textAlign : str
    内部文本的对齐方式取值为 center, left, right

echoMode : str
    文字回显模式取值为 normal, no-echo, password password-echo-on-edit

leadingActionIcon : str
    内部前置图标

trailingActionIcon : str
    内部后置图标

intOnly : bool
    只允许输入整数

onChange : Callable
    内部文本改变时的回调函数

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
    s__( paddings=20),

    username:= Input('byhy', align='center', textAlign='center', width=280, height=32,
                        trailingActionIcon='icons/icon-user.png'),
    password:= Input('88888888',  align='center', textAlign='center',width=280, height=32,
                    echoMode='password',trailingActionIcon='icons/icon-passwd.png'),

    Button('登录', color='white', bgColor='#367fa9', width=280, height=32, 
        border='1px solid #367fa9', # 否则鼠标移到界面上,背景颜色会变白
        onClick=lambda: print(username.text(), password.text()) 
    ), 
)

win.show()
app.exec()

TextArea

TextAreahyqt 封装的 QTextEdit 控件

除了 可以直接在初始化参数中设置 ss 函数里面的样式参数 之外, 还可以直接设置 如下参数

placeholder : str
    输入提示占位符

onChange : Callable
    内部文本改变时的回调函数

TextBrowser

TextBrowserhyqt 封装的 QTextBrowser 控件

可以直接在初始化参数中设置 ss 函数里面的样式参数

水平/垂直线

有时我们想在子控件之间加上 水平/垂直 分割线 ,这时可以使用 VerticalLine() , HorizontalLine() 类型

比如

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
    s__(itemsAlign='center', spacing=20, paddings=10, 
        bgColor='white', width=300, height=300),

    QLabel('第1行'),

    HorizontalLine(), # 水平分割线

    QLabel('第2行'),

    HorizontalLine(color='green',lineWidth=2), # 分割线,指定颜色,宽度

    Row(
        QLabel('第1列'),
        VerticalLine(), # 垂直分割线
        QLabel('第2列')
    )
)

win.show()
app.exec()

运行效果如下

后续会提供其它封装控件...

实用案例1 - 登录窗口

具体内容请看视频讲解

视频对应代码如下

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
    s__(itemsJustify='center',itemsAlign='center',
        bgColor='#e7ebf2',width=800, height=600, 
        styleSheet='''
            * {
                font-family: 微软雅黑 ;
                font-size:14px;
                color: #666;
            }
        '''),        

    # 标题栏
    Row(
        s__(itemsJustify='center',itemsAlign='center',spacing=20),
        Label(labelImg='icons/logo.png', labelImgSize=30) ,
        Label('白月 SMS 系统', fontSize=28, fontWeight='bold', 
              color='#32779f'),
    ),

    # 登录框
    Column(
        s__(itemsJustify='center',itemsAlign='center', spacing=20,
            bgColor='white',width=360,paddings=[0,30,0,30]),

        Label('输入 用户名/密码 登录'),

        username:= Input('byhy', textAlign='center', width=280, height=32,
            trailingActionIcon='icons/icon-user.png',
            bgColor='#e8f0fe',border="1px solid #e8f0fe"),

        password:= Input('88888888',  textAlign='center',width=280, height=32,
            echoMode='password',trailingActionIcon='icons/icon-passwd.png',
            bgColor='#e8f0fe',border="1px solid #e8f0fe"),

        Button('登录',  color='white', bgColor='#367fa9', width=280, height=32, 
            border='1px solid #367fa9', # 否则鼠标移到界面上,背景颜色会变白
            onClick=lambda: print(username.text(), password.text()) 
        ),
    ),

    # 额外空白间隔区
    spacing(150)

)

win.show()
app.exec()

实用案例2 - 主界面

具体内容请看视频讲解

视频对应代码如下

from PySide6.QtWidgets import *
from hyqt import *

app = QApplication()

win =  Column(
    s__( paddings=0, spacing=0, bgColor='white',size=(1000,800),
        styleSheet='''
        *{
            font-family: 微软雅黑;
            font-size: 14px;
            color: #666;
        }
        ''',
    ),

    # 导航栏
    Row(
        s__( bgColor='AliceBlue', paddings=[10,0,0,0], itemsJustify='even', height=50),

        Label('WorkFlow', fontSize=18),

        # 个人信息
        Row(s__(hExpanding=False, spacing=20),
            Label(labelImg='icons/avatars/f1.png',labelImgSize=20 ),
            Label('白月黑羽', ),
            Label(labelImg='icons/logout.png',labelImgSize=15),
        ),
    ),

    # 下方主体
    Row(
        s__(spacing=0,  paddings=0),

        # 左边菜单
        Column(
            s__(itemsJustify='start', stretchFactor=1,  paddings=0, 
                minWidth=200, maxWidth=300),

            Label('操作菜单',vExpanding=False, padding='20px 10px'), 

            Column( 
                s__(itemsJustify='start', spacing=0,  paddings=0, styleSheet='''
                QLabel{
                    padding: 15px 20px;
                    color: #2268a2;
                }
                QLabel:hover{
                    background: Bisque;
                }
                ''',
                ),
                Label('权限',hExpanding=True), 
                Label('群组',hExpanding=True), 
                Label('账号',hExpanding=True), 
                Label('工作流',hExpanding=True), 
            )
        ),

        VerticalLine(),

        # 右边主体内容
        Column(
            s__( stretchFactor=3),
            Label('白月黑羽')
        )
    )

)
win.show()
app.exec()