这是一个关于GUI如何绘制,以及是怎么绘制的问题。
图形用户界面,英文为Graphical User Interface,简写为GUI。
众说纷纭,有人列举了许多实现GUI界面的类库,例如C++的QT、MFC,Python的Tkinter等。但是这些类库是如何显示的呢?归根结底,它们都是在计算机屏幕上显示信息,那么计算机是如何绘制屏幕的呢?
计算机把内存中的内容输出到屏幕上,这个操作叫渲染。现代计算机有一个专门的关键部分,用于完成渲染工作,它就是GPU(Graphics Processing Unit)。
我们在屏幕上看到的动画或视频,是单一的一帧一帧画面重复绘制的结果。每一帧渲染主要分为六步:
alpha
值。完全理解这六个步骤稍微有点困难。大概可以这么理解:CPU送给GPU需要渲染的画面数据,是立体的,就像重叠的窗口一样,是一个立体、有重叠和覆盖性质的内容;GPU收到这些数据以后,先建点连线,构建3D图形,然后在屏幕上投影,将3D图形转化为2D图形,最后裁掉屏幕以外的部分,将像素绘制出来。
GPU本质上绘制的是像素。屏幕上每个像素可以看作是一个带颜色控制的小灯泡,GPU频繁控制这些灯泡的明灭暗淡,以此完成复杂的画面渲染。
既然屏幕绘制工作是GPU完成的,那么在系统里,软件是如何调用GPU的呢?
无论是什么系统,软件是不能直接控制GPU的。软件向系统发出控制请求,系统通过设备驱动控制特定的计算机设备。驱动全称是设备驱动程序,是添加到操作系统中的特殊程序。驱动中包含有关硬件设备信息,以及设备控制指令。厂商生产了硬件设备,只有厂商自己发布的设备驱动才知道如何控制设备。
计算机或其它程序软件没有办法直接控制某个驱动,只有设备驱动可以。驱动在计算机中的地位,就好比归附的山寨军队的山大王。要指挥山寨,必须通过山大王发号施令,直接安排是不好使的。
图源:snappygoat.com
Windows、Mac和Linux,是最常见的操作系统。这些系统的实现是有差异的,显卡之间也有差异,如何消减软件间接调用GPU的差异呢?为此程序员发明了OpenGL。
图源:www.kissclipart.com
OpenGL是Open Computer Graphics的简写,是图形学研究人员和程序员以图形学的渲染理论为基础,实现的底层图形算法库。OpenGL封装了不同操作和不同显式驱动之间的差异,让不同软件可以使用一套统一的接口控制屏幕绘制。用稍为正式语句表达,OpenGL是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API),由近350个不同的函数组成。这些函数并不是天生被支持的,OpenGL对显卡的支持是依赖于版本更新。OpenGL像一个适配的插头,处在软件和系统之间。
OpenGL作为一个开放图形库,并不是唯一的。微软的DirectX与它具有相似的功能。
在屏幕上绘制图形和文本的原理是相同的,本质上计算机没有文本,文本也是一个个字符编码对应的字符图像。计算机绘制文本,是拿字符编码先在字体库中找到对应的矢量图形或位图图形,再将图形绘制到屏幕上。
编程语言在屏幕上完成绘制,很少有直接调用显卡驱动的,一般都是通过一个通用的图形类库,间接调用一个或几个图形驱动库(OpenGL或DirectX)完成的。不同语言有不同的图形类库。
Filament:https://github.com/google/filament
Filament是谷歌推出的,开源的,一个实时的基于物理的渲染引擎,适用于Android, iOS, Linux, macOS, Windows和WebGL(浏览器)。它被设计得尽可能小,在Android上尽可能高效。Filament底层引用了OpenGL。
下面它的渲染效果:
图源:https://github.com/google/filament
CEF:https://github.com/chromiumembedded/cef
CEF是Chromium Embedded Framework的简写,它可以将一个浏览器内核嵌入到软件中。
Glfw:https://github.com/glfw/glfw
GLFW是一个开源的,跨平台GUI类库。它提供了简单的方法,用于创建窗口、读取输入、处理事件等。
Gephi:https://github.com/gephi/gephi
Gephi是一个用于可视化和处理大型图形的开源平台,它可以在Windows、Mac OS X和Linux上运行。
图源:https://github.com/gephi/gephi
G3N:https://github.com/g3n/engine
G3N是一个用Go语言编写的跨平台的OpenGL 3D游戏引擎。
但是这些类库太过庞大复杂,对于我们创建简单的UI界面没有实质性的帮助。我们需要使用UI组件库,帮助我们创建常见的UI,例如一个按钮,一个下拉框,一个窗体等。
Nuklear ⭐️⭐️⭐️
https://github.com/vurtun/nuklear
https://github.com/therecipe/qt:Go语言版本的QT类库。
Tkinter: Tkinter 模块是 Python 的标准 Tk GUI 工具包的接口。Tkinter的窗体及按钮效果:
图源:https://www.runoob.com/
wxPython
wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库。
PySimpleGUI ⭐️⭐️⭐️
https://github.com/PySimpleGUI/PySimpleGUI
代码:
import PySimpleGUI as sg # Part 1 - The import
# Define the window's contents
layout = [ [sg.Text("What's your name?")], # Part 2 - The Layout
[sg.Input()],
[sg.Button('Ok')] ]
# Create the window
window = sg.Window('Window Title', layout) # Part 3 - Window Defintion
# Display and interact with the Window
event, values = window.read() # Part 4 - Event loop or Window.read call
# Do something with the information gathered
print('Hello', values[0], "! Thanks for trying PySimpleGUI")
# Finish up by removing from the screen
window.close() # Part 5 - Close the Window
效果:
https://dotnet.microsoft.com/apps/aspnet
微软自搞了一套同时支持窗体、HTML页面、终端应用开发的.Net框架。使用VS可以实现拖拉式UI编程。
Elements C++ GUI library ⭐️⭐️⭐️
https://github.com/cycfi/elements
ImGui
https://github.com/ocornut/imgui
代码:
ImGui::Text("Hello, world %d", 123);
if (ImGui::Button("Save"))
MySaveFunction();
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
效果:
浏览器在系统中是一类特殊的软件,因为它依赖于浏览器引擎,可以解析执行js & html代码。有三个主流的UI类库,可以帮助我们在浏览器宿主环境中开发界面:
https://developers.weixin.qq.com/miniprogram/dev/component/
微信小程序本质是基于浏览器内核渲染的,它的WXML标签是微信团队自创的。在微信小程序中,主要使用js语言。官方文档上提供了完备的组件及API,实现常见UI功能都比较容易。
除了官方组件,微信团队还提供了一个WeUI扩展组件库。
最后总结一下,在计算机中,CPU负责计算,渲染是通过GPU完成的,操作系统(Mac、Windows and Linux)通过OpenGL或DirectX底层图形库实现对GPU的控制。不同编程语言,通过对OpenGL等底层图形库的封装,都有一些具体的图形引擎库,一般这些引擎库也是游戏引擎库。与此同时,为了方便业务应用开发,不同编程语言也实现了不同的UI组件库,默认实现了像按钮、下拉框、窗体等控件,可以直接使用。
浏览器是一类特殊的系统软件,它可以解析执行js、html标签代码。通过html、css3、js可以快速开发出好看易用的页面。也有UI组件库可以帮助程序员更快地完成开发。微信小程序与之类似。
如果程序员想以代码的形式开发GUI界面,依据语言不同,有不同的选择:
但是,每个语言都有自己擅长做的事情,后端语言写UI一般都是不太合适的。像Python语言,适合做数据抓取、分析,UI并非其长项;像Go语言,适合开发高并发、高吞吐的后端数据应用,UI并非其长项;像C语言,当下适合做嵌入式、物联网开发,UI也并非其长项;像C++语言,传统类库丰富,适合维护旧系统老软件,直接写UI也并非其长项,C++写界面必须依据业务需求基于某个成熟的UI组件库完成。
当下写PC软件,一种流行的做法是基于Electron框架开发。Electron是一个浏览器框架,可以将浏览器嵌入到软件中,使用Html & CSS3 & JS这些成熟的页面技术开发UI界面,同时也可以调用系统资源,做一些js不能做的事情。
学习反馈要及时,初学者学习编程,以前最好的入门语言是AS3,现在最好的入门技术是微信小程序。微信小程序的主要编程语言是js,有完整的UI组件,和丰富的平台接口,入门门槛低,非常合适初学者入门学习。
但是js这门语言太过简单,单线程,不涉及线程问题、内存问题等复杂问题。在学习微信小程序开发的同时,最好同时学一门后端语言,Go语言是最好的选择。
开发GUI应用,最方便的是使用前端技术(Vue、React或微信小程序都可以)。依赖CSS3丰富的表现能力,加上热加载技术,UI修改及时呈现,特别方便程序员开发出漂亮的UI界面。
---
我讲明白没有,欢迎留言讨论。