13. Dialogs

A dialog is a small window that presents information to the users and prompts them for a response. A dialog can be modal, in which case the user cannot continue without closing it, or modeless, where the user can continue work while the dialog is still open.1 Qt offers several standard dialogs while also letting developers create custom ones by subclassing the QDialog class.

Qt standard dialogs2:

Name Description
QColorDialog Dialog widget for choosing colors
QFileDialog Dialog that allows users to select files or directories
QFontDialog Dialog widget for selecting a font
QInputDialog Convenience dialog to get a single value from the user
QMessageBox Modal dialog for informing the user or for asking the user a question and receiving an answer
QProgressDialog Feedback on the progress of a slow operation

[TODO: A NOTE ON PARENTS]

13.1 Standard Message Dialogs with QMessageBox

QMessageBox is a modal dialog for providing information to the user or asking a question and receiving an answer. A message box can display a text message, an icon and Qt’s standard buttons for accepting the user’s response3.

An icon of a clipboard-list1

You are building a simple note-taking application where users can save their notes. To confirm actions like discarding unsaved changes, you decide to use a standard message dialog to prompt the user before closing the window.

To use a message box in your application:

  1. Create a QMessageBox object. In the example, we detect when the user attempts to close the application by overriding the main window’s closeEvent(). The document is stored in a text edit and we only show the message box if the document’s isModified() property is true.

  2. Set the message box properties. We set the title, icon, text, and informative text to provide additional information to the user (for even more details, use detailedText()). We also add three standard buttons, Save, Discard and Cancel, and set Save as the default.

  3. Display the message box using exec(), making it modal, and handle the user response. The message box’s return value is one of the standard button enumeration values: if the user presses Save, we simulate saving the document and set its modified() property to false; if the user presses Discard we continue without saving the document; and if the user presses Cancel we ignore the close event and the application remains open.

13.2 Input Dialogs with QInputDialog

Whereas QMessageBox typically returns a QMessageBox.StandardButton value, QinputDialog can return single-line or multiline text, an integer, a double, or a string selected from a list.

An icon of a clipboard-list1

In your note-taking app, users need to give each note a title. You opt for a simple input dialog to enter text, and set the opened note title.

To use a QInputDialog in your application:

  1. Provide a way for the user to invoke the dialog. We create a QAction and connect its triggered() signal to the set_note_title() slot.

  2. Show the dialog. When the user triggers the action, display the input dialog using one of the QInputDialog’s static methods:

    Method Description
    getDouble() Gets a floating point number from the user
    getInt() Gets an integer from the user
    getItem() Gets an item from a list
    getMultiLineText() Gets multi-line text input
    getText() Gets a single line of text

    In the example, the user needs to enter a string so we use getText().

  3. Check the return value and handle the user response. getText() returns a tuple:

    1 (text, ok)
    

    text is the string the user entered. ok will be true if the user presses Ok and false if the user presses Cancel. If ok is true, set the note title and update the action’s icon indicating the note has a title.

13.3 File Dialogs with QFileDialog

QFileDialog lets users select files or directories. The easiest approach is using one of its static methods4:

Method Description
getExistingDirectory() Select a directory
getExistingDirectoryUrl() Select a directory (URL)
getOpenFileContent() Open file and read content
getOpenFileName() Select a single file to open
getOpenFileNames() Select multiple files to open
getOpenFileUrl() Select a file to open (URL)
getOpenFileUrls() Select multiple files (URLs)
getSaveFileName() Select a file name to save
getSaveFileUrl() Select a file to save (URL)
saveFileContent() Save content to file

Behind the scenes, QFileDialog uses a platform-native file dialog if one is available, resulting in different appearence accross platforms.

An icon of a clipboard-list1

For a note-taking application, you need to let users open an existing file and save a new one. Implement a file dialog to handle file selection with options for filtering by file types.

To use a file dialog in your application:

  1. Give users a way to display the dialog. Create two QActions, one for saving and one for opening a file. For both actions, set text, a shortcut and an icon. Connect each action’s triggered() signal to a slot - save_note() for the save action and open_note() for the open action.

  2. Display the dialog. In open_note() we use getOpenFileName(). In save_note(), the file dialog is shown only if the note has not been already saved. For both dialogs set the title, the starting directory and the file filter.

  3. Use the return value to handle the user’s response. getSaveFileName() returns a tuple:

1 (fileName, selectedFilter)

If the user presses Cancel, fileName is an empty string so we don’t need to do anything. If the user presses the Save button, we save the contents of the text edit into fileName.

Likewise, we use fileName to read the file contents into the text edit only if getOpenFileName() does not return an empty string.

