长期以来,Tkinter 作为 Python 的标准 GUI 工具包,在简易性和可移植性方面有着不错的表现。然而,随着技术的迅速发展,Tkinter 在功能和现代化设计方面逐渐显得力不从心。因此,作者认为Tkinter 已逐渐被淘汰。
对于那些仍需简单的桌面小工具,以替代传统的命令行界面,PySimpleGUI 提供了一个轻量级且易于使用的解决方案。它允许用户快速创建窗口、按钮和其他常见的GUI元素,无需深入了解底层的GUI框架。
对于更复杂的桌面应用程序,PyQt 是一个不错的选择。它基于 Qt 框架,提供了丰富的功能和强大的定制性,非常适合构建高度复杂的用户界面。
近年来,基于浏览器的UI框架越来越受欢迎。相对于传统的桌面软件,这些框架更加灵活,能够轻松地实现跨平台功能。其中,像 Gradio、Streamlit 和 NiceGUI 这样的框架尤为突出。
在这些框架中,作者最推荐使用 NiceGUI。NiceGUI 提供了一种简单、直观的方式来构建富有吸引力的Web界面,无需深入研究复杂的前端技术。
本文接下来将详细探讨这些框架的特点和使用场景,以及它们如何改变我们构建GUI应用的方式。
开篇第一句话:Python GUI For Humans, 其将tkinter, Qt, Remi, WxPython转换为便于移植的、对码农友好的Python化界面。
Python有不少开源GUI的库,都在试图解决码农和普通用户之间的“GUI鸿沟”,但是几乎其他Python GUI库的安装和配置比较复杂,学习曲线较陡。
PySimpleGUI是一个Python包,目的是让所有人都能使用图形界面来构建自己的Python程序。PySimpleGUI窗口的构建过程中采用列表和字典等数据类型,列表和字典等数据类型是Python的基本数据类型,初学者都必须掌握,因此掌握Python语言后,对于PySimpleGUI的使用可以迅速入手。另外,将事件处理方式从回调的模型更改为消息传递模型,可以进一步简化代码,从代码的结构和易读性都更符合思考逻辑。
官方在GitHub上给出几百个demo,可以去下载学习,网址为:
https://github.com/PySimpleGUI/
示例:
import PySimpleGUI as sg
sg.theme('LightGreen')
# 窗体界面布局
layout = [
[sg.Text('Radio、Checkbox、Combo演示', size=(40, 1), justification='center')],
[sg.Radio('Radio1','Radio', key='-Radio1-'),
sg.Radio('Radio2', 'Radio',key='-Radio2-')],
[sg.Checkbox('CheckBox1',key='-CHECKBOX1-'),
sg.Checkbox('CheckBox2',key='-CHECKBOX2-',disabled=True,checkbox_color='red')],
[sg.Combo(['3','5','7'],'3',key='-Combo1-',background_color='white',
size=(15,1),enable_events=True)],
[sg.Text('操作结果:',k='-TEXT1-')],
[sg.Exit()],
]
# 窗体显示
window = sg.Window('PySimpleGUI Elements 测试', layout)
# 消息循环
while True:
event, values = window.read(timeout=100)
# print(event,values)
if event == 'Exit' or event == sg.WIN_CLOSED:
break
str = ""
if values['-Radio1-']:
str = 'Radio1选中'
elif values['-Radio2-']:
str = str + 'Radio2选中'
if values['-CHECKBOX1-']:
str = str + 'CheckBox1选中'
if event == '-Combo1-':
str = str + values['-Combo1-']
window['-TEXT1-'].update(str)
window.close()
效果:
继PySimpleGUI之后,我们来看看PyQt,这是一个功能更为强大的Python GUI库,它允许开发者创建复杂且具有高度定制性的用户界面。PyQt的强大之处不仅在于它的广泛的功能集,还包括其槽函数机制和QSS(Qt样式表)的实现能力。
PyQt的一个核心特性是其信号和槽机制,它允许对象之间进行通信。以下是一个简单的PyQt程序,展示了如何通过槽函数响应按钮点击事件:
import sys
from PyQt6.QtWidgets import (
QApplication,
QWidget,
QPushButton,
QVBoxLayout
)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# set the window title
self.setWindowTitle('Qt Signals & Slots')
# create a button widget and connect its clicked signal to a method
button = QPushButton('Click me')
button.clicked.connect(self.button_clicked)
# place the button on window using a vertical box layout
layout = QVBoxLayout()
self.setLayout(layout)
layout.addWidget(button)
# show the window
self.show()
def button_clicked(self):
print('clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
这个例子展示了一个按钮,当点击时,会在控制台显示“clicked”消息。
QSS是PyQt的另一个强大特性,它类似于CSS,可以让开发者以声明性的方式定制UI组件的外观。以下是一个使用QSS定制PyQt应用外观的示例:
import sys
from PyQt6.QtWidgets import (
QApplication, QWidget, QPushButton,
QGridLayout, QLabel, QLineEdit
)
class Window(QWidget):
def __init__(self):
super().__init__()
layout = QGridLayout()
self.setLayout(layout)
self.setWindowTitle("Login Page")
title = QLabel("Login Form with CSS Stylesheets")
user = QLabel("Username: ")
pwd = QLabel("Password: ")
input1 = QLineEdit()
input2 = QLineEdit()
button1 = QPushButton("Register")
button2 = QPushButton("Login")
layout.addWidget(title, 0, 0, 1, 3)
layout.addWidget(user, 1, 0)
layout.addWidget(pwd, 2, 0)
layout.addWidget(input1, 1, 1, 1, 2)
layout.addWidget(input2, 2, 1, 1, 2)
layout.addWidget(button1, 3, 1)
layout.addWidget(button2, 3, 2)
app = QApplication(sys.argv)
window = Window()
app.setStyleSheet("""
QWidget {
background-color: green;
color: white;
}
QPushButton {
font-size: 16px;
background-color: darkgreen;
}
QLineEdit {
background-color: white;
color: black;
}
""")
window.show()
sys.exit(app.exec())
这个例子创建了主题界面,通过QSS定制了窗口、按钮和输入框的样式。让我们看到了PyQt在qss加持下的无限可能性:
这两个例子表明,PyQt不仅提供了广泛的功能,还能通过其槽函数和QSS机制,允许开发者创建出既复杂又具有个性化的用户界面。与PySimpleGUI相比,PyQt提供了更深层次的定制能力,适合需要高度定制化的复杂应用程序。
Gradio是一个强大的Python库,它为机器学习应用提供了一种简单直观的方式来创建交互式用户界面。这个库的核心优势在于其简单性和灵活性,使得开发者可以专注于模型的核心逻辑,而将用户界面的复杂性交给Gradio处理。以下是Gradio的一些关键特点:
简单易用:Gradio旨在简化用户界面的创建过程,抽象掉许多复杂性。
支持多种输入输出类型:支持文本、图片、音频和视频等多种输入类型,以及文本、图片和图表等多种输出类型。
与主流深度学习框架兼容:能与TensorFlow、PyTorch和scikit-learn等框架无缝集成。
实时更新:提供实时更新功能,使模型能够在用户交互时立即做出预测。
交互性和定制化:允许开发者为模型添加交互性,并定制界面外观和行为。
可伸缩性和性能:能够有效处理并发请求,适用于小规模和大规模部署。
社区和开源:得益于活跃的开源社区,提供丰富的教程、文档和示例。
示例:
import gradio as gr
# 定义一个问候函数,接收一个名字作为输入,返回一个带有问候语的文本输出
def greet(name):
return "你好," + name + "!"
# 创建一个Gradio界面,将greet函数作为输入和输出函数传递给它
iface = gr.Interface(fn=greet, inputs="text", outputs="text")
# 启动Gradio应用程序
iface.launch()
效果:
大名鼎鼎的Stable Diffusion Web UI 即是基于Gradio开发,可见其功能和效率都有保证:
另一个类似的库Streamlit, 同样有不错的体验,但体验下来在反应速度上可能略逊一筹。
补充一点关于Gradio的重要功能:通过设置share=True
,Gradio允许用户一键发布应用。这意味着您只需在Gradio界面对象创建时加入这个参数,就可以立即将您的机器学习模型部署为一个可通过互联网访问的应用程序。这个功能极大地简化了从原型到可共享应用的过程,使得开发者可以轻松地与他人分享他们的工作成果。
例如,在之前的代码中,您可以简单地通过添加share=True
来启用此功能:
# Launch the Gradio interface with sharing enabled
iface.launch(share=True)
这样,当您运行应用时,Gradio会提供一个URL,通过这个URL,其他人可以访问并与您的模型交互。
NiceGUI,被称为python GUI 编程的终极选择,确实是有一定道理的,因为它是真正基于前端最新的理念打造纯python解决方案,尤其是基于vue数据绑定和css等样式支持,从原理上决定了其强大和灵活性,并且通过python封装后,使用难度降低了几个数量级。
https://nicegui.io/ (基于NiceGUI本身开发的官网)
NiceGUI是一个基于Python的Web UI框架,旨在简化前端应用的开发。该框架的UI元素基于Vue和Quasar,提供了丰富的、现成可用的元素,适用于从简短脚本到仪表板,再到完整的机器学习网站应用程序。NiceGUI的核心特性包括:
基于Vue和Quasar的UI元素:这提供了强大的交互能力和现代化的Web特性,使其成为更广泛Web开发的理想选择。
样式定制:NiceGUI支持使用CSS、Tailwind和Quasar进行样式定制,允许开发者轻松定制页面和布局。
丰富的GUI元素:内置了按钮、标签、复选框、滑块、开关等多种现成的GUI元素。
数据绑定:支持轻松的数据绑定,增强了用户界面的动态交互性。
内置计时器:用于数据的实时刷新。
3D场景和图表的渲染:能够渲染3D场景和图表,显示图片和视频,增强了视觉效果和用户体验。
NiceGUI利用Vue的现代Web特性和易用性,结合Python的强大后端处理能力,为开发者提供了一个强大的工具,用于快速、高效地开发复杂的Web应用程序。
from nicegui import ui
from nicegui.events import ValueChangeEventArguments
def show(event: ValueChangeEventArguments):
name = type(event.sender).__name__
ui.notify(f'{name}: {event.value}')
ui.button('Button', on_click=lambda: ui.notify('Click'))
with ui.row():
ui.checkbox('Checkbox', on_change=show)
ui.switch('Switch', on_change=show)
ui.radio(['A', 'B', 'C'], value='A', on_change=show).props('inline')
with ui.row():
ui.input('Text input', on_change=show)
ui.select(['One', 'Two'], value='One', on_change=show)
ui.link('And many more...', '/documentation').classes('mt-8')
ui.run()