纯Python GUI库?

8

Python有很多GUI库:tkinter、wxWidgets、pyGTK等。但是所有这些GUI都需要安装,而且非常庞大,因此部署依赖于这些GUI库的最终用户GUI python应用程序有点复杂。

最近,我考虑了Python内置的ctypes模块。从理论上讲,可以创建一个纯Python GUI库,该库将在Windows上使用ctypes(例如windll.user32.CreateWindowEx),在MacOS上使用本地pyObjC,在gnome / kde上使用pyGTK / pyQt。这样的库存在吗?如果不存在,您认为这个想法有什么问题?


3
Tkinter不需要单独安装,它是Python标准发行版的一部分。 - Bryan Oakley
2
仅限于Windows和macOS操作系统。需要在Ubuntu等系统上安装。 - grigoryvp
你的意思是“用Python重写wx”吗?为什么你认为这样做会比已经完成的更好呢? - nosklo
1
不需要安装,可作为脚本的一部分提供。 - grigoryvp
如果可移植性是优先考虑的因素,那么捆绑库(以某种方式)或使用 Py2Exe 构建独立可执行文件几乎肯定比从头开始重写整个 GUI 框架更容易。 - StockB
9个回答

11

从Python 2.7和3.1开始,Tk外观会变得更加出色。

http://docs.python.org/dev/whatsnew/2.7.html#ttk-themed-widgets-for-tk

"Tcl/Tk 8.5包含一组主题小部件,重新实现了基本的Tk小部件,但外观可以更自定义,因此可以更接近本地平台的小部件。此小部件集最初称为Tile,但在添加到Tcl/Tck 8.5版本时改名为Ttk(即“主题化Tk”)."


10

最省力、最好的结果的路径是学习如何使用现有的GUI库来部署应用程序。


1
+1:"相当沉重"是夸张的说法。在大多数情况下,构建GUI需要所有这些内容。 - S.Lott

8

Tkinter是Python标准发行版的一部分,并且默认安装。通常情况下,只要有图形显示,就可以在所有Python安装中找到它。


1
如果你需要更多的小部件,TKinter有一些轻量级的插件和附加组件可以显著改善工具包。但是,界面仍然很丑... - Bite code
6
“ui is ugly”的评论主要只适用于旧版本的Tkinter。现代Tk在支持的平台上使用本地小部件。如今丑陋的Tkinter应用程序主要反映了程序员的技能,而不是工具包的限制。有关此讨论的更多信息,请参见https://dev59.com/EHRC5IYBdhLWcg3wSu97。 - Bryan Oakley
1
Tkinter默认只在Windows和macOS上安装。在Ubuntu等其他操作系统上需要手动安装。 - grigoryvp
1
澄清一下。在默认配置中,Python将尝试使用tk(如果可用)。除主线之外的二进制发行版,例如Ubuntu或red-hat或其他可能遵循不同的策略。最常见的是基于其外部依赖项拆分标准Python库,这样您就不必支付数十或数百兆字节的库代码,而实际上您不会使用。 - SingleNegationElimination
1
我猜我是那些记得丑陋的旧TK的人之一。也许现在我只是觉得TK的内部很丑。也许我只是一个偏执狂,需要再看一眼。我从来没有明白为什么Python始终被绑定了最不友好的GUI工具包。 - Warren P
2
可能 Python 选择 Tk 的原因是当时没有其他成熟的跨平台工具包。Tk 可以追溯到 1990 年(http://www.tcl.tk/about/history.html),比任何合理的替代品都要早很多年。此外,与其他早期工具包不同,它旨在嵌入解释性语言中使用,因此将其移植到 Python 中比绑定另一个面向 C 的工具包要容易得多。 - SingleNegationElimination

6

“纯Python GUI库”的概念是错误的,因为最终你将使用系统级调用和小部件,可能是通过ctypes实现的,但这并不改变一个事实,如果你开始实现你的想法,你最终会变成wxPython。”


5
主要问题是它在重复发明已经被GTK、Tk、Wx、QT等制造商完成的轮子。虽然纯Python GUI在技术上是可行的,anygui等项目尝试了类似的事情,但做这件事情所得到的收益相对较少。
本地工具包也能更好地覆盖底层平台之间的差异(本地对话框等)。这意味着工具包可以让你编写一个可移植的应用程序,几乎不需要任何特定于平台的代码——大部分都是由底层工具包抽象出来的。
像Windows上的py2exe和任何Linux方法这样的分发机制允许您将DLL与应用程序捆绑在一起,因此您可以创建一个安装程序,将其需要的任何本地组件放置在适当的位置。然而,实际上并没有一种通用的跨平台方式来做到这一点,因此您需要为每个平台维护单独的安装程序。

4

首先,所有这些库都使用不同的抽象,因此任何能够与它们一起使用的东西都很可能会支持最小公共功能集,或者需要做很多工作才能充分利用每个库。


4

我不太确定您所说的“heavyweight”是什么意思。

wx在每个平台上都使用本机控件,并且在Python中使用起来非常容易。毕竟,GUI API之所以复杂,是因为GUI可以变得复杂。

我认为对于构建窗口所需的工作量和屏幕上显示的质量而言,wx非常好。 我不认为您很可能会自己开发出更好的东西。


2

我认为这是关于不要重复造轮子。虽然它可以工作,但为什么要这样做呢?你提到的所有GUI库都很稳定,基本上是经过了严格测试的。

我可以想象,可能会有一些尝试实现纯Python库的实验。但我从未见过这样的库。关于GUI的一切都是艰苦的工作,而一个纯Python库不会有如此庞大的受众群体。


1

你觉得使用一个轻量级的tkinter包装器如何,这样就不需要太多的设置了?PySimpleGUI是建立在tkinter之上的,这意味着它可以在任何支持tkinter的地方运行。

与使用tkinter相比,它的优点在于所需代码的数量。 PySimpleGUI程序往往非常紧凑。

以下是一个示例,展示了使用许多可用小部件的自定义布局。

enter image description here

生成它的代码在结尾处。看起来可能是很多代码,但就是这样。要用tkinter做同样的事情需要写很多很多页的代码。
import PySimpleGUI as sg

sg.ChangeLookAndFeel('GreenTan')
# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
            ['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
            ['&Help', '&About...'], ]
# ------ Column Definition ------ #
column1 = [[sg.Text('Column 1', background_color='lightblue', justification='center', size=(10, 1))],
           [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')],
           [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2')],
           [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]]

layout = [
    [sg.Menu(menu_def, tearoff=True)],
    [sg.Text('(Almost) All widgets in one Window!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
    [sg.Text('Here is some text.... and a place to enter text')],
    [sg.InputText('This is my text')],
    [sg.Frame(layout=[
    [sg.Checkbox('Checkbox', size=(10,1)),  sg.Checkbox('My second checkbox!', default=True)],
    [sg.Radio('My first Radio!     ', "RADIO1", default=True, size=(10,1)), sg.Radio('My second Radio!', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
    [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),
     sg.Multiline(default_text='A second multi-line', size=(35, 3))],
    [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 1)),
     sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],
    [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))],
    [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
     sg.Frame('Labelled Group',[[
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25),
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75),
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10),
     sg.Column(column1, background_color='lightblue')]])],
    [sg.Text('_' * 80)],
    [sg.Text('Choose A Folder', size=(35, 1))],
    [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'),
     sg.InputText('Default Folder'), sg.FolderBrowse()],
    [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]]

window = sg.Window('Everything bagel', default_element_size=(40, 1), grab_anywhere=False).Layout(layout)
button, values = window.Read()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接