样式表旋转框的字体不能调整大小
The font of a stylesheeted spinbox cannot be resized
如果应用了样式表,修改 QSpinBox
的字体大小没有任何效果,而我测试的所有其他小部件 类 都可以正确调整大小,而不管它们的样式表如何。 QSpinBox
没有样式表的元素也会正确调整大小。请注意,所有小部件的 .font().pointSize()
都是相等的,所以我认为这只是一个显示问题。
一种可能的解决方法是保存当前样式表,将其暂时设置为 None,调整字体大小并恢复样式表,但这听起来很糟糕而且很老套。
我正在使用 Python 3.7.4 和 PyQt5 5.12.2。
这是我的 MRE 的样子:
下面是使用的代码:
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QSpinBox, QMainWindow
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Setup widgets.
self.widgets = []
for n in range(2):
label = QLabel(parent=self)
label.move(10+150*n, 20)
label.setText("QLabel")
setattr(self, f"label{n+1}", label)
pb = QPushButton(parent=self)
pb.move(10+150*n, 60)
pb.setText("QPushButton")
setattr(self, f"pb{n+1}", pb)
le = QLineEdit(parent=self)
le.move(10+150*n, 100)
le.setText("QLineEdit")
setattr(self, f"le{n+1}", le)
sb = QSpinBox(parent=self)
sb.move(10+150*n, 140)
sb.setSpecialValueText("QSpinBox")
setattr(self, f"sb{n+1}", sb)
for widget in (label, pb, le, sb):
self.widgets.append(widget)
# Take note of the initial window size.
self.initial_size = (self.width(), self.height(), 30)
self.resize(300, 200)
# Paint the right-hand side widgets in red.
for widget in self.widgets[int(len(self.widgets)/2):]:
class_name = widget.__class__.__name__ # QLabel, QPushButton, QSpinBox.
widget.setStyleSheet(class_name + "{background-color: red}")
def resizeEvent(self, event):
"""Adjust the fontsize of all the widgets upon resizing the main window."""
# Calculate a scale factor by comparing current and initial size.
w0, h0, f0 = self.initial_size
w, h = self.width(), self.height()
scale = min(w/w0, h/h0)
# Apply the scale factor to each widget font.
for widget in self.widgets:
font = widget.font()
font.setPointSize(scale * f0)
widget.setFont(font)
# Check that all fontsizes are identical.
assert len(set(widget.font().pointSize() for widget in self.widgets)) == 1
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DisableHighDpiScaling) # Because it's irrelevant here.
app.setQuitOnLastWindowClosed(True)
window = MainWindow()
window.show()
app.exec_()
只要将样式表设置为小部件,Qt 就会自动禁用该小部件的调色板和字体传播。这意味着所有 child widget 都不会收到来自父级的有关字体(和调色板)更改的通知。
这在样式表语法的 inheritance 章节中有解释:
In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. By default, when using Qt Style Sheets, a widget does not automatically inherit its font and color setting from its parent widget.
注意上面明显是指使用setFont()
设置的字体和使用setPalette()
设置的颜色。如果您在样式表 中设置字体或颜色 , 这些 属性的传播将根据 级联按预期工作 样式表的性质。
QSpinBox 与 QComboBox 和项目视图等其他小部件一样,是一个 复杂 小部件,它使用子小部件来显示它并与之交互,在本例中它是一个 QLineEdit (可通过 lineEdit()
访问)。
为了解决您的问题,有多种方法可用:
在应用程序上设置 AA_UseStyleSheetPropagationInWidgetStyles
属性 :
QApplication.setAttribute(
Qt.AA_UseStyleSheetPropagationInWidgetStyles, True)
这显然有副作用,传播将适用于应用程序的 所有 小部件,由您决定是否合适。
注意:此属性已从 Qt 5.7 引入。
检查小部件是否为 QSpinBox 并为其行编辑设置字体:
for widget in self.widgets:
font = widget.font()
font.setPointSize(scale * f0)
if isinstance(widget, QSpinBox):
widget.lineEdit().setFont(font)
else:
widget.setFont(font)
使用样式表设置字体。在你的情况下,你可以检查小部件是否有样式表并使用模板更新它:
baseStyleSheet = '''
{} {{
background-color: red;
font-size: {}px;
}}
'''
# ...
def resizeEvent(self, event):
w0, h0, f0 = self.initial_size
w, h = self.width(), self.height()
scale = min(w/w0, h/h0)
font_size = scale * f0
for widget in self.widgets:
if widget.styleSheet():
widget.setStyleSheet(baseStyleSheet.format(
widget.__class__.__name__, font_size))
else:
font = widget.font()
font.setPointSize(font_size)
widget.setFont(font)
显然,以上仅适用于仅设置简单属性的特定情况。
如果应用了样式表,修改 QSpinBox
的字体大小没有任何效果,而我测试的所有其他小部件 类 都可以正确调整大小,而不管它们的样式表如何。 QSpinBox
没有样式表的元素也会正确调整大小。请注意,所有小部件的 .font().pointSize()
都是相等的,所以我认为这只是一个显示问题。
一种可能的解决方法是保存当前样式表,将其暂时设置为 None,调整字体大小并恢复样式表,但这听起来很糟糕而且很老套。
我正在使用 Python 3.7.4 和 PyQt5 5.12.2。
这是我的 MRE 的样子:
下面是使用的代码:
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QSpinBox, QMainWindow
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Setup widgets.
self.widgets = []
for n in range(2):
label = QLabel(parent=self)
label.move(10+150*n, 20)
label.setText("QLabel")
setattr(self, f"label{n+1}", label)
pb = QPushButton(parent=self)
pb.move(10+150*n, 60)
pb.setText("QPushButton")
setattr(self, f"pb{n+1}", pb)
le = QLineEdit(parent=self)
le.move(10+150*n, 100)
le.setText("QLineEdit")
setattr(self, f"le{n+1}", le)
sb = QSpinBox(parent=self)
sb.move(10+150*n, 140)
sb.setSpecialValueText("QSpinBox")
setattr(self, f"sb{n+1}", sb)
for widget in (label, pb, le, sb):
self.widgets.append(widget)
# Take note of the initial window size.
self.initial_size = (self.width(), self.height(), 30)
self.resize(300, 200)
# Paint the right-hand side widgets in red.
for widget in self.widgets[int(len(self.widgets)/2):]:
class_name = widget.__class__.__name__ # QLabel, QPushButton, QSpinBox.
widget.setStyleSheet(class_name + "{background-color: red}")
def resizeEvent(self, event):
"""Adjust the fontsize of all the widgets upon resizing the main window."""
# Calculate a scale factor by comparing current and initial size.
w0, h0, f0 = self.initial_size
w, h = self.width(), self.height()
scale = min(w/w0, h/h0)
# Apply the scale factor to each widget font.
for widget in self.widgets:
font = widget.font()
font.setPointSize(scale * f0)
widget.setFont(font)
# Check that all fontsizes are identical.
assert len(set(widget.font().pointSize() for widget in self.widgets)) == 1
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DisableHighDpiScaling) # Because it's irrelevant here.
app.setQuitOnLastWindowClosed(True)
window = MainWindow()
window.show()
app.exec_()
只要将样式表设置为小部件,Qt 就会自动禁用该小部件的调色板和字体传播。这意味着所有 child widget 都不会收到来自父级的有关字体(和调色板)更改的通知。
这在样式表语法的 inheritance 章节中有解释:
In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. By default, when using Qt Style Sheets, a widget does not automatically inherit its font and color setting from its parent widget.
注意上面明显是指使用setFont()
设置的字体和使用setPalette()
设置的颜色。如果您在样式表 中设置字体或颜色 , 这些 属性的传播将根据 级联按预期工作 样式表的性质。
QSpinBox 与 QComboBox 和项目视图等其他小部件一样,是一个 复杂 小部件,它使用子小部件来显示它并与之交互,在本例中它是一个 QLineEdit (可通过 lineEdit()
访问)。
为了解决您的问题,有多种方法可用:
在应用程序上设置
AA_UseStyleSheetPropagationInWidgetStyles
属性 :QApplication.setAttribute( Qt.AA_UseStyleSheetPropagationInWidgetStyles, True)
这显然有副作用,传播将适用于应用程序的 所有 小部件,由您决定是否合适。
注意:此属性已从 Qt 5.7 引入。检查小部件是否为 QSpinBox 并为其行编辑设置字体:
for widget in self.widgets: font = widget.font() font.setPointSize(scale * f0) if isinstance(widget, QSpinBox): widget.lineEdit().setFont(font) else: widget.setFont(font)
使用样式表设置字体。在你的情况下,你可以检查小部件是否有样式表并使用模板更新它:
baseStyleSheet = ''' {} {{ background-color: red; font-size: {}px; }} ''' # ... def resizeEvent(self, event): w0, h0, f0 = self.initial_size w, h = self.width(), self.height() scale = min(w/w0, h/h0) font_size = scale * f0 for widget in self.widgets: if widget.styleSheet(): widget.setStyleSheet(baseStyleSheet.format( widget.__class__.__name__, font_size)) else: font = widget.font() font.setPointSize(font_size) widget.setFont(font)
显然,以上仅适用于仅设置简单属性的特定情况。