qt-dialogs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseQt Dialog Patterns
Qt 对话框模式
QMessageBox — Standard Prompts
QMessageBox —— 标准提示框
python
from PySide6.QtWidgets import QMessageBoxpython
from PySide6.QtWidgets import QMessageBoxConfirmation dialog
Confirmation dialog
def confirm_delete(parent, item_name: str) -> bool:
result = QMessageBox.question(
parent,
"Confirm Delete",
f"Delete '{item_name}'? This cannot be undone.",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No, # default button
)
return result == QMessageBox.StandardButton.Yes
def confirm_delete(parent, item_name: str) -> bool:
result = QMessageBox.question(
parent,
"Confirm Delete",
f"Delete '{item_name}'? This cannot be undone.",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No, # default button
)
return result == QMessageBox.StandardButton.Yes
Error
Error
QMessageBox.critical(parent, "Error", f"Failed to save: {error}")
QMessageBox.critical(parent, "Error", f"Failed to save: {error}")
Warning
Warning
QMessageBox.warning(parent, "Warning", "File already exists. Overwrite?")
QMessageBox.warning(parent, "Warning", "File already exists. Overwrite?")
Information
Information
QMessageBox.information(parent, "Done", "Export completed successfully.")
QMessageBox.information(parent, "Done", "Export completed successfully.")
Custom buttons
Custom buttons
msg = QMessageBox(parent)
msg.setWindowTitle("Unsaved Changes")
msg.setText("You have unsaved changes.")
msg.setInformativeText("Do you want to save before closing?")
save_btn = msg.addButton("Save", QMessageBox.ButtonRole.AcceptRole)
discard_btn = msg.addButton("Discard", QMessageBox.ButtonRole.DestructiveRole)
msg.addButton(QMessageBox.StandardButton.Cancel)
msg.exec()
if msg.clickedButton() is save_btn:
self._save()
elif msg.clickedButton() is discard_btn:
pass # discard
msg = QMessageBox(parent)
msg.setWindowTitle("Unsaved Changes")
msg.setText("You have unsaved changes.")
msg.setInformativeText("Do you want to save before closing?")
save_btn = msg.addButton("Save", QMessageBox.ButtonRole.AcceptRole)
discard_btn = msg.addButton("Discard", QMessageBox.ButtonRole.DestructiveRole)
msg.addButton(QMessageBox.StandardButton.Cancel)
msg.exec()
if msg.clickedButton() is save_btn:
self._save()
elif msg.clickedButton() is discard_btn:
pass # discard
else: Cancel — do nothing
else: Cancel — do nothing
undefinedundefinedQFileDialog — File and Directory Pickers
QFileDialog —— 文件与目录选择器
python
from PySide6.QtWidgets import QFileDialog
from pathlib import Pathpython
from PySide6.QtWidgets import QFileDialog
from pathlib import PathOpen single file
Open single file
path, _ = QFileDialog.getOpenFileName(
parent,
"Open File",
str(Path.home()),
"CSV Files (.csv);;Text Files (.txt);;All Files (*)",
)
if path:
self._load(Path(path))
path, _ = QFileDialog.getOpenFileName(
parent,
"Open File",
str(Path.home()),
"CSV Files (.csv);;Text Files (.txt);;All Files (*)",
)
if path:
self._load(Path(path))
Open multiple files
Open multiple files
paths, _ = QFileDialog.getOpenFileNames(parent, "Select Images", "", "Images (*.png *.jpg *.svg)")
paths, _ = QFileDialog.getOpenFileNames(parent, "Select Images", "", "Images (*.png *.jpg *.svg)")
Save file
Save file
path, _ = QFileDialog.getSaveFileName(
parent, "Save As", "export.csv", "CSV (*.csv)"
)
if path:
self._export(Path(path))
path, _ = QFileDialog.getSaveFileName(
parent, "Save As", "export.csv", "CSV (*.csv)"
)
if path:
self._export(Path(path))
Select directory
Select directory
directory = QFileDialog.getExistingDirectory(parent, "Select Output Folder")
The filter string format is `"Description (*.ext *.ext2);;Description2 (*.ext3)"`.directory = QFileDialog.getExistingDirectory(parent, "Select Output Folder")
过滤器字符串格式为`"描述 (*.ext *.ext2);;描述2 (*.ext3)"`。Custom QDialog
自定义QDialog
python
from PySide6.QtWidgets import (
QDialog, QDialogButtonBox, QFormLayout, QLineEdit, QVBoxLayout
)
from PySide6.QtCore import Qt
class AddPersonDialog(QDialog):
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setWindowTitle("Add Person")
self.setModal(True)
self.setMinimumWidth(300)
self._setup_ui()
def _setup_ui(self) -> None:
layout = QVBoxLayout(self)
form = QFormLayout()
self._name_edit = QLineEdit()
self._name_edit.setPlaceholderText("Full name")
self._email_edit = QLineEdit()
self._email_edit.setPlaceholderText("email@example.com")
form.addRow("Name:", self._name_edit)
form.addRow("Email:", self._email_edit)
layout.addLayout(form)
# Standard OK / Cancel buttons
buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
buttons.accepted.connect(self._on_accept)
buttons.rejected.connect(self.reject)
layout.addWidget(buttons)
def _on_accept(self) -> None:
if not self._name_edit.text().strip():
QMessageBox.warning(self, "Validation", "Name is required.")
return
self.accept() # closes dialog and returns QDialog.Accepted
def name(self) -> str:
return self._name_edit.text().strip()
def email(self) -> str:
return self._email_edit.text().strip()python
from PySide6.QtWidgets import (
QDialog, QDialogButtonBox, QFormLayout, QLineEdit, QVBoxLayout
)
from PySide6.QtCore import Qt
class AddPersonDialog(QDialog):
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setWindowTitle("Add Person")
self.setModal(True)
self.setMinimumWidth(300)
self._setup_ui()
def _setup_ui(self) -> None:
layout = QVBoxLayout(self)
form = QFormLayout()
self._name_edit = QLineEdit()
self._name_edit.setPlaceholderText("Full name")
self._email_edit = QLineEdit()
self._email_edit.setPlaceholderText("email@example.com")
form.addRow("Name:", self._name_edit)
form.addRow("Email:", self._email_edit)
layout.addLayout(form)
# Standard OK / Cancel buttons
buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
buttons.accepted.connect(self._on_accept)
buttons.rejected.connect(self.reject)
layout.addWidget(buttons)
def _on_accept(self) -> None:
if not self._name_edit.text().strip():
QMessageBox.warning(self, "Validation", "Name is required.")
return
self.accept() # closes dialog and returns QDialog.Accepted
def name(self) -> str:
return self._name_edit.text().strip()
def email(self) -> str:
return self._email_edit.text().strip()Usage
Usage
dialog = AddPersonDialog(self)
if dialog.exec() == QDialog.DialogCode.Accepted:
self._model.add_person(dialog.name(), dialog.email())
Use `QDialogButtonBox` for standard buttons — it respects platform button order conventions (OK/Cancel vs Cancel/OK).dialog = AddPersonDialog(self)
if dialog.exec() == QDialog.DialogCode.Accepted:
self._model.add_person(dialog.name(), dialog.email())
使用`QDialogButtonBox`创建标准按钮——它会遵循平台的按钮顺序惯例(如OK/Cancel 或 Cancel/OK)。Modal vs Modeless
模态与非模态
python
undefinedpython
undefinedModal — blocks input to parent window
Modal — blocks input to parent window
dialog.setModal(True)
dialog.exec() # blocks until closed
dialog.setModal(True)
dialog.exec() # blocks until closed
Modeless — user can interact with parent
Modeless — user can interact with parent
dialog.setModal(False)
dialog.show() # non-blocking
dialog.raise_() # bring to front
dialog.activateWindow()
For modeless dialogs, keep a reference to prevent garbage collection:
```python
self._settings_dialog = SettingsDialog(self)
self._settings_dialog.show()dialog.setModal(False)
dialog.show() # non-blocking
dialog.raise_() # bring to front
dialog.activateWindow()
对于非模态对话框,需保留引用以避免被垃圾回收:
```python
self._settings_dialog = SettingsDialog(self)
self._settings_dialog.show()Settings Dialog Pattern
设置对话框模式
Settings dialogs should apply changes live (on change) or on explicit OK:
python
class SettingsDialog(QDialog):
settings_changed = Signal(dict)
def __init__(self, settings: dict, parent=None) -> None:
super().__init__(parent)
self._original = dict(settings)
self._current = dict(settings)
self._setup_ui(settings)
def _on_change(self) -> None:
self._current["theme"] = self._theme_combo.currentText()
self.settings_changed.emit(self._current) # live preview
def reject(self) -> None:
self.settings_changed.emit(self._original) # restore on cancel
super().reject()设置对话框应实时应用更改(在修改时)或在点击确定后应用:
python
class SettingsDialog(QDialog):
settings_changed = Signal(dict)
def __init__(self, settings: dict, parent=None) -> None:
super().__init__(parent)
self._original = dict(settings)
self._current = dict(settings)
self._setup_ui(settings)
def _on_change(self) -> None:
self._current["theme"] = self._theme_combo.currentText()
self.settings_changed.emit(self._current) # live preview
def reject(self) -> None:
self.settings_changed.emit(self._original) # restore on cancel
super().reject()