当与 QLabel 重叠时,QSlider 无法正确显示透明度 - PyQt5
QSlider not displaying transparency properly when overlapped with QLabel - PyQt5
很确定我已经在整个互联网上到处查看为什么会发生这种情况,所以我已经求助于一次问题。
无论如何,我正在尝试制作一个透明的(除了边框)QSlider 放在 QLabel 的顶部,上面设置了 QPixmap。
这样我就可以拥有
this hue gradient underneath the transparent parts of this slider(所以我可以 select 一个色调,我正在创建一个粗略的图像编辑器)
但问题是,不管它知道它有多透明(字面意思是在它后面显示整个 window 的背景颜色)它似乎真的不想让 QLabel 显示在下面它
我知道我可以保存色调渐变并使用 .setStyleSheet('background-image:url('gradient.png')
并避免完全使用 QLabel,但我不想将渐变保存为文件,我希望它在主内存中该程序是 运行.
目前这是我的代码:
# hue background
self.hueBGData = Image.new('RGBA', (40, 256), (0, 0, 0, 0)) # background hue gradient
self.drawHueSlider() # here i'm just generating the hue gradient, but I don't want to save it as an actual file
self.QtHueBG = ImageQt.ImageQt(self.hueBGData)
self.hueBG = QLabel(self)
self.hueBGPixmap = QPixmap.fromImage(self.QtHueBG)
self.hueBG.setPixmap(self.hueBGPixmap)
self.hueBG.setGeometry(604, 255, 40, 256) # set to same position (40, 256)
# actual slider
self.hueSlider = QSlider(Qt.Vertical, self) # actual slider
self.hueSlider.setRange(1, 1530)
self.hueSlider.setValue(600)
self.hueSlider.setGeometry(604, 255, 40, 256) # set to same position (40, 256)
self.hueSlider.setStyleSheet('''QSlider::groove:vertical {border-radius:4px;
border:1px solid #88888f;}
QSlider::handle:vertical {border-radius:4px; margin:-5px 0px;
border:1px solid #88888f;}''')
我试过使用:
.setAttribute(Qt.WA_TranslucentBackground)
滑块
background-color:(0, 0, 0, 0);
滑块
- 首先定义 hueSlider,然后在 hueBG 上使用
.stackUnder(self.hueSider)
。
我还让滑块位于渐变的后面,并使渐变具有 0.5 的不透明度,并将它们完美地分层,但显然滑块在渐变的后面,我不能使用它,我不想渐变为 0.5 不透明度。
如有任何帮助,我们将不胜感激。
编辑最小可重现示例:
from PIL import Image, ImageQt, ImageColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QSlider, QStyleFactory, QStyle
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
import sys
class Interface(QMainWindow):
def __init__(self):
super(Interface, self).__init__()
self.setWindowTitle('slider test')
self.setStyleSheet('background-color: #d8d8df;')
self.background = Image.new('RGBA', (40, 256), (255, 0, 0, 255))
self.label = QLabel(self)
self.backgroundQt = ImageQt.ImageQt(self.background)
self.backgroundPixmap = QPixmap.fromImage(self.backgroundQt)
self.label.setPixmap(self.backgroundPixmap)
self.label.setGeometry(100, 100, 40, 256)
self.slider = QSlider(Qt.Vertical, self)
self.slider.setStyle(QStyleFactory.create('fusion'))
self.slider.setStyleSheet('''QSlider::groove:vertical {border-radius:4px; border:1px solid #88888f;}
QSlider::handle:vertical {border-radius:4px; margin:-5px 0px;
border:1px solid #88888f;}''')
self.slider.setGeometry(100, 100, 40, 256)
self.showMaximized()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle('fusion')
print(app.style().objectName())
ex = Interface()
sys.exit(app.exec_())
此示例仅显示滑块及其背后的整体背景:
问题在于为父项(主要 window)使用通用样式表定义。这是应该避免使用通用样式表的原因之一,应该始终首选 selectors。
样式表本质上是级联的,因此,为父窗口小部件设置背景会为其 所有 个子窗口小部件设置背景。
为避免这种情况,您可以简单地覆盖背景:
self.slider.setStyleSheet('''
QSlider:vertical {
background: transparent;
}
QSlider::groove:vertical {
border-radius: 4px;
border: 1px solid #88888f;
}
QSlider::handle:vertical {
border-radius: 4px;
margin: -5px 0px;
border: 1px solid #88888f;}
''')
但请记住,应避免为父小部件使用通用属性,因为它也可能导致滚动区域中的组合框和滚动条等复杂小部件出现意外问题,因此我强烈建议您正确更改主样式表使用选择器。
另请注意,Qt 样式表支持所有三种 Qt 渐变,因此您甚至不需要为此创建图像,因为您可以非常轻松地构建类似 Hue 的渐变;尝试使用以下样式表
QSlider::groove:vertical {
border: none;
}
QSlider::handle:vertical {
margin: -5px 0px;
border-radius: 4px;
border: 1px solid #88888f;
}
QSlider:vertical {
border-radius: 4px;
border: 1px solid #88888f;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 0, 0, 255),
stop:0.166 rgba(255, 0, 255, 255),
stop:0.333 rgba(0, 0, 255, 255),
stop:0.5 rgba(0, 255, 255, 255),
stop:0.666 rgba(0, 255, 0, 255),
stop:0.833 rgba(255, 255, 0, 255),
stop:1 rgba(255, 0, 0, 255))
}
最后,请记住,不支持也不鼓励将直接子级添加到 QMainWindow,应该始终使用中央小部件(可能具有适当的 layout managers)。
很确定我已经在整个互联网上到处查看为什么会发生这种情况,所以我已经求助于一次问题。
无论如何,我正在尝试制作一个透明的(除了边框)QSlider 放在 QLabel 的顶部,上面设置了 QPixmap。
这样我就可以拥有 this hue gradient underneath the transparent parts of this slider(所以我可以 select 一个色调,我正在创建一个粗略的图像编辑器)
但问题是,不管它知道它有多透明(字面意思是在它后面显示整个 window 的背景颜色)它似乎真的不想让 QLabel 显示在下面它
我知道我可以保存色调渐变并使用 .setStyleSheet('background-image:url('gradient.png')
并避免完全使用 QLabel,但我不想将渐变保存为文件,我希望它在主内存中该程序是 运行.
目前这是我的代码:
# hue background
self.hueBGData = Image.new('RGBA', (40, 256), (0, 0, 0, 0)) # background hue gradient
self.drawHueSlider() # here i'm just generating the hue gradient, but I don't want to save it as an actual file
self.QtHueBG = ImageQt.ImageQt(self.hueBGData)
self.hueBG = QLabel(self)
self.hueBGPixmap = QPixmap.fromImage(self.QtHueBG)
self.hueBG.setPixmap(self.hueBGPixmap)
self.hueBG.setGeometry(604, 255, 40, 256) # set to same position (40, 256)
# actual slider
self.hueSlider = QSlider(Qt.Vertical, self) # actual slider
self.hueSlider.setRange(1, 1530)
self.hueSlider.setValue(600)
self.hueSlider.setGeometry(604, 255, 40, 256) # set to same position (40, 256)
self.hueSlider.setStyleSheet('''QSlider::groove:vertical {border-radius:4px;
border:1px solid #88888f;}
QSlider::handle:vertical {border-radius:4px; margin:-5px 0px;
border:1px solid #88888f;}''')
我试过使用:
.setAttribute(Qt.WA_TranslucentBackground)
滑块background-color:(0, 0, 0, 0);
滑块- 首先定义 hueSlider,然后在 hueBG 上使用
.stackUnder(self.hueSider)
。
我还让滑块位于渐变的后面,并使渐变具有 0.5 的不透明度,并将它们完美地分层,但显然滑块在渐变的后面,我不能使用它,我不想渐变为 0.5 不透明度。
如有任何帮助,我们将不胜感激。
编辑最小可重现示例:
from PIL import Image, ImageQt, ImageColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QSlider, QStyleFactory, QStyle
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
import sys
class Interface(QMainWindow):
def __init__(self):
super(Interface, self).__init__()
self.setWindowTitle('slider test')
self.setStyleSheet('background-color: #d8d8df;')
self.background = Image.new('RGBA', (40, 256), (255, 0, 0, 255))
self.label = QLabel(self)
self.backgroundQt = ImageQt.ImageQt(self.background)
self.backgroundPixmap = QPixmap.fromImage(self.backgroundQt)
self.label.setPixmap(self.backgroundPixmap)
self.label.setGeometry(100, 100, 40, 256)
self.slider = QSlider(Qt.Vertical, self)
self.slider.setStyle(QStyleFactory.create('fusion'))
self.slider.setStyleSheet('''QSlider::groove:vertical {border-radius:4px; border:1px solid #88888f;}
QSlider::handle:vertical {border-radius:4px; margin:-5px 0px;
border:1px solid #88888f;}''')
self.slider.setGeometry(100, 100, 40, 256)
self.showMaximized()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle('fusion')
print(app.style().objectName())
ex = Interface()
sys.exit(app.exec_())
此示例仅显示滑块及其背后的整体背景:
问题在于为父项(主要 window)使用通用样式表定义。这是应该避免使用通用样式表的原因之一,应该始终首选 selectors。
样式表本质上是级联的,因此,为父窗口小部件设置背景会为其 所有 个子窗口小部件设置背景。
为避免这种情况,您可以简单地覆盖背景:
self.slider.setStyleSheet('''
QSlider:vertical {
background: transparent;
}
QSlider::groove:vertical {
border-radius: 4px;
border: 1px solid #88888f;
}
QSlider::handle:vertical {
border-radius: 4px;
margin: -5px 0px;
border: 1px solid #88888f;}
''')
但请记住,应避免为父小部件使用通用属性,因为它也可能导致滚动区域中的组合框和滚动条等复杂小部件出现意外问题,因此我强烈建议您正确更改主样式表使用选择器。
另请注意,Qt 样式表支持所有三种 Qt 渐变,因此您甚至不需要为此创建图像,因为您可以非常轻松地构建类似 Hue 的渐变;尝试使用以下样式表
QSlider::groove:vertical {
border: none;
}
QSlider::handle:vertical {
margin: -5px 0px;
border-radius: 4px;
border: 1px solid #88888f;
}
QSlider:vertical {
border-radius: 4px;
border: 1px solid #88888f;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 0, 0, 255),
stop:0.166 rgba(255, 0, 255, 255),
stop:0.333 rgba(0, 0, 255, 255),
stop:0.5 rgba(0, 255, 255, 255),
stop:0.666 rgba(0, 255, 0, 255),
stop:0.833 rgba(255, 255, 0, 255),
stop:1 rgba(255, 0, 0, 255))
}
最后,请记住,不支持也不鼓励将直接子级添加到 QMainWindow,应该始终使用中央小部件(可能具有适当的 layout managers)。