0

我正在使用 Python 3.8 和 PyQt5 编写一个带有“Designer”的 GUI,该 GUI 与 Qt5-Package 一起安装,然后翻译(使用 pyuic5)到一个 .py 文件。

实际上,当堆叠小部件的当前索引发生变化时(单击按钮时它会更改/切换),我有一个渐变动画。

我的问题... 在动画到堆叠小部件的其他页面时出现白色背景。我想让它透明,例如。不可见,因此背景中的图像可见(它位于另一个文件“资源”中)。

我已经尝试为堆叠的小部件设置固定背景。这样,在动画期间看不到白色。但是,我的目标是将其设置为透明以查看背景。在某些页面上,我找到了将样式表设置为“背景:透明”或将属性设置为“WA_TranslucentBackground”的信息,但所有这些都对我不起作用。样式表 background-color: rgba(0,0,0,0) 都不起作用。

我希望有人可以帮助我解决我的问题。如果缺少任何信息,请发表评论。预先感谢。


更新:一个要测试的代码片段...

有一个非常小的代码片段可以工作(我不记得我是从哪个网站获得的)。我将背景涂成绿色,所以问题是可见的。使用 Python 3.8 运行以下代码我得到了...

IncorrectFadingAnimationAtQStackedWidgetSimplified

很明显,我在动画过程中遇到了与白色背景相同的问题。

import sys
from PyQt5.QtCore import QTimeLine
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class FaderWidget(QWidget):
    def __init__(self, old_widget, new_widget): 
        QWidget.__init__(self, new_widget)    
        self.old_pixmap = QPixmap(new_widget.size())
        old_widget.render(self.old_pixmap)
        self.pixmap_opacity = 1.0  
        self.timeline = QTimeLine()
        self.timeline.valueChanged.connect(self.animate)
        self.timeline.finished.connect(self.close)
        self.timeline.setDuration(333)
        self.timeline.start()  
        self.resize(new_widget.size())
        self.show()
    
    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        painter.setOpacity(self.pixmap_opacity)
        painter.drawPixmap(0, 0, self.old_pixmap)
        painter.end()
    
    def animate(self, value):
        self.pixmap_opacity = 1.0 - value
        self.repaint()

class StackedWidget(QStackedWidget):
    def __init__(self, parent = None):
        QStackedWidget.__init__(self, parent)
    
    def setCurrentIndex(self, index):
        self.fader_widget = FaderWidget(self.currentWidget(), self.widget(index))
        QStackedWidget.setCurrentIndex(self, index)
    
    def setPage1(self):
        self.setCurrentIndex(0)
    
    def setPage2(self):
        self.setCurrentIndex(1)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = QWidget()
    stack = StackedWidget()
    window.setStyleSheet("background-color: #0f0;")  # To see problem
    stack.addWidget(QCalendarWidget())
    editor = QTextEdit()
    editor.setPlainText("Hello world! "*100)
    stack.addWidget(editor)
    
    page1Button = QPushButton("Page 1")
    page2Button = QPushButton("Page 2")
    page1Button.clicked.connect(stack.setPage1)
    page2Button.clicked.connect(stack.setPage2)
    
    layout = QGridLayout(window)
    layout.addWidget(stack, 0, 0, 1, 2)
    layout.addWidget(page1Button, 1, 0)
    layout.addWidget(page2Button, 1, 1)
    
    window.show()
    
    sys.exit(app.exec_())

希望现在更容易提供帮助。


我试图简化我的python代码,但它仍然是一些代码......

主要.py:

from sys import exit as sys_exit
from sys import argv as sys_argv
from outputFile import Ui_MainWindow
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QStackedWidget, QWidget

import types
from funcs import FaderWidget, setCurrentIndex


class MyMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MyMainWindow, self).__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.btnFunc)

        ''' Overwrite method 'setCurrentIndex' from StackedWidget to animate it '''
        self.stackedWidget.setCurrentIndex = types.MethodType(setCurrentIndex, self.stackedWidget)

    def btnFunc(self):
        index = self.stackedWidget.currentIndex()
        if index == 1:
            self.stackedWidget.setCurrentIndex(0)
        else:
            self.stackedWidget.setCurrentIndex(1)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys_argv)
    MainWindow = MyMainWindow()
    MainWindow.show()
    sys_exit(app.exec_())

函数.py:

from PyQt5.QtWidgets import QStackedWidget, QWidget
from PyQt5.QtCore import QTimeLine
from PyQt5.QtGui import QPixmap, QPainter

class FaderWidget(QWidget):
    def __init__(self, old_widget, new_widget):
        QWidget.__init__(self, new_widget)

        self.old_pixmap = QPixmap(new_widget.size())
        old_widget.render(self.old_pixmap)
        self.pixmap_opacity = 1.0

        self.timeline = QTimeLine()
        self.timeline.valueChanged.connect(self.animate)
        self.timeline.finished.connect(self.close)
        self.timeline.setDuration(333)
        self.timeline.start()

        self.resize(new_widget.size())
        self.show()

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        painter.setOpacity(self.pixmap_opacity)
        painter.drawPixmap(0, 0, self.old_pixmap)
        painter.end()

    def animate(self, value):
        self.pixmap_opacity = 1.0 - value
        self.repaint()


def setCurrentIndex(self, index):
    self.fader_widget = FaderWidget(self.currentWidget(), self.widget(index))
    QStackedWidget.setCurrentIndex(self, index)

我的问题预览: IncorrectFadingAnimationAtQStackedWidget

4

1 回答 1

2

问题是渲染一个小部件并没有考虑到父级的背景,而只考虑了小部件自己的背景:

如果启用此选项,即使未设置 autoFillBackground,窗口小部件的背景也会呈现到目标中。

这意味着render它将使用小部件的调色板backgroundRole作为背景颜色,无论它是否“透明”。

禁用默认DrawWindowBackground标志对您没有多大帮助,即使您fill使用 的像素图Qt.transparent,因为它将与现有小部件重叠,使其“模糊”。

解决方案是渲染顶级窗口,但仅使用小部件的几何图形:

class FaderWidget(QWidget):
    def __init__(self, old_widget, new_widget):
        QWidget.__init__(self, new_widget)

        self.old_pixmap = QPixmap(old_widget.size())
        window = old_widget.window()
        geo = old_widget.rect().translated(old_widget.mapTo(window, QtCore.QPoint()))
        window.render(self.old_pixmap, sourceRegion=QtGui.QRegion(geo))
        # ...

请注意,您应该为 QPixmap和调整大小使用的小部件大小,这是因为如果您调整窗口大小,“新”小部件仍将具有以前的大小(堆叠的小部件大小或它在可见之前的大小) ): QStackedWidget 子对象的几何图形仅在它们可见或将要显示时在调整大小时更新。

于 2020-07-04T12:09:40.600 回答