☰
利用Qt和live2d-py自制重返未来1999的桌面动态壁纸
2026/9/27 23:10:40 网站建设 项目流程

Windows11关于利用Qt和live2d-py自制重返未来1999的桌面动态壁纸

  • 前言
  • 前期准备
      • 1、准备一个工程文件夹,按照以下格式存放文件与文件夹
      • 2、安装python 3.11
      • 3、准备额外依赖项
  • python源码(建议看一遍源码再复制)
  • 一些其他问题
    • 角色资源
    • 模型有白色方块
    • 模型脸部有黑色的拼接缝隙
    • 其它
      • 关于更新
  • 其他没什么了,大家中秋快乐

前言

这只是基础版,有很多没更新

前期准备

1、准备一个工程文件夹,按照以下格式存放文件与文件夹

project/ ├── Model/ │ └── 你的角色代码1/ │ ├── expressions/ │ │ ├── ... │ │ ├── 面部json文件1.json │ │ └── 面部json文件2.json │ ├── motions/ │ │ ├── ... │ │ ├── 动作json文件1.json │ │ └── 动作json文件2.json │ ├── textures/ │ │ ├── ... │ │ ├── png纹理图1.png │ │ └── png纹理图2.png │ ├── 角色1.moc3 │ └── 角色1.model3.json └── 源码.py

2、安装python 3.11

3、准备额外依赖项

有条件的在虚拟环境里安装

pip install pyside6 live2d-py

python源码(建议看一遍源码再复制)