13.4 Color Selection with QColorDialog

QColorDialog allows users to select colors. You typically use its getColor() static method to show it as a modal dialog5.

An icon of a clipboard-list1

Users of your note-taking application want to be able to change their note text and background colors. You use a color dialog to allow selecting a color from a palette without building a custom color picker.

To use a color dialog in your application:

  1. Provide a way for users to display the dialog. In the main window’s __init__(), create actions for selecting the foreground and background colors. Connect the actions to the slots and add the them to the the main window’s menu bar and toolbar.

  2. Show the dialog. We want both dialogs to open with the current text colors. foreground() and background() are QBrush objects, so we extract their colors and use them as the dialogs’ initial colors.

  3. If the dialog returns a valid color use it in your application. Unlike QInputDialog and QFileDialog, QColorDialog does not return a tuple - it always returns a QColor object, so we need to check if it isValid() to confirm that the user pressed Ok.

13.5 Font Selection with QFontDialog

QFontDialog provides a dialog for selecting a font. It is created by invoking one of the static getFont() methods6:

  • getFont(parent)
  • getFont(initial, parent, title, options)
An icon of a clipboard-list1

AYou need to add font selection to your note-taking application’s formatting toolbar. You use a font dialog to let users choose family, style, size, and effects.

To use a font dialog in your application:

  1. Create an action to trigger the dialog.

  2. Show the dialog to the user. In set_font(), we get the current QFont from the text edit’s currentCharFormat() and pass it to getFont() so the dialog opens with that font selected.

  3. If the user presses Ok, update the font. getFont() returns a tuple where the first element, ok, is true if the user pressed Ok and false otherwise. The second element is a QFont object representing the font the user selected.

13.6 Creating Custom Dialogs by Subclassing QDialog

Standard dialogs are straightforward to use - you display them using static methods and handle the result based on which button the user pressed. They are designed to fiy most common use cases like showing messages, choosing colors, files and folders, fonts, and accepting user input. For more complex or custom dialogs, however, you can subclass the QDialog class and create your own.

QDialog is the base class of all the Qt standard dialogs, implementing the slots common to all of them:

Slot Description
accept() Closes dialog with Accepted result
done(int r) Closes dialog with specified result code
exec() Shows dialog modally, returns result code
open() Shows dialog non-modally
reject() Closes dialog with Rejected result

and their common methods:

Method Description
isSizeGripEnabled() Returns if resize grip is enabled
result() Returns the dialog’s result code
setModal(bool) Sets whether dialog is modal
setResult(int) Sets the dialog’s result code
setSizeGripEnabled(bool) Enables/disables resize grip

signals:

Signal Description
accepted() Emitted when dialog is accepted
finished(int) Emitted when dialog closes with result code
rejected() Emitted when dialog is rejected

and properties:

Property Description
modal Whether dialog blocks input to other windows
sizeGripEnabled Whether dialog has a resize grip

Set result() to one of the QDialog.DialogCode values, Accepted or Rejected.

The QDialogButtonBox class, commonly used with QDialog, automatically arranges standard buttons in a layout appropriate for the user’s desktop environment. For instance, Windows places the OK button before Cancel, while Gnome reverses this order.

An icon of a clipboard-list1

For a user preferences panel in your application, you need a dialog with multiple input fields and buttons. Create a custom dialog subclass to organize these elements and handle acceptance/rejection.

To create a custom Qt dialog:

  1. Create a QDialog subclass. We create a class named SettingsDialog, set its window title and set it to be modal.

  2. Add the child widgets to the dialog. In the example, we create three widgets:

    • A checkbox to set whether the application should auto-save the current note or not,
    • A spinbox to set the auto-save interval,
    • A checkbox to make the application reopen the last edited note. The spinbox is enabled only if the auto-save checkbox is checked and lets the user select values between one and sixty minutes.
  3. Add QDialogButtonBox to the dialog. We want the application to have a native look on multiple platforms so we add a button box with the Ok and Cancel buttons. We also connect the button box accepted signal to accept() and the rejected signal to reject(). The current widget values are saved to a .ini file using QSettings.

  1. Use the custom dialog in your application. In the main window, we create the settings action and, when it’s triggered, show our custom dialog so the user can edit the settings.

  1. If you don’t implement __init__() in your class at all, the parent class gets initalized automatically.↩︎

  2. https://doc.qt.io/qtforpython-6/↩︎

  3. https://doc.qt.io/↩︎

  4. https://doc.qt.io/qt-6/qobject.html↩︎

  5. https://doc.qt.io/qt-6/qcolordialog.html↩︎

  6. https://doc.qt.io/qt-6/qfontdialog.html↩︎