窗口系统与图形绘制接口

news2024/10/10 15:43:31

个人博客:Sekyoro的博客小屋
个人网站:Proanimer的个人网站

当我们想要进行底层图形应用(GUI)开发时,往往需要用到窗口系统和图形库,这里简单介绍一下

视窗系统(window system)与通信协议

下面内容主要针对Unix-like操作系统

视窗系统是以使用视窗作为主要特征之一的图形用户接口的构成组件.更为明确地说,它是桌面环境的构成组件.视窗系统支撑著窗口管理器的实现(implementation);视窗系统为“图像硬件(graphics hardware)、指向设备(pointing devices)提供基本支持.绘制鼠标光标,一般也与视窗系统相关.

X Window System(X11)

X窗口系统是一种以位图方式显示的软件窗口系统,X窗口系统通过软件工具及架构协议来建立操作系统所用的图形用户界面,此后则逐渐扩展适用到各形各色的其他操作系统上.

在X11的设计中,应用程序和显示器不必在同一台计算机上,这一点并不明显.在开发X时,X server运行在工作站上,而用户在具有更强处理能力的远程计算机上运行应用程序是很常见的.

X Window核心协议

X Window 核心协议是X窗口系统的基础协议,它是一个以位图显示的网络化视窗系统,用来在Unix、类Unix和其它操作系统上建立用户图形界面.X Window 系统基于主从式模型:单一服务器控管硬件的输出入,如屏幕、键盘和鼠标;所有的应用程序都被视作客户端,用户之间透过服务器来交互.

交互部分由X Window核心协议来管理.还有其它与X窗口系统有关的协议,有的建立在X Window核心协议之上的,有的是独立的协议.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

X server接受来自键盘,鼠标,显示器的输入,并将这些请求发送给client.

so1jXbe2d2Vvx917pbA5Cjw

X server

与大多数早期的显示协议不同,X是专门设计用于网络连接,而不是用于集成或附加的显示设备.X具有网络透明性,这意味着在网络上某处的计算机(例如Internet)上运行的X程序可以在网络上其他计算机上运行的X服务器上显示其用户界面.

X服务器通常为X客户机提供图形资源和键盘/鼠标事件,这意味着X服务器通常在人类用户面前的计算机上运行,而X客户机应用程序在网络上的任何地方运行,并与用户的计算机通信,请求图形内容的呈现,并从包括键盘和鼠标在内的输入设备接收事件

Xlib与其他的客户端程序

大部分的客户端程序借由 Xlib 客户端程序库与服务器交流.特别是客户端大多使用 Xaw、Motif、GTK+、Qt 之类使用到 Xlib 的程序库,方便和服务器交互.

XLib是X Window System的核心库,它提供了与窗口系统交互的基本功能,如创建窗口、处理事件和绘制图形

Xlib是一种X Window System协议的客户端,以C语言撰写.其功能是与X server沟通.这样的功能可以让程序人员撰写程序时,

#include <X11/Xlib.h>
#include <unistd.h>

int main()
{
    Display* MainDisplay = XOpenDisplay(0);
    Window RootWindow = XDefaultRootWindow(MainDisplay);
    
    Window MainWindow = XCreateSimpleWindow(MainDisplay, RootWindow, 0, 0, 800, 600, 0, 0, 0x00aade87);
    XMapWindow(MainDisplay, MainWindow);
    XFlush(MainDisplay);

    for(;;) { sleep(1); }
}
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>

typedef struct {
    int X;
    int Y;
    int Width;
    int Height;
} entity;

