qt-dialogs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Qt Dialog Patterns

Qt 对话框模式

QMessageBox — Standard Prompts

QMessageBox —— 标准提示框

python
from PySide6.QtWidgets import QMessageBox
python
from PySide6.QtWidgets import QMessageBox

Confirmation 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

undefined
undefined

QFileDialog — File and Directory Pickers

QFileDialog —— 文件与目录选择器

python
from PySide6.QtWidgets import QFileDialog
from pathlib import Path
python
from PySide6.QtWidgets import QFileDialog
from pathlib import Path

Open 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
undefined
python
undefined

Modal — 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()