aiohttp
免费Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues
中文简介正在准备中。当前显示原文说明。
Use when styling PyQt/PySide6 widgets with QSS - selectors and pseudo-states, stylesheet application, common style properties, widget-specific styling, or building a dark theme
中文简介正在准备中。当前显示原文说明。
查看安装方法安装前可以查看交给 AI 代理的指令内容。
QSS (Qt Style Sheets) is Qt's styling system. It resembles CSS but has critical differences that cause cross-platform bugs.
QSS shares CSS syntax but differs in supported selectors, properties, and cascade behavior. These differences are the source of most cross-platform bugs.
| Selector | CSS | QSS |
|---|---|---|
::pseudo-element | Supported (e.g., ::before, ::after) | Limited support - only Qt-specific pseudo-elements like ::indicator, ::drop-down, ::item |
Descendant selector (A B) | Matches nested elements | Does not work in most widgets - Qt uses parent-to-child cascade instead |
Child selector (A > B) | Matches direct children | Partially supported, but widget hierarchy matters more than DOM-like nesting |
Sibling selector (A + B, A ~ B) | Supported | Not supported - widgets don't have sibling relationships like DOM |
Attribute selectors ([attr]) | Full support | Supported via setProperty() but syntax differs ([attr="value"] works) |
Class selector (.my-class) | Supported | Not supported - use objectName or custom properties instead |
Qt silently ignores CSS properties it doesn't implement:
box-shadow - Qt uses custom properties or qproperty- prefix insteadtext-shadow - Not implementedfilter - Not implemented (use QGraphicsEffect instead)transform - Not implemented (use widget geometry methods)position: absolute/fixed - Qt uses layouts or manual geometrydisplay: flex/grid - Qt uses QLayout classes, not CSS display::before, ::after - Not supported (use child widgets instead)border-radius on a parent widget does not clip child widgets unless the parent sets a mask:
# Bad - children overflow rounded corners
parent.setStyleSheet("border-radius: 10px;")
parent.addWidget(child) # child shows outside rounded area
# Good - use a mask
from PySide6.QtGui import QRegion
from PySide6.QtCore import QRect
parent.setMask(QRegion(QRect(0, 0, parent.width(), parent.height()), QRegion.Ellipse))
# Or use a custom paintEvent for rounded rectangle mask
Widgets cascade styles from parent to child differently from the DOM:
app.setStyleSheet() applies globally, but parent.setStyleSheet() only affects children that don't have their own stylesheet set# Bad - child overrides parent
app.setStyleSheet("QPushButton { background: blue; }")
child_button.setStyleSheet("") # Empty string clears inherited style
# Good - use custom properties for theming
app.setStyleSheet("QPushButton { background: $primary-color; }")
child_button.setProperty("primary-color", "#0078d4")
child_button.style().polish(child_button)
The same QSS renders differently across Windows, macOS, and Linux due to native widget rendering.
Fix: Use explicit min-height, padding on critical widgets rather than relying on defaults.
Qt widgets may render with native platform styling that ignores QSS:
# Force QSS rendering on Windows/macOS
widget.setAttribute(Qt.WidgetAttribute.WA_StyleSheet)
# For QComboBox dropdown - native rendering ignores QSS
combo.setStyleSheet("QComboBox::drop-down { border: none; }")
combo.view().setAttribute(Qt.WidgetAttribute.WA_StyleSheet)
QSS uses device-independent pixels, but scaling behavior varies:
# Set high-DPI scaling policy (Qt 6)
from PySide6.QtWidgets import QApplication
from PySide6.QtCore import Qt
app = QApplication(sys.argv)
app.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
)
Verification on a platform you don't have: Use Qt's remote desktop or CI services (GitHub Actions with Xvfb), or test in a VM with the target OS.
A theme should be a single QSS source with placeholder/palette substitution, not per-widget stylesheets:
# Bad - per-widget stylesheets
class MainWindow(QMainWindow):
def __init__(self):
self.button1.setStyleSheet("background: #0078d4;")
self.button2.setStyleSheet("background: #0078d4;")
self.label.setStyleSheet("color: #333;")
# Good - tokenized theme
class Theme:
@staticmethod
def apply(app):
app.setStyleSheet("""
QPushButton { background-color: $primary; }
QLabel { color: $text-primary; }
""".replace("$primary", "#0078d4").replace("$text-primary", "#333"))
# Or use a palette
from PySide6.QtGui import QPalette, QColor
class Theme:
@staticmethod
def apply_dark(app):
palette = QPalette()
palette.setColor(QPalette.ColorRole.Window, QColor("#1e1e1e"))
palette.setColor(QPalette.ColorRole.WindowText, QColor("#ffffff"))
app.setPalette(palette)
Create a gallery page to verify theme changes:
class ThemeGallery(QWidget):
def __init__(self):
super().__init__()
# Create one of each widget type
self.buttons = [QPushButton(f"Button {i}") for i in range(3)]
self.inputs = [QLineEdit(f"Input {i}") for i in range(3)]
self.labels = [QLabel(f"Label {i}") for i in range(3)]
# Layout them all
# Switch themes with a button to verify consistency
Use custom painting instead of fighting QSS when:
class RoundedButton(QPushButton):
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
# Custom rounded rectangle with gradient
gradient = QLinearGradient(0, 0, 0, self.height())
gradient.setColorAt(0, "#0078d4")
gradient.setColorAt(1, "#106ebe")
painter.setBrush(gradient)
painter.setPen(Qt.PenStyle.NoPen)
painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), 8, 8)
Assumes familiarity with CSS selectors and specificity. Focuses on Qt-specific syntax.
from PySide6.QtWidgets import QApplication
app = QApplication()
# Inline
app.setStyleSheet("""
QLabel { color: #333; }
QPushButton { padding: 5px 10px; }
""")
# From file
with open("style.qss", "r") as f:
app.setStyleSheet(f.read())
button = QPushButton("Styled")
button.setStyleSheet("""
QPushButton {
background-color: blue;
color: white;
border-radius: 5px;
}
QPushButton:hover {
background-color: darkblue;
}
""")
# Set custom property
button = QPushButton("Primary")
button.setProperty("primary", True)
# Force style refresh
button.style().unpolish(button)
button.style().polish(button)
/* Use in QSS */
QPushButton[primary="true"] {
background-color: #0078d4;
color: white;
}
QPushButton[primary="true"]:hover {
background-color: #106ebe;
}
QPushButton {
background-color: #0078d4;
color: white;
border: none;
border-radius: 4px;
padding: 8px 16px;
font-weight: bold;
}
QPushButton:hover {
background-color: #106ebe;
}
QPushButton:pressed {
background-color: #005a9e;
}
QPushButton:disabled {
background-color: #cccccc;
color: #666666;
}
/* Flat button */
QPushButton[flat="true"] {
background-color: transparent;
color: #0078d4;
border: 1px solid #0078d4;
}
QLineEdit {
background-color: white;
border: 1px solid #cccccc;
border-radius: 4px;
padding: 4px 8px;
selection-background-color: #0078d4;
}
QLineEdit:focus {
border: 2px solid #0078d4;
}
QLineEdit:disabled {
background-color: #f5f5f5;
color: #999999;
}
/* Password field */
QLineEdit[echoMode="2"] {
lineedit-password-character: 9679; /* Unicode bullet */
}
QComboBox {
background-color: white;
border: 1px solid #cccccc;
border-radius: 4px;
padding: 4px 8px;
}
QComboBox:hover {
border-color: #999999;
}
QComboBox::drop-down {
border: none;
width: 24px;
}
QComboBox::down-arrow {
image: url(down_arrow.png);
width: 12px;
height: 12px;
}
/* Dropdown list */
QComboBox QAbstractItemView {
background-color: white;
border: 1px solid #cccccc;
selection-background-color: #0078d4;
}
QTabWidget::pane {
border: 1px solid #cccccc;
border-radius: 4px;
}
QTabBar::tab {
background-color: #f5f5f5;
border: 1px solid #cccccc;
padding: 8px 16px;
margin-right: 2px;
}
QTabBar::tab:selected {
background-color: white;
border-bottom-color: white;
}
QTabBar::tab:hover {
background-color: #e5e5e5;
}
/* Vertical scrollbar */
QScrollBar:vertical {
background-color: #f5f5f5;
width: 12px;
margin: 0;
}
QScrollBar::handle:vertical {
background-color: #cccccc;
border-radius: 6px;
min-height: 30px;
}
QScrollBar::handle:vertical:hover {
background-color: #999999;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical {
height: 0;
}
setProperty() for theme variables instead of hardcoding colorswidget.blockSignals(True) before batch changes, then blockSignals(False)还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues
中文简介正在准备中。当前显示原文说明。
Use when doing structural code search and rewriting - ast-grep linting, refactoring, multi-language patterns
中文简介正在准备中。当前显示原文说明。
Use when building GBA games with the BPCore Lua engine - entity, sprite and tilemap functions, SRAM save and load, link cable multiplayer protocol, camera and scrolling, or optimization patterns
中文简介正在准备中。当前显示原文说明。
Use when running background tasks with Celery - worker and broker configuration (Redis, RabbitMQ), task routing by name vs queue, chains/groups/chords, retry patterns (autoretry_for, retry_backoff), acks_late semantics, failure detection, and monitoring with Flower
中文简介正在准备中。当前显示原文说明。
Use when building Django applications - security hardening, authentication and permissions, ORM optimization, PostgreSQL features, Django 6.0, migrations, testing, and ecosystem libraries
中文简介正在准备中。当前显示原文说明。
Use when customizing Django Admin - save_formset, get_search_results, formsets, queryset optimization, db_index, custom URLs
中文简介正在准备中。当前显示原文说明。