PyQt中QSplashScreen透明图像上出现白边问题

3

尽管我已经尝试了谷歌搜索,但似乎无法弄清楚如何消除我在为QSplashScreen提供的PNG图片周围得到的白色边框。

我看过这篇文章,但是我不知道如何将其翻译成PyQt,或者是否适用于我的情况。

我甚至尝试分别设置黑色和白色蒙版,但效果很差,到处都是点。

有没有人发现了神奇的半透明SplashScreen,还可以像showMessage命令一样输入文本数据?先感谢您的帮助。

我应该提到这也是Windows 7。

以下是我用作启动图像的测试PNG以及它带来的丑陋白边:

Splash Image Result in Windows 7

通过使用QBitmap提供黑白alpha的另一种方法会产生更接近但更丑陋的示例,其中存在奇怪的点。以下是代码和图像。
    splash_pix = QPixmap(":/images/images/PyQtSplash.png")
    splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
    splash.setMask(QBitmap(QPixmap(":/images/images/PyQtSplashAlpha.jpg")))

Splash Alpha QBitmap Result


我不清楚你的问题,但请注意可能是你的窗口管理器坚持绘制边框。 - Thomas K
我使用PySide,但是使用QtCore.Qt.FramelessWindowHint作为窗口标志时,我得到了预期的所有显示内容,甚至包括透明区域。也许这是一个错误,现在已经修复了。(PySide 1.2.1,Python 3.3,Windows 7) - Trilarion
1个回答

3
只要你使用干净透明区域的图像,只需要将其掩码传递给QSplashScreen.setMask即可。在Linux上,此脚本按预期工作。
from PyQt4 import QtGui, QtCore

def show_splash(path):
    image = QtGui.QPixmap(path)
    splash = QtGui.QSplashScreen(image)
    splash.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    splash.setMask(image.mask())
    font = QtGui.QFont(splash.font())
    font.setPointSize(font.pointSize() + 5)
    splash.setFont(font)
    splash.show()
    QtGui.QApplication.processEvents()
    for count in range(1, 6):
        splash.showMessage(splash.tr('Processing %1...').arg(count),
                           QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeft,
                           QtCore.Qt.white)
        QtGui.QApplication.processEvents()
        QtCore.QThread.msleep(1000)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    show_splash(sys.argv[1])
    app.quit()

编辑

这个自定义的 SplashScreen 类应该在 Linux 和 Windows 上都能产生合理的结果:

from PyQt4 import QtGui, QtCore

class SplashScreen(QtGui.QWidget):
    def __init__(self, pixmap):
        QtGui.QWidget.__init__(self)
        self._pixmap = pixmap
        self._message = QtCore.QString()
        self._color = QtGui.QColor.black
        self._alignment = QtCore.Qt.AlignLeft
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint |
                            QtCore.Qt.WindowStaysOnTopHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setFixedSize(self._pixmap.size())
        self.setMask(self._pixmap.mask())

    def clearMessage(self):
        self._message.clear()
        self.repaint()

    def showMessage(self, message, alignment=QtCore.Qt.AlignLeft,
                                   color=QtGui.QColor.black):
        self._message = QtCore.QString(message)
        self._alignment = alignment
        self._color = color
        self.repaint()

    def paintEvent(self, event):
        textbox = QtCore.QRect(self.rect())
        textbox.setRect(textbox.x() + 5, textbox.y() + 5,
                        textbox.width() - 10, textbox.height() - 10)
        painter = QtGui.QPainter(self)
        painter.drawPixmap(self.rect(), self._pixmap)
        painter.setPen(QtGui.QColor(self._color))
        painter.drawText(textbox, self._alignment, self._message)

    def mousePressEvent(self, event):
        self.hide()

def show_splash(path):
    image = QtGui.QPixmap(path)
    splash = SplashScreen(image)
    font = QtGui.QFont(splash.font())
    font.setPointSize(font.pointSize() + 5)
    splash.setFont(font)
    splash.show()
    QtGui.QApplication.processEvents()
    for count in range(1, 6):
        splash.showMessage(splash.tr('Processing %1...').arg(count),
                           QtCore.Qt.AlignCenter, QtCore.Qt.white)
        QtGui.QApplication.processEvents()
        QtCore.QThread.msleep(1000)
    splash.hide()
    splash.close()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    show_splash(sys.argv[1])
    app.quit()

你如何定义“清晰”?我的图片里有一个投影,还有其他东西。在 OP 中更新了一个示例 png 飞溅图像以及我得到的结果。 - Cryptite
@Cryptite。我猜你的图像中可能有一些偏离的几乎透明的像素。然而,我刚刚在Windows XP上测试了一下,现在我能够看到掩码的问题了。QSplashScreen中似乎存在一些错误,因此不久后,我将在我的答案中添加一个自定义的SplashScreen类,希望能够修复这些问题。 - ekhumoro
非常好!谢谢您先生。我可能会在不久的将来在我的网站上写一篇文章,并向您致敬,因为在整个PyQt网络上似乎没有这样的记录。 - Cryptite
@Cryptite。问题可能是由于这个Qt bug引起的。 - ekhumoro
啊,好的,知道了。接下来的问题是!我的大部分程序“加载”都发生在我调用QMainWindow时的init中。在构建过程中,我该如何将状态消息从那里重定向到启动屏幕? - Cryptite
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接