int main()
{
    Display* MainDisplay = XOpenDisplay(0);
    Window RootWindow = XDefaultRootWindow(MainDisplay);

    int DefaultScreen = DefaultScreen(MainDisplay);
    GC Context = XDefaultGC(MainDisplay, DefaultScreen);
    
    int WindowX = 0;
    int WindowY = 0;
    int WindowWidth = 800;
    int WindowHeight = 600;
    int BorderWidth = 0;
    int WindowDepth = CopyFromParent;
    int WindowClass = CopyFromParent;
    Visual* WindowVisual = CopyFromParent;

    int AttributeValueMask = CWBackPixel | CWEventMask;
    XSetWindowAttributes WindowAttributes = {};
    WindowAttributes.background_pixel = 0xffffccaa;
    WindowAttributes.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask;

    Window MainWindow = XCreateWindow(MainDisplay, RootWindow, 
            WindowX, WindowY, WindowWidth, WindowHeight,
            BorderWidth, WindowDepth, WindowClass, WindowVisual,
            AttributeValueMask, &WindowAttributes);

    XMapWindow(MainDisplay, MainWindow);

    XStoreName(MainDisplay, MainWindow, "Moving rectangle. Use arrow keys to move.");

    Atom WM_DELETE_WINDOW = XInternAtom(MainDisplay, "WM_DELETE_WINDOW", False);
    if(!XSetWMProtocols(MainDisplay, MainWindow, &WM_DELETE_WINDOW, 1)) {
        printf("Couldn't register WM_DELETE_WINDOW property \n");
    }


    entity Box = {};
    Box.Width = 50;
    Box.Height = 80;
    Box.X = WindowWidth/2 - Box.Width/2;
    Box.Y = WindowHeight/2 - Box.Height/2;
    int StepSize = 5;

    int IsWindowOpen = 1;
    while(IsWindowOpen) {
        XEvent GeneralEvent = {};


        XNextEvent(MainDisplay, &GeneralEvent);

        switch(GeneralEvent.type) {
            case KeyPress:
            case KeyRelease:
            {
                XKeyPressedEvent *Event = (XKeyPressedEvent *)&GeneralEvent;
                if(Event->keycode == XKeysymToKeycode(MainDisplay, XK_Escape))
                {
                    IsWindowOpen = 0;
                }

                if(Event->keycode == XKeysymToKeycode(MainDisplay, XK_Down))
                {
                    Box.Y += StepSize;
                }
                else if(Event->keycode == XKeysymToKeycode(MainDisplay, XK_Up))
                {
                    Box.Y -= StepSize;
                }
                else if(Event->keycode == XKeysymToKeycode(MainDisplay, XK_Right))
                {
                    Box.X += StepSize;
                }
                else if(Event->keycode == XKeysymToKeycode(MainDisplay, XK_Left))
                {
                    Box.X -= StepSize;
                }
            } break;

            case ClientMessage:
            {
                XClientMessageEvent *Event = (XClientMessageEvent *) &GeneralEvent;
                if((Atom)Event->data.l[0] == WM_DELETE_WINDOW) {
                    XDestroyWindow(MainDisplay, MainWindow);
                    IsWindowOpen = 0;
                }
            } break;

        }

        XClearWindow(MainDisplay, MainWindow);
        XFillRectangle(MainDisplay, MainWindow, Context, Box.X, Box.Y, Box.Width, Box.Height);
    }
}
窗口管理器

窗口管理器(Window manager)是在图形用户界面中,控制窗口位置与外观的软件. 许多窗口管理器是为了桌面环境编写,与桌面环境一同发布的,例如被GNOME使用的Mutter.同时也存在不少独立的窗口管理器,如Openbox、Awesome等.

linux的窗口管理器(dwm,i3wm)以及桌面环境(比如Gnome,KDE等)往往不会直接使用xlib编写界面,而是使用其他库调用xlib,比如GTK,Qt以及cairographics.org等.

窗口管理器是一个常规的X客户机.它没有任何超级用户权限;它是X服务器允许调用一组特殊api的普通用户进程

X通过拒绝客户端对这些api的访问(如果另一个客户端当前具有访问权限),确保在任何给定点上运行的窗口管理器不超过一个.第一个尝试访问这些api的客户端总是成功的.

so1jXbe2d2Vvx917pbA5Cjw

窗口管理器通过两个X机制与它所管理的窗口进行通信:属性和事件。通信是通过X服务器进行的,而不是直接在窗口管理器和其他应用程序之间进行的。

substructure redirection

在没有窗口管理器的情况下,当一个应用程序想要对一个窗口做一些事情——移动它、调整它的大小、显示/隐藏它等等——它的请求直接由X服务器处理。但是,窗口管理器需要拦截这些请求。例如,窗口管理器可能需要知道一个新的顶层窗口已经创建并显示,以便在其周围绘制窗口装饰(例如最小化/最大化/关闭按钮)。它可能还需要知道现有的顶层窗口已被调整大小,以便重新绘制窗口装饰以重新填充.允许窗口管理器拦截此类请求的机制称为substructure redirection

假设我们有一个窗口W。如果程序M在W上注册substructure redirection,则X服务器不会执行修改W的任何直接子窗口的匹配请求。相反,X服务器将此请求重定向到程序M,程序M可以对请求执行任何操作,包括直接拒绝请求或通过、修改请求。

