如何获取小部件文本的颜色,并将其设置为另一个小部件的颜色

How to get the color of a widget text, and set it as the color of another widget

我有两个小部件

首先,QLineEdit 有一个样式表(假设不可访问或不可更改)将文本颜色设置为某种颜色(例如红色)。

第二个,QLabel 具有默认文本颜色(例如黑色)

如何获取QLineEdit中文本的颜色,并将其设置为QLabel

中的颜色
l1 = QLineEdit()
color_to_be_set= l1.palette().highlight().color().name() # this approach is giving the wrong color

q1 = QLabel()
q1.setText("the text")

# then set the new color
"Trial#1 (Not working at all, not changing the color)"
palette = q1.palette()
palette.setColor(QPalette.WindowText,QColor(color_to_be_set))
q1.setPalette.....

"Trial#2, gives the wrong color"
q1.setStyleSheet("color:{}".format(color_to_be_set))

正如评论中已经解释的那样,没有 public API 可以访问样式表设置的属性,我真诚地怀疑是否存在(至少,对于当前的实现,包括 Qt6) .

也就是说,对这些属性有一定程度的访问权限,但它仅适用于以下内容:

  • backgroundbackground-color(相同);
  • color;
  • selection-background-color;
  • selection-color;
  • alternate-background-color;

只要设置了上述任何属性,小部件的调色板就会更改为以下调色板颜色角色

QSS property QPalette role(s)
background, background-color Base, Button, Window, backgroundRole()*
color Text, ButtonText, WindowText, foregroundRole()*
selection-background-color Highlight
selection-color HighlightedText
alternate-background-color AlternateBase

* 值是对部件 class 定义的引用(例如,QPushButton 通常使用 Button 作为前台角色) .它们可能会被各自的 setter 函数覆盖。

此外,这些属性仅支持 QSS Brush types: plain colors, gradients or palette(<role>)。这里没有像素图!

请记住,为了正确访问这些属性,小部件 必须 抛光 ,这意味着,如果小部件尚未曾经显示,调用ensurePolished()是强制性的:

Ensures that the widget and its children have been polished by QStyle (i.e., have a proper font and palette).

这意味着在 任何已经完善的 parent 的情况下创建的任何新 Qt 小部件都将使用 系统 调色板。

考虑以下几点:

from PyQt5.QtWidgets import *
app = QApplication([])
app.setStyleSheet('* {color: green;}')
source = QWidget()
# source.ensurePolished() # leave this commented for now
color = source.palette().windowText().color()
target = QWidget(styleSheet='background: {}'.format(color.name()))
target.show()
app.exec()

然后取消第五行的注释,看看结果。


现在,有一些收获。

设置样式表后,任何受其影响 的小部件都会style()private QStyleSheetStyle 覆盖。 API 不会公开该样式,并且会完全控制每个受影响的小部件的样式集。
但并非总是如此。

看这个片段:

from PyQt5.QtWidgets import *
app = QApplication([])
app.setStyleSheet('* {background-color: black;}')
topLevel = QTextEdit()
topLevel.show()
parent = QWidget()
layout = QVBoxLayout(parent)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(QTextEdit())
parent.show()
app.exec()

以我现在的风格(氧气),两个背景略有不同:

左边是 topLevel 小部件,右边是 parent。如您所见,底层样式仍然具有一定程度的控制。

这是一个必须牢记的重要方面,尝试用 QProxyStyle 覆盖它是不够的:QStyleSheetStyle 将“取得控制权”并完全忽略覆盖的功能,除了一个非常很少有人喜欢 drawItemText()。任何其他函数都将在“C++ 端”实现中调用,python 绑定中对此没有有用的覆盖。

此外,无论何时 QSS 仍然在内部使用底层样式,结果是颜色属性将像任何 QPalette 一样使用:它们是 reference 颜色,而不是实际的。任何小部件都会使用样式实现,它可能会使用不同的颜色角色,或者根据情况完全改变颜色。

无论何时使用默认样式(即使通过 QStyleSheetStyle 修改),调色板都只是一个参考,与物理调色板不同:将相同的基本调色板提供给两个样式画家,他们将以不同的方式使用它的颜色方法。显示给用户的实际颜色可能略有不同,甚至完全不同,可能会被忽略。


总而言之,以下几个方面最为重要:

  • 刚刚创建的小部件将使用默认调色板;
  • 无法访问边框属性,也无法访问边距和填充(最后两个也取决于继承的样式);
  • 顶级小部件的行为可能不同;
  • 样式可能不完全符合颜色集(甚至忽略它们);
  • 调色板颜色是参考:样式可能将某个角色用于意想不到的目的,或者完全忽略它;一些常见样式对项目视图 headers 使用 Button 角色,其他使用 Window 角色;
  • 虽然通常受到尊重,但上述颜色属性可能会被样式更改,就像任何调色板一样;
  • 基本的 QSS 颜色属性只有在小部件被抛光后才能正确访问:必须调用 ensurePolished(),这通常发生在第一次可见性更改和任何影响小部件(参见 QStyle.unpolish() and QStyle.polish());
  • QPalette 将 QBrush 用于其任何角色和组,可以是以下任何一种:QColor、QGradient 或 QPixmap;这意味着如果调色板角色使用渐变或像素图,returned color() 将是 invalid,等等;
  • background-image 更新调色板(事实上,它没有在上面的 table 中列出); border-image 也是如此(如上所述,无法访问边框属性);
  • fusion 样式(通常)是用于扩展样式表实现的最可靠样式;当不确定或出现意外行为时,请使用 QApplication.setStyle('fusion')widget.setStyle(QStyleFactory.create('fusion'));
  • OS 样式可能会覆盖使用私有像素图的绘图以尊重标准 OS 外观;
  • 复杂的小部件需要完整和明确的属性值; 从不 为 parent 小部件或应用程序 [1] 设置通用属性(又名,无选择器),包括 QComboBox、QScrollBar 和所有QAbstractScrollArea subclasses(包括项目视图);

所以,考虑到这一切,只要用一个标准的QStyle,把widget打磨好,上面解释的作用table应该return 任何样式表支持的属性中设置的颜色,包括继承的样式表。

但是你永远不能确定这一点,你必须始终意识到这一点。

[1] 在上面的代码示例中,我 确实 使用了通用样式表,但这是有意为之且为了简单起见;这种做法通常 高度 不鼓励正常使用。在为 parent 和复杂小部件(见上文)设置样式表时始终使用 selectors