杰瑞科技汇

Python setstylesheet如何自定义控件样式?

Of course! The setStyleSheet method in Python is a powerful feature of Qt-based GUI frameworks, primarily PyQt and PySide. It allows you to style your application's widgets using Cascading Style Sheets (CSS), a language familiar to web developers.

Python setstylesheet如何自定义控件样式?-图1
(图片来源网络,侵删)

This is the preferred way to style modern Qt applications because it separates the application's logic (the Python code) from its presentation (the styling).

How it Works

You apply CSS rules to Qt widgets just like you would to HTML elements on a webpage. A rule consists of:

  • A Selector: Specifies which widget(s) to style (e.g., QPushButton, #myButton, .QPushButtonClass).
  • A Declaration Block: Contains one or more property-value pairs inside curly braces (e.g., background-color: blue; color: white;).

Basic Syntax and Common Widgets

Let's start with a simple example using PyQt6. The syntax is identical for PyQt5 and PySide6/PySide2.

First, make sure you have the library installed:

Python setstylesheet如何自定义控件样式?-图2
(图片来源网络,侵删)
pip install PyQt6

Example: Styling a QPushButton

This example shows how to change the background color, text color, and font of a button.

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
# Create the main application window
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('PyQt setStyleSheet Example')
window.setGeometry(300, 300, 400, 200)
# --- CSS Styling ---
# We define a style sheet as a multi-line string
style_sheet = """
    QPushButton {
        background-color: #2196F3; /* A nice blue */
        color: white;
        border: none;
        padding: 10px;
        font-size: 16px;
        font-weight: bold;
        border-radius: 5px;
    }
    QPushButton:hover {
        background-color: #1976D2; /* Darker blue on hover */
    }
    QPushButton:pressed {
        background-color: #0D47A1; /* Even darker blue when clicked */
    }
"""
# Apply the style sheet to the main window
# This style will be inherited by all child widgets unless they are styled explicitly
window.setStyleSheet(style_sheet)
# Create a button
button = QPushButton("Click Me")
# Layout
layout = QVBoxLayout()
layout.addWidget(button)
window.setLayout(layout)
window.show()
sys.exit(app.exec())

Common Widget Selectors

Here are some of the most frequently used selectors:

Selector Description Example
QWidget Targets all widgets of a specific type. QLabel { color: red; }
#objectName Targets a specific widget using its objectName. #myButton { background-color: green; }
.className Targets widgets with a specific set style class. .error-label { color: red; font-weight: bold; }
A wildcard that targets all widgets. * { font-family: Arial; }
WidgetType > ChildWidget Targets a widget that is a direct child of another. QDialog > QPushButton { border: 2px solid black; }

Advanced Styling Techniques

a) Using objectName for Specific Widgets

This is the most common and recommended way to style individual widgets. It's more specific than a type selector.

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Using objectNames')
window.setGeometry(300, 300, 300, 150)
# Create two buttons
button_ok = QPushButton("OK")
button_cancel = QPushButton("Cancel")
# Give them unique objectNames
button_ok.setObjectName("okButton")
button_cancel.setObjectName("cancelButton")
# Layout
layout = QVBoxLayout()
layout.addWidget(button_ok)
layout.addWidget(button_cancel)
window.setLayout(layout)
# CSS using objectNames (the '#' prefix)
style_sheet = """
    #okButton {
        background-color: #4CAF50; /* Green */
        color: white;
    }
    #cancelButton {
        background-color: #F44336; /* Red */
        color: white;
    }
"""
window.setStyleSheet(style_sheet)
window.show()
sys.exit(app.exec())

b) Using Style Classes (.className)

Style classes allow you to apply a common set of styles to multiple widgets without giving them the same objectName.

Python setstylesheet如何自定义控件样式?-图3
(图片来源网络,侵删)
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Using Style Classes')
window.setGeometry(300, 300, 300, 150)
# Create buttons
button1 = QPushButton("Button 1")
button2 = QPushButton("Button 2")
button3 = QPushButton("Button 3")
# Add a style class to specific buttons
button1.setProperty("class", "primary-button")
button2.setProperty("class", "primary-button")
# button3 does not have the class, so it won't be styled
# Layout
layout = QVBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
layout.addWidget(button3)
window.setLayout(layout)
# CSS using class names (the '.' prefix)
style_sheet = """
    /* Style for all primary buttons */
    .primary-button {
        background-color: #3F51B5; /* Indigo */
        color: white;
        padding: 8px;
        border-radius: 4px;
    }
    /* Style for all buttons by type */
    QPushButton {
        font-size: 14px;
    }
"""
window.setStyleSheet(style_sheet)
window.show()
sys.exit(app.exec())

c) Styling Complex Widgets (QLineEdit, QSlider, etc.)

Complex widgets often have sub-controls that can be styled individually. You access them using the syntax.

Example: Styling a QLineEdit

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLineEdit, QVBoxLayout
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Styling QLineEdit')
window.setGeometry(300, 300, 300, 100)
line_edit = QLineEdit("Some text...")
layout = QVBoxLayout()
layout.addWidget(line_edit)
window.setLayout(layout)
# QLineEdit has sub-controls like 'text' (the input area) and 'placeholder-text'
style_sheet = """
    QLineEdit {
        border: 2px solid #ccc;
        border-radius: 5px;
        padding: 5px;
    }
    QLineEdit:focus {
        border: 2px solid #0096FF;
    }
    /* Style the placeholder text */
    QLineEdit::placeholder {
        color: #aaaaaa;
    }
"""
window.setStyleSheet(style_sheet)
window.show()
sys.exit(app.exec())

Best Practices and Tips

  1. Separation of Concerns: It's a good practice to store your CSS in a separate .css file (e.g., styles.css) and load it into your application. This keeps your Python code clean.

    # In your Python file
    with open('styles.css', 'r') as f:
        style_sheet = f.read()
    window.setStyleSheet(style_sheet)
  2. Inheritance: Styles applied to a parent widget (like QWidget or QMainWindow) are inherited by its children unless a more specific rule overrides it.

  3. Specificity: The order of rules matters. If two rules apply to the same widget, the one defined later in the style sheet usually wins. However, CSS has a specificity system (IDs > Classes > Elements) that determines precedence. When in doubt, make your selector more specific (e.g., #myWindow QPushButton instead of just QPushButton).

  4. Qt Properties: Qt's CSS engine understands special Qt properties. For example, you can use the qproperty- prefix to set a widget's C++ property directly from CSS.

    # Let's say you have a QLabel with a 'customText' property
    # my_label.setProperty("customText", "Hello from CSS!")
    # In CSS:
    QLabel {
        qproperty-customText: "Hello from CSS!";
    }
  5. Use a Qt Style: Instead of writing all CSS from scratch, you can start with a built-in Qt style and then use setStyleSheet to override specific parts of it.

    app.setStyle("Fusion") # Use a clean base style
    window.setStyleSheet("QLineEdit { border: 1px solid black; }")

Summary

Method When to Use Example
setStyleSheet("...") For quick styling, simple apps, or overriding specific parts of a widget's look. window.setStyleSheet("QPushButton { color: blue; }")
#objectName Best practice for styling a single, specific widget. #okButton { background-color: green; }
.className For applying a common style to multiple unrelated widgets. .primary-button { font-weight: bold; }
**:subControl
分享:
扫描分享到社交APP
上一篇
下一篇