8

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

最近在想python的内置ctypes模块。从理论上讲,可以创建一个纯 python GUI 库,用于ctypesWindows(windll.user32.CreateWindowEx等)、MacOS 上的本机 pyObjC 和 gnome / kde 上的 pyGTK / pyQt。有这样的图书馆吗?如果不是,您认为这个想法有什么问题?

4

9 回答 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,但重命名为 Ttk(用于“主题 Tk”)被添加到 Tcl/Tck 版本 8.5 中。”

于 2009-06-24T13:48:15.933 回答
10

最少努力和最好结果的途径是了解使用现有的 GUI 库部署应用程序需要什么。

于 2009-06-24T11:14:16.663 回答
8

Tkinter 是 python 标准发行版的一部分,默认安装。期望在首先有图形显示的所有 python 安装中找到它。

于 2009-06-24T11:45:45.697 回答
6

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

于 2009-06-24T13:15:55.733 回答
5

主要的问题是它正在重新发明已经由 GTK、Tk、Wx、QT 等制造商完成的轮子。虽然纯 python GUI 在技术上是可行的,并且诸如anygui之类的项目确实尝试了类似的东西,但这样做的收获相对较小。

本机工具包还将更好地覆盖底层平台(本机对话框等)之间的差异。这意味着这些工具包允许您编写一个可移植的应用程序,该应用程序几乎不需要任何特定于平台的代码——其中大部分是由底层工具包抽象的。

Windows 上的 py2exe 和任何 linux 方法等分发机制允许您将 DLL 与应用程序捆绑在一起,因此您可以制作一个安装程序,将它需要的任何本机组件放置到位。但是,实际上并没有通用的跨平台方法来执行此操作,因此您需要为每个平台维护单独的安装程序。

于 2009-06-24T13:24:50.537 回答
4

一方面,所有这些库都使用不同的抽象,因此任何与它们一起工作的东西都可能最终支持一组最小公分母的功能,或者做大量工作以充分利用每一个。

于 2009-06-24T11:18:35.033 回答
4

不太清楚你所说的“重量级”是什么意思。

wx 在每个平台上都使用原生控件,并且在 Python 中使用起来和我想象的一样容易;毕竟,GUI API 很复杂,因为 GUI 会变得复杂。

我认为 wx 对于构建窗口所需的努力和屏幕上显示的内容的质量来说非常棒。我认为你不可能自己推出更好的东西。

于 2009-06-24T11:36:05.030 回答
2

我认为这与不发明轮子有关。它会起作用,但你为什么要这样做呢?您提到的所有 GUI 库都是稳定的,或多或少是防弹的。

我可以想象有一些实验实现了一个纯 python 库。但我从来没有见过一个。关于 GUI 的一切都是艰苦的工作,纯粹的 Python 库不会有这么多的受众。

于 2009-06-24T11:08:56.457 回答
1

tkinter 周围的轻量级包装器怎么样,这样它就不需要大量设置? PySimpleGUI建立在 tkinter 之上,这意味着它可以在 tkinter 运行的任何地方运行。

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

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

在此处输入图像描述

生成它的代码在最后。它可能看起来像很多代码,但仅此而已。做同样的事情需要一页又一页的 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()
于 2018-09-03T23:20:53.087 回答