importos.pathimportsysfromPySide6.QtGuiimportQSurfaceFormatfromPySide6.QtWidgetsimportQApplication,QWidget,QMainWindowfromPySide6.QtOpenGLWidgetsimportQOpenGLWidgetfromPySide6.QtCoreimportQTimer,Qt,Signalimportlive2d.v3asl2dimportwin32conimportwin32guiimportwin32apiimporttimeimportpathlibimportjsonclassmotionJson:def__init__(self,json_path):withopen(json_path,"r")asf:text=f.read()self.Json=json.loads(text)self.motion=self.Json["FileReferences"]["Motions"]expressions=self.Json["FileReferences"]["Expressions"]self.expressions={}forexpinexpressions:self.expressions[exp["Name"]]=exp["File"]self.motion2num={}self.num2motion=[]self.expression2num={}self.num2expression=[]i=0fornameinself.motion.keys():self.motion2num[name]=i self.num2motion.append(name)i+=1i=0fornameinself.expressions.keys():self.expression2num[name]=i self.num2expression.append(name)i+=1classLive2DWidget(QOpenGLWidget):modelLoaded=Signal()def__init__(self,model_path,role_name):super().__init__()self.model=Noneself.role_name=role_name self.timer=QTimer(self)self.timer.timeout.connect(self.update)self.timer.start(16)self.model_path=model_path self.Json=motionJson(self.model_path+"/"+self.role_name+".model3.json")definitializeGL(self):l2d.init()l2d.glInit()model_path_=self.model_path+"/"+self.role_name+".model3.json"ifos.path.exists(model_path_):self.model=l2d.LAppModel()self.model.LoadModelJson(model_path_)self.model.Resize(self.width(),self.height())self.modelLoaded.emit()else:print(f"模型文件未找到:{model_path_}")defpaintGL(self):ifself.model:l2d.clearBuffer()self.model.Update()# 缩放:1.0 默认,0.8 缩小到 80%,1.2 放大到 120%self.model.SetScale(1.3)# 水平:正数向右,负数向左# 垂直:正数向上,负数向下self.model.SetOffset(-0.7,-1.2)ifself.model.IsMotionFinished():self.model.StartMotion("body",self.Json.motion2num["b_idle"],l2d.MotionPriority.NORMAL)self.model.Draw()defresizeGL(self,w,h):"""窗口大小改变时,调整模型的显示大小"""ifself.model:self.model.Resize(self.width(),self.height())defmotion(self):foriinrange(len(self.Json.motion)):motion=self.model_path+"/"+self.Json.motion[self.Json.num2motion[i]][0]["File"]self.model.LoadExtraMotion(motionJsonPath=motion,group="body")self.model.StartMotion("body",self.Json.motion2num["b_idle"],l2d.MotionPriority.NORMAL)defexpressions(self):foriinrange(len(self.Json.expressions)):exp=self.model_path+"/"+self.Json.expressions[self.Json.num2expression[i]]self.model.LoadExtraExpression(self.Json.num2expression[i],filePath=exp)self.model.SetExpression("e_idle")classl2d_windows(QMainWindow):def__init__(self,model_path,role_name,x=0,y=0,w=3456,h=1920):super().__init__()self.setGeometry(x,y,w,h)self.setWindowFlags(Qt.FramelessWindowHint)# 允许窗口透明self.setAttribute(Qt.WA_TranslucentBackground)self.l2d_widget=Live2DWidget(model_path,role_name)self.setCentralWidget(self.l2d_widget)self.l2d_widget.modelLoaded.connect(self.f_connect)deff_connect(self):self.l2d_widget.motion()self.l2d_widget.expressions()defmake_me_wallpaper(hwnd,x=0,y=0,screen_w=win32api.GetSystemMetrics(win32con.SM_CXSCREEN),screen_h=win32api.GetSystemMetrics(win32con.SM_CYSCREEN)):# 1. 先把窗口改成无边框+WS_CHILDstyle=win32gui.GetWindowLong(hwnd,win32con.GWL_STYLE)style=style&~win32con.WS_OVERLAPPEDWINDOW|win32con.WS_CHILD win32gui.SetWindowLong(hwnd,win32con.GWL_STYLE,style)exstyle=win32gui.GetWindowLong(hwnd,win32con.GWL_EXSTYLE)exstyle=exstyle|win32con.WS_EX_LAYERED win32gui.SetWindowLong(hwnd,win32con.GWL_EXSTYLE,exstyle)# 2. 找到 Progmanprogman=win32gui.FindWindow("Progman",None)ifnotprogman:returnFalse# 3. 发消息让它生成 WorkerWwin32gui.SendMessage(progman,0x052C,0,0)time.sleep(0.3)# 4. 枚举所有 WorkerWworkerw_list=[]defenum_cb(h,_):ifwin32gui.GetClassName(h)=="WorkerW":workerw_list.append(h)returnTruewin32gui.EnumChildWindows(progman,enum_cb,0)ifnotworkerw_list:returnFalsetarget_workerw=workerw_list[-1]win32gui.SetParent(hwnd,target_workerw)# 5. 全屏win32gui.SetWindowPos(hwnd,None,x,y,screen_w,screen_h,win32con.SWP_NOZORDER|win32con.SWP_NOACTIVATE)# 确保窗口显示win32gui.ShowWindow(int(hwnd),win32con.SW_SHOW)returnTrueif__name__=="__main__":app=QApplication([])root=l2d_windows("Model/315502","315502")# 这里将315502替换为你的角色代码,角色代码就是你的moc3文件名hwnd=root.winId()ifmake_me_wallpaper(hwnd,screen_w=3456,screen_h=1920):# screen_w与screen_h替换为你电脑屏幕的实际分辨率print("Successfully set the window as wallpaper.")else:print("Failed to set the window as wallpaper.")root.show()sys.exit(app.exec())

需要改模型的大小与位置在 Live2DWidget.paintGL() 里面修改
该代码的详细教程与注意事项以后有空的时候再出

一些其他问题

角色资源

可以在github上找找,我记得有位大佬上传过1999的全套live2d资源,也可以通过https://uttu.merui.net/ 这个网站看看,这个网站有模型,但没办法直接下,只能通过其他办法获取该网址的模型,而且通过该网站获取的纹理图是webp格式的,需要转为png格式,有空的时候会出教程

模型有白色方块

这个是moc3文件中存在一系列名为bone的网格,有bone、bone1、bone2…,需要调整这些网格的透明度,让其完全透明隐藏,有会live2d的大佬应该会用Cubism调整这些网格吧(这方面我不太清楚),有空的时候会出用python调整的代码

模型脸部有黑色的拼接缝隙

该问题主要是因为纹理图各个纹理的边缘有黑色的描边,这个会在出角色资源教程时给出我的一个解决方案

其它

关于更新

闲暇的时候更新一下交互什么的吧,说不定能添加一些好玩的功能

其他没什么了,大家中秋快乐

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询