如何获取小部件文本的颜色,并将其设置为另一个小部件的颜色
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) .
也就是说,对这些属性有一定程度的访问权限,但它仅适用于以下内容:
background
和 background-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。
我有两个小部件
首先,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) .
也就是说,对这些属性有一定程度的访问权限,但它仅适用于以下内容:
background
和background-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()
andQStyle.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。