窗口管理器能为一个root window(是应用的top-level window的父窗口)注册substructure redirection,使得这个顶层窗口的任何直接子窗口(也就是应用的top-level窗口)发送的请求经过x server不经过修改转发到window manager,windows manager可以进行处理

sTifV_OHk9dsZi6cwbLS7qQ

reparenting

如果在没有窗口管理器的情况下运行X应用程序,则应用程序的顶层窗口将是根窗口的直接子窗口.但是,在运行窗口管理器时,应用程序的顶层窗口可能被窗口管理器重新定义;它成为由窗口管理器创建的框架窗口的子窗口,并且它本身是根窗口的直接子窗口。窗口管理器可以将其他UI元素添加到这个框架窗口中,并与应用程序的顶层窗口一起使用

Reparenting允许不同的窗口管理器绘制不同的窗口装饰,从而实现跨窗口的一致外观。然而,也有一些窗口管理器根本不reparent:这些窗口管理器称为非reparent窗口管理器。窗口管理器不希望重命名有两个原因:

  1. 如果窗口管理器不在顶层窗口周围绘制窗口装饰,那么它显然不需要重新表示它们。例如:xmonad、dwm。

  2. 合成窗口管理器并不总是需要reparent窗口

简单来说,reparent赋予了窗口管理器对其他应用程序的top-level也就是顶层窗口绘制的能力

让window manager管理了应用程序的top-level window

compositing

从窗口管理器的角度来看,top-level窗口是黑盒;它们各自管理自己的后代窗口(UI元素),可能通过GTK+或Qt这样的框架,窗口管理器无权干涉那里。

但现在,随着图形硬件计算能力增强,window manager能做的更多了

sawR1epQiKxE5bX3Cplms2A

绘制应用top-level窗口下的子元素往往如果直接由应用程序管理,那么其子元素的绘制和事件处理均通过应用发送请求到X server(中间通过window manager可能做出一些修改)

让我们花点时间思考一下如何实现像上面的Shift Switcher这样的接口。当用户触发这个接口时,我们需要:

  1. 将每个顶层窗口及其所有后代窗口(UI元素)呈现到off-screen的内存缓冲区中,而不是直接呈现给硬件。

  2. 根据设计变换(旋转,扭曲等)每个缓冲区。

  3. 将转换后的buffer与背景和我们需要显示的任何其他浮动UI元素一起合成为最终buffer

  4. 创建一个覆盖窗口,覆盖整个屏幕,并隐藏所有其他窗口

  5. 渲染最终的buffer到覆盖的窗口

​ Composite扩展提供了一种机制,请求X服务器不要将特定的窗口及其后代直接呈现给硬件,而是呈现给X服务器维护的一个特殊缓冲区,这样做不需要进行常规的裁剪和重叠计算。然后,发出请求的客户端(也就是composition window manager)可以读取和使用该缓冲区

​ 由于合成窗口管理器已经知道所有顶层窗口的大小和位置,因此在使用图形操作(例如OpenGL)合成到覆盖窗口时,只需绘制窗口装饰就很容易了,而无需创建实际的X框架窗口和reparent

另一方面,窗口管理器可能需要同时支持合成和非合成模式,以兼容较旧或不受支持的图形硬件。在这种情况下,它需要为非合成模式实现修复和框架窗口,因此使用图形操作额外实现绘制窗口装饰变得多余。这就是为什么许多其他合成窗口管理器仍然选择重命名的原因

XCB

XCB - 维基百科,自由的百科全书 (wikipedia.org)

XCB是目标在于取代Xlib,XCB 主要目标是:

  • 减轻函数库的大小与复杂度;
  • 可直接访问 X Window核心协议.

Wayland

Wayland 是在同一个主机上的 GUI 通信协议:新、简单、快速,不需要 setuid root 二进制

Wayland是一个通信协议,规定了显示服务器与其客户机之间的通信方式,而使用这个协议的显示服务器称为Wayland Compositor.它由Kristian Høgsberg于2008年发起,目标是用更简单的现代化视窗系统取代X Window System.Wayland协议的参考实现称为Weston,由Wayland项目组使用C语言开发

Wayland与X Window System的最大不同在于它规定由客户机自身负责窗口边框和装饰的绘制(应用程序直接修改显存?),并且客户机能够通过EGL以及一些Wayland特定的EGL扩展组件直接在显示内存中算绘自己的缓冲器.

窗口管理器简化成显示管理服务,专门负责算绘那些屏幕上的程序.这比X Window System中的窗口管理器要更简单、高效

以“鼠标点击按钮引发按钮更新动作”为例来说明一下Wayland和X server的区别

