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

No one assigned

    Labels

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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions