首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在没有高级库的情况下用Python创建GUI?

如何在没有高级库的情况下用Python创建GUI?
EN

Stack Overflow用户
提问于 2022-11-07 11:55:55
回答 2查看 88关注 0票数 1

我想要创建一个GUI,没有Tkinter或任何其他库(最好是在Windows和CPython中)。

基本上,如果您进入Python及其库的文件,就可以找到库的函数。一个例子是randint库的random函数:

代码语言:javascript
复制
def randint(self, a, b):
    """Return random integer in range [a, b], including both end points.
    """
    
    return self.randrange(a, b+1)

现在,不用使用randint,我只需键入函数在我的程序中所做的事情。

这意味着Tkinter必须有类似的东西来创建GUI (尽管我找不到Tkinter的文件),这是一个虚构的示例:

代码语言:javascript
复制
def Tk(self, ...):
    """...
    """
    
    ...
    
    (simple library like "os" or "sys").create_window(...)
    
    ...

我希望使用create_window函数而不是Tkinter,我想要一些关于这些函数的文档。

我听说Tkinter直接与一些C类通信,如果是这样的话,我想知道如何直接从我的程序中进行,而不是使用Tkinter。我不在乎它是否更复杂、更不必要、更非pythonic,或者其他什么,我只需要创建一个GUI,而不需要任何GUI库。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-07 13:24:41

一个令人钦佩的目标!如果您这样做,我希望这是为了您自己的兴趣和开发,而不是任何严肃的应用程序,因为像tkinter这样的库是抽象的抽象,并且为您做了大量乏味的样板工作。在真实世界中,通常不适合自己做这样的工作,因为你会重犯几十年前Tcl开发人员犯的很多错误。然而,看看你如何去做这件事通常是很有趣的。

实际上,tkinter的源代码可以在GitHub上使用,您可以亲自阅读它。在CPython中,tkinter被实现为一系列python绑定这里和C模块这里。所有这些都是Tcl/Tk的接口,它们本身就是开源工具。它是几千行C和Python的代码,所以我恐怕不能很容易地总结它是如何工作的,但是在Windows上,它归结为对Windows的直接调用,函数包括RegisterClassWCreateWindowW

如果您愿意,可以使用ctypes直接从您自己的Python代码中与这些API进行接口--当然,这仍然是一个库,但是您将在一个比Tcl接口更基本的层次上进行交互。这个问题通过下面的代码片段提供了一个简单的起点:

代码语言:javascript
复制
import ctypes  # An included library with Python install.
ctypes.windll.user32.MessageBoxA(0, "Your text", "Your title", 1)

注意:根据这个问题的日期,它可能是一个Python2答案,所以在一个现代的ctypes.windll.user32.MessageBoxA(0, b"Your text", b"Your title", 1)实现中,调用可能是ctypes.windll.user32.MessageBoxA(0, b"Your text", b"Your title", 1)--我不运行ctypes.windll.user32.MessageBoxA(0, b"Your text", b"Your title", 1),所以我不知道。

您需要调用的函数都在微软网站的相关网页上有了详细的文档,所以您需要查找的是使用Windows进行图形编程的良好教程,然后将其转换到Python接口中。我自己也不能担保,但本教程看上去没问题。

这可能是因为你想要比这更低的级别,看看Windows在调用像MessageBoxA这样的函数时实际做了什么。我也很好奇,但是微软选择了保持API的封闭源代码,所以我们无法查看这个函数的源代码。如果您一定要知道,您将需要使用反向工程工具包来打开实现它的dll文件。根据你的管辖范围,这可能违反了当地的版权法,所以这个答案就到此为止。

票数 1
EN

Stack Overflow用户

发布于 2022-11-07 12:17:34

好吧..。这太复杂了,在windows上创建和操作应用程序的所有函数都是用C编写的,存储在windows 例如,如win32文档中所述,C语言就是这样做的上的例如,如win32文档中所述,C语言就是这样做的上的

这个程序需要通过C型转换成python,它将从python内部调用C代码,您将在python中编写C代码,这几乎是您用C编写的代码的4倍,它的工作速度将慢100倍,您必须在C、python和win32 api方面有很好的经验才能获得有用的应用程序.对于很多高级开发人员来说,这是可以提高的。

所以轨道是:

学习C ->学习win32 api ->学习python ->学习ctype ->学习python ABI ->制作一个简单的hello程序

用C编写代码更容易(也更快),然后将代码包装到python模块中,就像tkinter和wxwidget、QT以及几乎所有其他框架中所做的那样。

这是在32位python中如何操作的要点,但是它不能在64位python上工作,因为变量的类型在32位到64位的windows dlls之间发生了变化。https://gist.github.com/mouseroot/6128651

这是64位系统的另一个要点,它解决了类型问题。https://gist.github.com/syegulalp/7cf217677e893881a18d10020f2966e4

代码语言:javascript
复制
# Adapted for Python 3.6 + 64-bit Windows

from ctypes import *
from ctypes.wintypes import *

WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)

WS_EX_APPWINDOW = 0x40000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_CAPTION = 0xc00000

SW_SHOWNORMAL = 1
SW_SHOW = 5

CS_HREDRAW = 2
CS_VREDRAW = 1

CW_USEDEFAULT = 0x80000000

WM_DESTROY = 2

WHITE_BRUSH = 0


class WNDCLASSEX(Structure):
    _fields_ = [("cbSize", c_uint),
                ("style", c_uint),
                ("lpfnWndProc", WNDPROCTYPE),
                ("cbClsExtra", c_int),
                ("cbWndExtra", c_int),
                ("hInstance", HANDLE),
                ("hIcon", HANDLE),
                ("hCursor", HANDLE),
                ("hBrush", HANDLE),
                ("lpszMenuName", LPCWSTR),
                ("lpszClassName", LPCWSTR),
                ("hIconSm", HANDLE)]


user32 = ctypes.WinDLL('user32', use_last_error=True)
user32.DefWindowProcW.argtypes = [HWND, c_uint, WPARAM, LPARAM]


def PyWndProcedure(hWnd, Msg, wParam, lParam):
    if Msg == WM_DESTROY:
        user32.PostQuitMessage(0)
        return 0
    return user32.DefWindowProcW(hWnd, Msg, wParam, lParam)


def main():
    WndProc = WNDPROCTYPE(PyWndProcedure)
    hInst = windll.kernel32.GetModuleHandleW(0)
    wclassName = u'My Python Win32 Class'
    wname = u'My test window'

    wndClass = WNDCLASSEX()
    wndClass.cbSize = sizeof(WNDCLASSEX)
    wndClass.style = CS_HREDRAW | CS_VREDRAW
    wndClass.lpfnWndProc = WndProc
    wndClass.cbClsExtra = 0
    wndClass.cbWndExtra = 0
    wndClass.hInstance = hInst
    wndClass.hIcon = 0
    wndClass.hCursor = 0
    wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH)
    wndClass.lpszMenuName = 0
    wndClass.lpszClassName = wclassName
    wndClass.hIconSm = 0

    regRes = windll.user32.RegisterClassExW(byref(wndClass))

    hWnd = windll.user32.CreateWindowExW(
        0, wclassName, wname,
        WS_OVERLAPPEDWINDOW | WS_CAPTION,
        CW_USEDEFAULT, CW_USEDEFAULT,
        300, 300, 0, 0, hInst, 0)

    if not hWnd:
        print('Failed to create window')
        exit(0)
    print('ShowWindow', windll.user32.ShowWindow(hWnd, SW_SHOW))
    print('UpdateWindow', windll.user32.UpdateWindow(hWnd))

    msg = MSG()
    lpmsg = pointer(msg)

    print('Entering message loop')
    while windll.user32.GetMessageA(lpmsg, 0, 0, 0) != 0:
        windll.user32.TranslateMessage(lpmsg)
        windll.user32.DispatchMessageA(lpmsg)

    print('done.')


if __name__ == "__main__":
    print("Win32 Application in python")
    main()

在您的代码过于混乱和缓慢之后,您的代码只能在您的操作系统上工作,所以要将它移植到另一个操作系统仍然需要承受10倍的麻烦,所以最好使用库来处理这些东西。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74346199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档