在X中

  1. 内核捕获鼠标点击事件并发送给X server.

  2. X server会计算该把这一事件发送给哪个窗口(事实上,窗口位置是由Compositor控制的,X server并不能够正确的计算Compositor做过特效变化之后的按钮的正确位置).

  3. 应用程序对此事件进行处理(将引发按钮更新动作).但是,在此之前它得向X server发送绘制请求.

  4. X server接收到这条绘制请求,然后把它发给视频驱动来渲染.X还计算了更新区域,并且这条“垃圾信息”发送给了Compositor.

  5. 这时,Compositor知道它必须要重新合成屏幕上的一块区域.当然,这还是要向X server发送绘制请求的.

  6. 开始绘制.但是X server还会去做一些不必要的本职工作(窗口重叠计算、窗口剪裁计算等)

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在Wayland中

  1. 内核捕获鼠标点击事件并发送给Wayland Compositor.
  2. 由于是直接发给Wayland Compositor的,所以Wayland Compositor会正确地计算出按钮的位置.同时它会把这一事件发送给按钮所在的应用程序来处理.
  3. 应用程序直接渲染,无需向Wayland Compositor请求.只需在绘制完成之后向Wayland Compositor发送一条信息表明这块区域被更新了.
  4. Wayland Compositor收到这条信息后,立即重新合成整个桌面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实现 Wayland 显示服务器协议的显示服务器也称为 Wayland 合成器,因为它们也执行合成视窗管理器的任务.

  • Hyprland – 一个用C++ 编写的基于wlroots 的平铺Wayland 合成器,Hyprland 值得注意的功能包括动态平铺、选项卡式视窗、干净且可读的C++ 代码库以及提供视窗动画、圆角和Dual-Kawase模糊的自定义渲染器.

  • Weston – Wayland 合成器的参考实现,实现客户端装饰.

  • Sway – 平铺 Wayland 合成器和 X11 i3 视窗管理器的直接替代品.

在Windows上

win32 api

我去,这接口名把我看吐了

win32api提供了用户界面,图形,音视频,设备以及网络等等Win32 API 的编程参考 - Win32 apps | Microsoft Learn

winui

WinUI 是适用于 Windows 桌面应用和 UWP 应用的本机用户体验 (UX) 框架

使用界面使用xaml,处逻辑处理使用c++

图形绘制接口

图形绘制与窗口管理(窗口上下文)往往是一起的,比如使用OpenGL往往需要搭配类似GLFW的窗口绘制库.

OpenGL

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

主页 - LearnOpenGL CN (learnopengl-cn.github.io)

DirectX

DirectXDirect eXtension,缩写:DX)是一系列专为多媒体以及游戏开发的api.旗下包含Direct3D、Direct2D、DirectCompute等等多个不同用途的子部分,因为这一系列API皆以Direct字样开头,所以DirectX(只要把X字母替换为任何一个特定API的名字)就成为这一巨大的API系列的统称.目前最新版本为DirectX 12,随附于Windows 10操作系统之上. 之前还有GDI/GDI++(已经过时)Graphics and gaming - Win32 apps | Microsoft Learn

Direct2D 快速入门 - Win32 apps | Microsoft Learn

ID2D1Factory* pD2DFactory = NULL;
HRESULT hr = D2D1CreateFactory(
    D2D1_FACTORY_TYPE_SINGLE_THREADED,
    &pD2DFactory
    );
   // Obtain the size of the drawing area.
RECT rc;
GetClientRect(hwnd, &rc);

// Create a Direct2D render target          
ID2D1HwndRenderTarget* pRT = NULL;          
HRESULT hr = pD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties(),
    D2D1::HwndRenderTargetProperties(
        hwnd,
        D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top)
    ),
    &pRT
); 
 ID2D1SolidColorBrush* pBlackBrush = NULL;
if (SUCCEEDED(hr))
{
            
    pRT->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        ); 
}   
  pRT->BeginDraw();

pRT->DrawRectangle(
    D2D1::RectF(
        rc.left + 100.0f,
        rc.top + 100.0f,
        rc.right - 100.0f,
        rc.bottom - 100.0f),
        pBlackBrush);

HRESULT hr = pRT->EndDraw();    
 
SafeRelease(pRT);
SafeRelease(pBlackBrush);

Vulkan

跨平台图形与计算应用程序接口,号称下一代OpenGL

首页 — EasyVulkan

Home | Vulkan | Cross platform 3D Graphics

