Skip to content

Cannot set a transparent background in qt/tkinter #98

@Arkueid

Description

@Arkueid

On some devices, the following code fails to display a transparent background.

import os
import sys
from typing import Optional

from OpenGL.raw.GL.VERSION.GL_1_0 import glEnable, GL_BLEND, glBlendFunc, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, \
    glClearColor, glClear, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, glViewport
from PySide6.QtCore import Qt, QTimer, QPoint
from PySide6.QtGui import QSurfaceFormat, QMouseEvent
from PySide6.QtOpenGLWidgets import QOpenGLWidget
from PySide6.QtWidgets import QApplication, QMainWindow
import live2d.v3 as live2d
from live2d.v3.params import StandardParams



class Live2DWidget(QOpenGLWidget):
    def __init__(self, model_path: str):
        super().__init__()
        self.model_path = os.path.normpath(model_path)
        self.model: Optional[live2d.LAppModel] = None
        self.last_pos = QPoint()
        self.setAutoFillBackground(False)  # 在Live2DWidget构造函数中添加


        # OpenGL 高级配置

        fmt = QSurfaceFormat()
        fmt.setAlphaBufferSize(0)
        fmt.setSamples(4)
        self.setFormat(fmt)

        # 60FPS 定时器
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.timer.start(16)

    def initializeGL(self):
        # 核心透明通道初始化[6,7](@ref)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        # glClearColor(1.0, 0.0, 0.0, 0.0)
        # live2d.clearBuffer()

        # Live2D 初始化
        live2d.init()
        live2d.glewInit()

        # 加载模型(增加异常处理)
        try:
            self.model = live2d.LAppModel()
            self.model.LoadModelJson(self.model_path)
            # 根据模型发布者或者模型 XXX.cdi3.json 中可查找到水印对应的参数 id

            # 假设查找到的模型参数 id 为 Param261,假设值为 0 表示显示水印,值为 1 表示消失
            self.model.SetParameterValue("Param14", 1, 1)
            # print(f"Part Count: {self.model.GetPartCount()}")
            # # 获取 part 名称的字符串数组
            # partIds = self.model.GetPartIds()
            # print(f"Part Ids: {partIds}")
            # # 设置部件 PartHairBack 的透明度为 50%
            # self.model.SetPartOpacity(partIds.index("PartHairBack"), 0.5)
            # self.model.SetPartOpacity(partIds.index("PartHairBack"), 0.5)
            self.model.Resize(self.width(), self.height())
        except Exception as e:
            print(f"模型加载失败: {str(e)}")
            QApplication.instance().quit()

    def paintGL(self):

        # glClearColor(0.0, 0.0, 0.0, 0.0)
        # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)  # 关键修复点[1,6](@ref)
        # glClear(GL_COLOR_BUFFER_BIT)
        live2d.clearBuffer()
        if self.model:
            self.model.Update()
            self.model.Draw()

    def resizeGL(self, w: int, h: int):
        glViewport(0, 0, w, h)
        if self.model:
            self.model.Resize(w, h)
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Live2D透明窗口")

        # 配置主窗口透明
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
        # self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)

        self.setStyleSheet("background:transparent;")

        # 创建Live2D部件
        self.live2d_widget = Live2DWidget(r"./recourse/mianfeimox/llny.model3.json")
        self.setCentralWidget(self.live2d_widget)

        #
        # # 窗口尺寸
        self.resize(800, 600)

        # 示例参数控制
        # QTimer.singleShot(1000, self.init_extra_controls)

    def init_extra_controls(self):
        # 初始化后控制示例
        if self.live2d_widget.model:
            # 设置透明度
            part_ids = self.live2d_widget.model.GetPartIds()
            if "PartHairBack" in part_ids:
                index = part_ids.index("PartHairBack")
                self.live2d_widget.model.SetPartOpacity(index, 0.7)

            # 控制嘴部
            self.live2d_widget.model.SetParameterValue(
                StandardParams.ParamMouthOpenY,
                0.5,
                1.0
            )

    def closeEvent(self, event):
        # 清理资源
        if self.live2d_widget.model:
            self.live2d_widget.model = None
        live2d.dispose()
        event.accept()


if __name__ == "__main__":
    # 配置OpenGL格式
    fmt = QSurfaceFormat()
    fmt.setVersion(3, 3)
    fmt.setProfile(QSurfaceFormat.CoreProfile)
    fmt.setAlphaBufferSize(8)
    QSurfaceFormat.setDefaultFormat(fmt)

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

Originally posted by @gyl1314 in #30

Sub-issues

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdocumentationImprovements or additions to documentationwontfixThis will not be worked on

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions