| name | pyqt-widgets |
| description | PyQt/PySide6 widgets and layouts - buttons, inputs, containers, item views, layout management |
| metadata | {"author":"OSS AI Skills","version":"1.0.0","tags":["python","qt","pyqt","pyside","widgets","gui","layouts"]} |
PyQt Widgets - QtWidgets Module
Comprehensive guide to Qt widgets and layout management.
Display Widgets
QLabel
from PySide6.QtWidgets import QLabel
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap
label = QLabel("Text Label")
label.setText("New text")
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
label.setWordWrap(True)
label.setIndent(10)
label.setPixmap(QPixmap("image.png"))
label.setScaledContents(True)
label.setText("<b>Bold</b> and <i>italic</i>")
label.setTextFormat(Qt.TextFormat.RichText)
label.setText('<a href="https://example.com">Click here</a>')
label.setOpenExternalLinks(True)
label.linkActivated.connect(lambda url: print(f"Clicked: {url}"))
QProgressBar
from PySide6.QtWidgets import QProgressBar
progress = QProgressBar()
progress.setRange(0, 100)
progress.setValue(50)
progress.setTextVisible(True)
progress.setFormat("%p%")
progress.setRange(0, 0)
progress.setOrientation(Qt.Orientation.Horizontal)
progress.setOrientation(Qt.Orientation.Vertical)
QLCDNumber
from PySide6.QtWidgets import QLCDNumber
lcd = QLCDNumber()
lcd.display(123)
lcd.setDigitCount(4)
lcd.setMode(QLCDNumber.Mode.Dec)
lcd.setSegmentStyle(QLCDNumber.SegmentStyle.Flat)
Input Widgets
QLineEdit
from PySide6.QtWidgets import QLineEdit
line = QLineEdit()
line.setText("Default")
line.setPlaceholderText("Enter text...")
line.clear()
line.setEchoMode(QLineEdit.EchoMode.Normal)
line.setEchoMode(QLineEdit.EchoMode.Password)
line.setEchoMode(QLineEdit.EchoMode.NoEcho)
line.setMaxLength(100)
line.setInputMask("999-9999")
line.setValidator(QIntValidator(0, 100))
line.selectAll()
line.setSelection(0, 5)
line.textChanged.connect(self.onTextChange)
line.textEdited.connect(self.onTextEdit)
line.returnPressed.connect(self.onSubmit)
line.editingFinished.connect(self.onEditDone)
QTextEdit
from PySide6.QtWidgets import QTextEdit
text = QTextEdit()
text.setPlainText("Plain text content")
plain = text.toPlainText()
text.setHtml("<b>Bold</b> and <i>italic</i>")
html = text.toHtml()
text.append("More text")
text.append("<b>HTML text</b>")
text.setReadOnly(True)
text.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
cursor = text.textCursor()
cursor.insertText("Inserted text")
text.undo()
text.redo()
text.setUndoRedoEnabled(False)
QSpinBox and QDoubleSpinBox
from PySide6.QtWidgets import QSpinBox, QDoubleSpinBox
spin = QSpinBox()
spin.setRange(0, 100)
spin.setValue(50)
spin.setSingleStep(5)
spin.setSuffix(" px")
spin.setPrefix("$ ")
spin.valueChanged.connect(lambda v: print(f"Value: {v}"))
dspin = QDoubleSpinBox()
dspin.setRange(0.0, 1.0)
dspin.setValue(0.5)
dspin.setDecimals(2)
dspin.setSingleStep(0.1)
QComboBox
from PySide6.QtWidgets import QComboBox
combo = QComboBox()
combo.addItem("Option 1")
combo.addItems(["Option 2", "Option 3", "Option 4"])
combo.setCurrentIndex(0)
combo.setCurrentText("Option 2")
index = combo.currentIndex()
text = combo.currentText()
combo.setEditable(True)
combo.setCompleter(None)
combo.insertItem(0, "First")
combo.insertItems(1, ["A", "B"])
combo.removeItem(0)
combo.clear()
combo.currentIndexChanged.connect(lambda i: print(f"Index: {i}"))
combo.currentTextChanged.connect(lambda t: print(f"Text: {t}"))
QCheckBox
from PySide6.QtWidgets import QCheckBox
check = QCheckBox("Enable feature")
check.setChecked(True)
check.setTristate(True)
check.setCheckState(Qt.CheckState.PartiallyChecked)
is_checked = check.isChecked()
state = check.checkState()
check.stateChanged.connect(lambda s: print(f"State: {s}"))
check.toggled.connect(lambda c: print(f"Checked: {c}"))
QRadioButton
from PySide6.QtWidgets import QRadioButton, QButtonGroup
radio1 = QRadioButton("Option A")
radio2 = QRadioButton("Option B")
group = QButtonGroup()
group.addButton(radio1)
group.addButton(radio2)
radio1.setChecked(True)
if radio1.isChecked():
print("Option A selected")
radio1.toggled.connect(lambda c: print(f"Toggled: {c}"))
group.buttonClicked.connect(lambda btn: print(f"Clicked: {btn.text()}"))
QSlider
from PySide6.QtWidgets import QSlider
slider = QSlider(Qt.Orientation.Horizontal)
slider.setRange(0, 100)
slider.setValue(50)
slider.setSingleStep(1)
slider.setPageStep(10)
slider.setTickPosition(QSlider.TickPosition.TicksBelow)
slider.setTickInterval(10)
value = slider.value()
slider.valueChanged.connect(lambda v: print(f"Value: {v}"))
Buttons
QPushButton
from PySide6.QtWidgets import QPushButton
from PySide6.QtGui import QIcon
button = QPushButton("Click Me")
button.setIcon(QIcon("icon.png"))
button.setIconSize(QSize(16, 16))
button.setEnabled(False)
button.setDefault(True)
button.setFlat(True)
button.setCheckable(True)
button.setChecked(True)
button.toggled.connect(lambda c: print(f"Toggled: {c}"))
menu = QMenu(button)
menu.addAction("Option 1")
menu.addAction("Option 2")
button.setMenu(menu)
button.clicked.connect(lambda: print("Clicked!"))
button.pressed.connect(lambda: print("Pressed"))
button.released.connect(lambda: print("Released"))
QToolButton
from PySide6.QtWidgets import QToolButton
tool = QToolButton()
tool.setIcon(QIcon("icon.png"))
tool.setToolTip("Tool tip")
tool.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
tool.setAutoRaise(True)
Container Widgets
QGroupBox
from PySide6.QtWidgets import QGroupBox, QVBoxLayout
group = QGroupBox("Settings")
group.setCheckable(True)
group.setChecked(True)
layout = QVBoxLayout(group)
layout.addWidget(QCheckBox("Option 1"))
layout.addWidget(QCheckBox("Option 2"))
QTabWidget
from PySide6.QtWidgets import QTabWidget, QWidget
tabs = QTabWidget()
page1 = QWidget()
page2 = QWidget()
tabs.addTab(page1, "Tab 1")
tabs.addTab(page2, "Tab 2")
tabs.addTab(page3, QIcon("icon.png"), "Tab 3")
tabs.setCurrentIndex(0)
index = tabs.currentIndex()
tabs.setTabsClosable(True)
tabs.setMovable(True)
tabs.setDocumentMode(True)
tabs.currentChanged.connect(lambda i: print(f"Tab: {i}"))
tabs.tabCloseRequested.connect(lambda i: tabs.removeTab(i))
QScrollArea
from PySide6.QtWidgets import QScrollArea, QLabel
scroll = QScrollArea()
content = QLabel("Very long content...")
content.setWordWrap(True)
scroll.setWidget(content)
scroll.setWidgetResizable(True)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
QSplitter
from PySide6.QtWidgets import QSplitter
splitter = QSplitter(Qt.Orientation.Horizontal)
splitter.addWidget(left_widget)
splitter.addWidget(right_widget)
splitter.setSizes([200, 400])
sizes = splitter.sizes()
splitter.setChildrenCollapsible(False)
QStackedWidget
from PySide6.QtWidgets import QStackedWidget
stack = QStackedWidget()
stack.addWidget(page1)
stack.addWidget(page2)
stack.addWidget(page3)
stack.setCurrentIndex(0)
stack.setCurrentWidget(page2)
current = stack.currentIndex()
Item Views
QListWidget
from PySide6.QtWidgets import QListWidget, QListWidgetItem
list = QListWidget()
list.addItems(["Item 1", "Item 2", "Item 3"])
item = QListWidgetItem("Custom Item")
item.setIcon(QIcon("icon.png"))
item.setData(Qt.ItemDataRole.UserRole, {"id": 123})
list.addItem(item)
list.setCurrentRow(0)
list.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)
selected = list.selectedItems()
for item in selected:
print(item.text())
list.currentItemChanged.connect(lambda curr, prev: print(curr.text()))
list.itemClicked.connect(lambda item: print(item.text()))
list.itemDoubleClicked.connect(lambda item: print(f"Double: {item.text()}"))
QTreeWidget
from PySide6.QtWidgets import QTreeWidget, QTreeWidgetItem
tree = QTreeWidget()
tree.setHeaderLabels(["Name", "Value"])
root = QTreeWidgetItem(["Parent", "0"])
tree.addTopLevelItem(root)
child1 = QTreeWidgetItem(["Child 1", "1"])
child2 = QTreeWidgetItem(["Child 2", "2"])
root.addChild(child1)
root.addChild(child2)
grandchild = QTreeWidgetItem(["Grandchild", "3"])
child1.addChild(grandchild)
root.setExpanded(True)
tree.itemClicked.connect(lambda item, col: print(f"{item.text(col)}"))
QTableWidget
from PySide6.QtWidgets import QTableWidget, QTableWidgetItem
table = QTableWidget()
table.setRowCount(3)
table.setColumnCount(2)
table.setHorizontalHeaderLabels(["Column 1", "Column 2"])
item = QTableWidgetItem("Cell 0,0")
table.setItem(0, 0, item)
item = table.item(0, 0)
text = item.text() if item else ""
table.selectRow(0)
table.selectColumn(1)
table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
table.setEditTriggers(QAbstractItemView.EditTrigger.DoubleClicked)
table.horizontalHeader().setStretchLastSection(True)
table.resizeColumnsToContents()
Layout Management
QVBoxLayout and QHBoxLayout
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout
vlayout = QVBoxLayout()
vlayout.addWidget(label)
vlayout.addWidget(button)
vlayout.addStretch()
vlayout.addWidget(bottom_label)
hlayout = QHBoxLayout()
hlayout.addWidget(left_button)
hlayout.addStretch()
hlayout.addWidget(right_button)
main_layout = QVBoxLayout()
main_layout.addLayout(hlayout)
QGridLayout
from PySide6.QtWidgets import QGridLayout
grid = QGridLayout()
grid.addWidget(label1, 0, 0)
grid.addWidget(lineEdit, 0, 1)
grid.addWidget(label2, 1, 0)
grid.addWidget(comboBox, 1, 1)
grid.addWidget(bigWidget, 2, 0, 1, 2)
grid.setColumnStretch(1, 1)
grid.setRowStretch(0, 2)
QFormLayout
from PySide6.QtWidgets import QFormLayout
form = QFormLayout()
form.addRow("Name:", nameLineEdit)
form.addRow("Email:", emailLineEdit)
form.addRow("Age:", ageSpinBox)
form.addRow(button)
form.setLabelAlignment(Qt.AlignmentFlag.AlignRight)
form.setFormAlignment(Qt.AlignmentFlag.AlignHCenter)
QStackedLayout
from PySide6.QtWidgets import QStackedLayout
stack = QStackedLayout()
stack.addWidget(page1)
stack.addWidget(page2)
stack.addWidget(page3)
stack.setCurrentIndex(0)
Layout Properties
layout.setContentsMargins(10, 10, 10, 10)
layout.setSpacing(5)
layout.addWidget(label, alignment=Qt.AlignmentFlag.AlignCenter)
layout.addWidget(widget1, stretch=1)
layout.addWidget(widget2, stretch=2)
widget.setMinimumSize(100, 50)
widget.setMaximumSize(500, 300)
from PySide6.QtWidgets import QSizePolicy
widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
Best Practices
Layout
layout = QVBoxLayout()
layout.addWidget(button)
button.setGeometry(10, 10, 100, 30)
layout.setStretchFactor(widget, 1)
Widget Creation
class CustomButton(QPushButton):
def __init__(self, text):
super().__init__(text)
self.setMinimumSize(100, 40)
State Management
class AppState:
def __init__(self):
self.data_changed = Signal()
state = AppState()
Do:
- Use layouts over fixed geometry
- Set size policies, not fixed sizes
- Use signals for communication
Don't:
- Mix layout with setGeometry
- Create widgets in tight loops
- Hardcode sizes
References