PacktPublishing/Learning-Vulkan: Code repository for Learning Vulkan, published by Packt (github.com)

https://vulkan-tutorial.com/

void initVulkan() {
    createInstance();
    setupDebugMessenger();
    createSurface();
    pickPhysicalDevice();
    createLogicalDevice();
    createSwapChain();
    createImageViews();
    createGraphicsPipeline();
}

...

void createGraphicsPipeline() {

}

Metal

苹果上的类似OpenGL,Direct3D,兼顾图形与计算,面向底层应用程序接口.

相关应用库

  1. SFML
  2. SDL
  3. FLTK
  4. Qt
  5. GLFW(针对OpenGL图形库)
  6. raylib
  7. imgui
  8. nanoGui
  9. easyx
  10. Oxygine - 2D C++ game framework

相关资料

  1. How X Window Managers Work, And How To Write One (Part I) (jichu4n.com)
  2. Xlib 01: Creating windows from scratch with Xlib on Linux | Hereket
  3. tutorial (xcb.freedesktop.org)
  4. cairographics.org
  5. Metal (API) - 维基百科,自由的百科全书 (wikipedia.org)
  6. Vulkan - 维基百科,自由的百科全书 (wikipedia.org)

如有疑问,欢迎各位交流!

服务器配置
宝塔:宝塔服务器面板,一键全能部署及管理
云服务器:阿里云服务器
Vultr服务器: Vultr服务器
GPU服务器:Vast.ai
代码练习平台
CodeCrafters CodeCrafters

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2195196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【含开题报告+文档+PPT+源码】基于SSM + Vue的养老院管理系统【包运行成功】

开题报告 随着社会的发展和经济的进步&#xff0c;人口老龄化问题逐渐凸显。统计数据显示&#xff0c;全球范围内的老龄人口比例正在逐年上升&#xff0c;养老需求也随之增长。养老院作为提供专业养老服务的机构&#xff0c;承担着照料老人、提供医疗保健和社交活动等责任。传…

DVWA Brute Force篇暴力破解 Low/Medium/Hight

这里就不再赘述环境搭建&#xff0c;就默认你已经做好环境搭建的准备了.接下来就步入正题(我的bp是汉化) 任务一&#xff0c;设置级别为low级别&#xff0c;创建好我们的字典文件 任务二 开启抓包&#xff0c;并且我们输入错误的账户密码 &#xff08;当我知道账户名称为admin时…

Nginx06-静态资源部署

零、文章目录 Nginx06-静态资源部署 1、静态资源概述 静态资源&#xff1a;是在Web开发中不经常改变的文件&#xff0c;比如图片、CSS样式表、JavaScript脚本文件等。这些资源通常是预先编译好的&#xff0c;不需要服务器端的动态处理。动态资源&#xff1a;是在Web开发中需…

fiddler抓包19_模拟IP地址(如异地IP)

课程大纲 使用场景举例&#xff1a;北京模拟海南IP地址“182.118.99.12”发送请求。 ① 打开CustomRules.js文件&#xff1a;Fiddler快捷键“CtrlR”(或鼠标点击&#xff0c;菜单栏 - Rules“规则” - Customize Rules“自定义规则”)。 ② 添加代码&#xff0c;保存&#xff1…

SpringBoot在线教育系统:架构设计与技术选型

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

计算机网络——DNS

提供域名——>ip地址的转换 分层命名 分布式解析 怎么样维护 DNS实现在边缘系统——传输层及其以上 还提供别名——>规范名字的转换——>ip 负载均衡是一种用于在多个计算资源&#xff08;如服务器、网络设备等&#xff09;之间分配工作负载的技术。其主要目的是…

最小生成树prim算法kruskal算法

最小生成树 在一个无向图中求一棵树(n-1条边&#xff0c;无环&#xff0c;连通所有点)而且这棵树的边的权和最小 prim(普利姆)算法 prim算法有叫加点法&#xff0c;我们先标定一个点&#xff0c;然后寻找与这个点相连的边的权值最小的点&#xff0c;不断重复此操作&#xff…

【鸿蒙学习】深入解析鸿蒙应用与元服务:含义、区别、应用场景及创建方法

文章目录 鸿蒙应用&#xff08;HarmonyOS App&#xff09;含义用于干什么优缺点 元服务&#xff08;Atomic Service&#xff09;含义用于干什么优缺点 鸿蒙应用与元服务的区别创建方法鸿蒙应用的创建元服务的创建 总结 随着科技的不断进步&#xff0c;操作系统也在不断迭代更新…

医院管理自动化:Spring Boot技术实践

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…

上传文件失败,请检查阿里云配置信息:[The specified bucket is not valid.

-- 十一假期结束 -- 去年今日此门中&#xff0c;人面挑花相应红。 -- 人面不知何处去&#xff0c;桃花依旧笑春风。

UART驱动学习三(TTY驱动部分源码解析)

目录 全局框架图一、tty_io.c 分析1. 关键数据结构和定义2. 文件操作结构体3. 初始化和注册4. 读写操作5. 挂起和恢复6. 信号处理7. 设备类8. 控制台通知9. 辅助函数10. 代码功能11. 带有注释的部分tty_io.c源码 二、tty_ldisc.c 分析1. 关键数据结构和定义2. 行规程操作函数3.…

从零开始打造华丽的国庆生活记录本地HTML网站

目录 目录 前言 准备工作 所需工具 文件夹结构 基础知识入门 HTML基础 CSS基础 JavaScript基础 步骤详解 1. 创建项目文件夹 2. 编写HTML文件 3. 添加CSS样式 4. 增加交互功能 5. 添加图片和视频 6. 美化网站 7. 实现响应式设计 8. 测试与优化 附加功能 创建…

Windows 搭建 Gitea

一、准备工作 1. 安装 Git&#xff1a;Gitea 依赖 Git 进行代码管理&#xff0c;所以首先需要确保系统中安装了 Git。 下载地址&#xff1a;https://git-scm.com/downloads/win 2. 安装数据库&#xff08;可选&#xff09; 默认情况下&#xff0c;Gitea 使用 SQLite 作为内…

【springboot】使用代码生成器快速开发

接上一项目&#xff0c;使用mybatis-plus-generator实现简易代码文件生成 在fast-demo-web模块中的pom.xml中添加mybatis-plus-generator、freemarker和Lombok依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator&…

Windows 11:如何轻松安装或卸载 Copilot 应用(多种方法)

起初&#xff0c;Copilot 是一个与 Windows 11 和 Windows 10 系统紧密结合的内置 AI 助手&#xff0c;能够通过回答问题、调整系统设置等功能来提高你的工作效率。 但从 Windows 11 24H2 开始&#xff0c;Copilot 功能已经从系统中剥离出来&#xff0c;成了一个基于 Microsoft…

【kubernetes】环境准备及K8S二进制安装【最新最全】

一,规划 1,架构 主节点(3台 master)+ 工作节点 (1台 node1) Pod网段: 10.0.0.0/16 Service网段: 10.255.0.0/16 实验环境规划: 操作系统:centos7.6 配置: 4Gib内存/6vCPU/100G硬盘 注意:也可以用4vCPU 网络:NAT 开启虚拟机的虚拟化: 2,K8S集群角色 Ip 主机名…

【嵌入式实时操作系统开发】智能家居入门4(FreeRTOS、MQTT服务器、MQTT协议、STM32、微信小程序)

前面已经发了智能家居入门的1、2、3了&#xff0c;在实际开发中一般都会使用到实时操作系统&#xff0c;这里就以FreeRTOS为例子&#xff0c;使用标准库。记录由裸机转到实时操作系统所遇到的问题以及总体流程。相较于裸机&#xff0c;系统实时性强了很多&#xff0c;小程序下发…

JavaSE——面向对象9.1:代码块详解

目录 一、静态代码块 二、构造代码块 三、局部代码块 四、总结 一、静态代码块 在《JavaSE——面向对象9&#xff1a;static、final关键字、代码块、单例模式》这篇文章中已经介绍过&#xff0c;静态代码块随着类的加载而加载&#xff0c;且只加载一次&#xff0c;这里不再…

【优选算法】---分治 归并排序

分治 归并排序 一、排序数组 / 归并排序的复习1、题目解析2、算法原理3、代码 二、逆序对的总数1、题目解析2、算法原理3、代码 三、计算右侧小于当前元素的个数1、题目解析2、算法原理3、代码 四、翻转对1、题目解析2、算法原理3、代码 一、排序数组 / 归并排序的复习 归并排…

Windows下Jenkins控制台中文乱码

问题描述 问题情况如下图&#xff1a; 环境信息 Windows 11 家庭中文版java 21.0.4 2024-07-16 LTSJenkins 2.452.3 解决方法 增加系统JAVA_TOOL_OPTIONS&#xff0c;并设置值为-Dfile.encodingGBK。 打开设置方法&#xff1a;桌面上右键点击“此电脑”图标&#xff0c;选…