Skip to content

Dialogs

Usage

A dialog is a short-lived window that requires the user to provide acknowledgement, respond to a question, or provide information to the application.

A dialog can be presented relative to a specific window (a window-modal dialog), and relative to the entire app (an app-modal dialog). When presented as a window-modal dialog, the user will not be able to interact with anything in the window until the dialog is dismissed. When presented as an app-modal dialog, the user will be restricted from interacting with the rest of the app (there are some platform-specific variations in this behavior; see the platform notes for details).

When a dialog is presented, the app's event loop will continue to run, and the content of the app windows will redraw if requested by the event loop. For this reason, dialogs are implemented asynchronously - that is, they must be await-ed in the context of an async method. The value returned by the await is the response of the dialog; the return type will vary depending on the type of dialog being displayed.

To display a dialog, create an instance of the dialog type you want to display, and await the dialog() method in the context that you want to display the dialog (either toga.Window.dialog() or toga.App.dialog()). In the following example, my_handler is an asynchronous method defined on an App subclass that would be installed as an event handler (e.g., as an on_press() handler on a Button). The dialog is displayed as window-modal against the app's main window; the dialog returns True or False depending on the user's response:

async def my_handler(self, widget, **kwargs):
    ask_a_question = toga.QuestionDialog("Hello!", "Is this OK!")

    if await self.main_window.dialog(ask_a_question):
        print("The user said yes!")
    else:
        print("The user said no.")

When this handler is triggered, the dialog will be displayed, but a print statement will not be executed until the user's response has been received. To convert this example into an app-modal dialog, you would use self.dialog(ask_a_question), instead of self.main_window.dialog(ask_a_question).

If you need to display a dialog in a synchronous context (i.e., in a normal, non-async event handler), you must create a [asyncio.Task][] for the dialog, and install a callback that will be invoked when the dialog is dismissed:

def my_sync_handler(self, widget, **kwargs):
    ask_a_question = toga.QuestionDialog("Hello!", "Is this OK!")

    task = asyncio.create_task(self.main_window.dialog(ask_a_question))
    task.add_done_callback(self.dialog_dismissed)
    print("Dialog has been created")

def dialog_dismissed(self, task):
    if task.result():
        print("The user said yes!")
    else:
        print("The user said no.")

In this example, when my_sync_handler is triggered, a dialog will be created, the display of that dialog will be scheduled as an asynchronous task, and a message will be logged saying the dialog has been created. When the user responds, the dialog_dismissed callback will be invoked, with the dialog task provided as an argument. The result of the task can then be interrogated to handle the response.

Notes

  • On macOS, app-modal dialogs will not prevent the user from interacting with the rest of the app.
  • On Linux (Qt), the SelectFolderDialog does not support multiple selection.

Reference

Bases: Dialog[None]

Source code in core/src/toga/dialogs.py
48
49
50
51
52
53
54
55
56
57
58
59
60
class InfoDialog(Dialog[None]):
    def __init__(self, title: str, message: str) -> None:
        """Ask the user to acknowledge some information.

        Presents as a dialog with a single "OK" button to close the dialog.

        Returns a response of `None`.

        :param title: The title of the dialog window.
        :param message: The message to display.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.InfoDialog(title=title, message=message)

__init__(title, message)

Ask the user to acknowledge some information.

Presents as a dialog with a single "OK" button to close the dialog.

Returns a response of None.

:param title: The title of the dialog window. :param message: The message to display.

Source code in core/src/toga/dialogs.py
49
50
51
52
53
54
55
56
57
58
59
60
def __init__(self, title: str, message: str) -> None:
    """Ask the user to acknowledge some information.

    Presents as a dialog with a single "OK" button to close the dialog.

    Returns a response of `None`.

    :param title: The title of the dialog window.
    :param message: The message to display.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.InfoDialog(title=title, message=message)

Bases: Dialog[bool]

Source code in core/src/toga/dialogs.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
class QuestionDialog(Dialog[bool]):
    def __init__(self, title: str, message: str) -> None:
        """Ask the user a yes/no question.

        Presents as a dialog with "Yes" and "No" buttons.

        Returns a response of `True` when the "Yes" button is pressed, `False` when
        the "No" button is pressed.

        :param title: The title of the dialog window.
        :param message: The question to be answered.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.QuestionDialog(title=title, message=message)

__init__(title, message)

Ask the user a yes/no question.

Presents as a dialog with "Yes" and "No" buttons.

Returns a response of True when the "Yes" button is pressed, False when the "No" button is pressed.

:param title: The title of the dialog window. :param message: The question to be answered.

Source code in core/src/toga/dialogs.py
64
65
66
67
68
69
70
71
72
73
74
75
76
def __init__(self, title: str, message: str) -> None:
    """Ask the user a yes/no question.

    Presents as a dialog with "Yes" and "No" buttons.

    Returns a response of `True` when the "Yes" button is pressed, `False` when
    the "No" button is pressed.

    :param title: The title of the dialog window.
    :param message: The question to be answered.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.QuestionDialog(title=title, message=message)

Bases: Dialog[bool]

Source code in core/src/toga/dialogs.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class ConfirmDialog(Dialog[bool]):
    def __init__(self, title: str, message: str) -> None:
        """Ask the user to confirm if they wish to proceed with an action.

        Presents as a dialog with "Cancel" and "OK" buttons (or whatever labels are
        appropriate on the current platform).

        Returns a response of `True` when the "OK" button is pressed, `False` when
        the "Cancel" button is pressed.

        :param title: The title of the dialog window.
        :param message: A message describing the action to be confirmed.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.ConfirmDialog(title=title, message=message)

__init__(title, message)

Ask the user to confirm if they wish to proceed with an action.

Presents as a dialog with "Cancel" and "OK" buttons (or whatever labels are appropriate on the current platform).

Returns a response of True when the "OK" button is pressed, False when the "Cancel" button is pressed.

:param title: The title of the dialog window. :param message: A message describing the action to be confirmed.

Source code in core/src/toga/dialogs.py
80
81
82
83
84
85
86
87
88
89
90
91
92
93
def __init__(self, title: str, message: str) -> None:
    """Ask the user to confirm if they wish to proceed with an action.

    Presents as a dialog with "Cancel" and "OK" buttons (or whatever labels are
    appropriate on the current platform).

    Returns a response of `True` when the "OK" button is pressed, `False` when
    the "Cancel" button is pressed.

    :param title: The title of the dialog window.
    :param message: A message describing the action to be confirmed.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.ConfirmDialog(title=title, message=message)

Bases: Dialog[None]

Source code in core/src/toga/dialogs.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
class ErrorDialog(Dialog[None]):
    def __init__(self, title: str, message: str) -> None:
        """Ask the user to acknowledge an error state.

        Presents as an error dialog with an "OK" button to close the dialog.

        Returns a response of `None`.

        :param title: The title of the dialog window.
        :param message: The error message to display.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.ErrorDialog(title=title, message=message)

__init__(title, message)

Ask the user to acknowledge an error state.

Presents as an error dialog with an "OK" button to close the dialog.

Returns a response of None.

:param title: The title of the dialog window. :param message: The error message to display.

Source code in core/src/toga/dialogs.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
def __init__(self, title: str, message: str) -> None:
    """Ask the user to acknowledge an error state.

    Presents as an error dialog with an "OK" button to close the dialog.

    Returns a response of `None`.

    :param title: The title of the dialog window.
    :param message: The error message to display.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.ErrorDialog(title=title, message=message)

Bases: Dialog[DialogResultT]

Source code in core/src/toga/dialogs.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
class StackTraceDialog(Dialog[DialogResultT]):
    @overload
    def __init__(
        self: StackTraceDialog[None],
        title: str,
        message: str,
        content: str,
        retry: Literal[False] = ...,
    ) -> None: ...

    @overload
    def __init__(
        self: StackTraceDialog[bool],
        title: str,
        message: str,
        content: str,
        retry: Literal[True],
    ) -> None: ...

    def __init__(
        self, title: str, message: str, content: str, retry: bool = False
    ) -> None:
        """Open a dialog to display a large block of text, such as a stack trace.

        If `retry` is true, returns a response of `True` when the user selects
        "Retry", and `False` when they select "Quit".

        If `retry` is `False`, returns a response of `None`.

        :param title: The title of the dialog window.
        :param message: Contextual information about the source of the stack trace.
        :param content: The stack trace, pre-formatted as a multi-line string.
        :param retry: If true, the user will be given options to "Retry" or "Quit"; if
            false, a single option to acknowledge the error will be displayed.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.StackTraceDialog(
            title=title,
            message=message,
            content=content,
            retry=retry,
        )

__init__(title, message, content, retry=False)

__init__(
    title: str,
    message: str,
    content: str,
    retry: Literal[False] = ...,
) -> None
__init__(
    title: str,
    message: str,
    content: str,
    retry: Literal[True],
) -> None

Open a dialog to display a large block of text, such as a stack trace.

If retry is true, returns a response of True when the user selects "Retry", and False when they select "Quit".

If retry is False, returns a response of None.

:param title: The title of the dialog window. :param message: Contextual information about the source of the stack trace. :param content: The stack trace, pre-formatted as a multi-line string. :param retry: If true, the user will be given options to "Retry" or "Quit"; if false, a single option to acknowledge the error will be displayed.

Source code in core/src/toga/dialogs.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
def __init__(
    self, title: str, message: str, content: str, retry: bool = False
) -> None:
    """Open a dialog to display a large block of text, such as a stack trace.

    If `retry` is true, returns a response of `True` when the user selects
    "Retry", and `False` when they select "Quit".

    If `retry` is `False`, returns a response of `None`.

    :param title: The title of the dialog window.
    :param message: Contextual information about the source of the stack trace.
    :param content: The stack trace, pre-formatted as a multi-line string.
    :param retry: If true, the user will be given options to "Retry" or "Quit"; if
        false, a single option to acknowledge the error will be displayed.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.StackTraceDialog(
        title=title,
        message=message,
        content=content,
        retry=retry,
    )

Bases: Dialog[Path | None]

Source code in core/src/toga/dialogs.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class SaveFileDialog(Dialog[Path | None]):
    def __init__(
        self,
        title: str,
        suggested_filename: Path | str,
        file_types: list[str] | None = None,
    ) -> None:
        """Prompt the user for a location to save a file.

        This dialog is not currently supported on Android or iOS.

        Returns a path object for the selected file location, or `None` if the user
        cancelled the save operation.

        If the filename already exists, the user will be prompted to confirm they want
        to overwrite the existing file.

        :param title: The title of the dialog window
        :param suggested_filename: The initial suggested filename
        :param file_types: The allowed filename extensions, without leading dots. If not
            provided, any extension will be allowed.
        """
        # Convert suggested filename to a path (if it isn't already),
        # and break it into a filename and a directory
        suggested_path = Path(suggested_filename)
        initial_directory: Path | None = suggested_path.parent
        if initial_directory == Path("."):
            initial_directory = None
        filename = suggested_path.name

        self.factory = get_factory()
        self._impl = self.factory.dialogs.SaveFileDialog(
            title=title,
            filename=filename,
            initial_directory=initial_directory,
            file_types=file_types,
        )

__init__(title, suggested_filename, file_types=None)

Prompt the user for a location to save a file.

This dialog is not currently supported on Android or iOS.

Returns a path object for the selected file location, or None if the user cancelled the save operation.

If the filename already exists, the user will be prompted to confirm they want to overwrite the existing file.

:param title: The title of the dialog window :param suggested_filename: The initial suggested filename :param file_types: The allowed filename extensions, without leading dots. If not provided, any extension will be allowed.

Source code in core/src/toga/dialogs.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def __init__(
    self,
    title: str,
    suggested_filename: Path | str,
    file_types: list[str] | None = None,
) -> None:
    """Prompt the user for a location to save a file.

    This dialog is not currently supported on Android or iOS.

    Returns a path object for the selected file location, or `None` if the user
    cancelled the save operation.

    If the filename already exists, the user will be prompted to confirm they want
    to overwrite the existing file.

    :param title: The title of the dialog window
    :param suggested_filename: The initial suggested filename
    :param file_types: The allowed filename extensions, without leading dots. If not
        provided, any extension will be allowed.
    """
    # Convert suggested filename to a path (if it isn't already),
    # and break it into a filename and a directory
    suggested_path = Path(suggested_filename)
    initial_directory: Path | None = suggested_path.parent
    if initial_directory == Path("."):
        initial_directory = None
    filename = suggested_path.name

    self.factory = get_factory()
    self._impl = self.factory.dialogs.SaveFileDialog(
        title=title,
        filename=filename,
        initial_directory=initial_directory,
        file_types=file_types,
    )

Bases: Dialog[DialogResultT]

Source code in core/src/toga/dialogs.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
class OpenFileDialog(Dialog[DialogResultT]):
    @overload
    def __init__(
        self: OpenFileDialog[Path],
        title: str,
        initial_directory: Path | str | None = None,
        file_types: list[str] | None = None,
        multiple_select: Literal[False] = ...,
    ) -> None: ...

    @overload
    def __init__(
        self: OpenFileDialog[list[Path]],
        title: str,
        initial_directory: Path | str | None = None,
        file_types: list[str] | None = None,
        *,
        multiple_select: Literal[True],
    ) -> None: ...

    def __init__(
        self,
        title: str,
        initial_directory: Path | str | None = None,
        file_types: list[str] | None = None,
        multiple_select: bool = False,
    ) -> None:
        """Prompt the user to select a file (or files) to open.

        This dialog is not currently supported on Android or iOS.

        If `multiple_select` is `True`, returns a list of `Path` objects.

        If `multiple_select` is `False`, returns a single `Path`.

        Returns `None` if the open operation is cancelled by the user.

        :param title: The title of the dialog window
        :param initial_directory: The initial folder in which to open the dialog. If
            `None`, use the default location provided by the operating system (which
            will often be the last used location)
        :param file_types: The allowed filename extensions, without leading dots. If not
            provided, all files will be shown.
        :param multiple_select: If True, the user will be able to select multiple files;
            if False, the selection will be restricted to a single file.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.OpenFileDialog(
            title=title,
            initial_directory=Path(initial_directory) if initial_directory else None,
            file_types=file_types,
            multiple_select=multiple_select,
        )

__init__(title, initial_directory=None, file_types=None, multiple_select=False)

__init__(
    title: str,
    initial_directory: Path | str | None = None,
    file_types: list[str] | None = None,
    multiple_select: Literal[False] = ...,
) -> None
__init__(
    title: str,
    initial_directory: Path | str | None = None,
    file_types: list[str] | None = None,
    *,
    multiple_select: Literal[True],
) -> None

Prompt the user to select a file (or files) to open.

This dialog is not currently supported on Android or iOS.

If multiple_select is True, returns a list of Path objects.

If multiple_select is False, returns a single Path.

Returns None if the open operation is cancelled by the user.

:param title: The title of the dialog window :param initial_directory: The initial folder in which to open the dialog. If None, use the default location provided by the operating system (which will often be the last used location) :param file_types: The allowed filename extensions, without leading dots. If not provided, all files will be shown. :param multiple_select: If True, the user will be able to select multiple files; if False, the selection will be restricted to a single file.

Source code in core/src/toga/dialogs.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
def __init__(
    self,
    title: str,
    initial_directory: Path | str | None = None,
    file_types: list[str] | None = None,
    multiple_select: bool = False,
) -> None:
    """Prompt the user to select a file (or files) to open.

    This dialog is not currently supported on Android or iOS.

    If `multiple_select` is `True`, returns a list of `Path` objects.

    If `multiple_select` is `False`, returns a single `Path`.

    Returns `None` if the open operation is cancelled by the user.

    :param title: The title of the dialog window
    :param initial_directory: The initial folder in which to open the dialog. If
        `None`, use the default location provided by the operating system (which
        will often be the last used location)
    :param file_types: The allowed filename extensions, without leading dots. If not
        provided, all files will be shown.
    :param multiple_select: If True, the user will be able to select multiple files;
        if False, the selection will be restricted to a single file.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.OpenFileDialog(
        title=title,
        initial_directory=Path(initial_directory) if initial_directory else None,
        file_types=file_types,
        multiple_select=multiple_select,
    )

Bases: Dialog[DialogResultT]

Source code in core/src/toga/dialogs.py
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
class SelectFolderDialog(Dialog[DialogResultT]):
    @overload
    def __init__(
        self: SelectFolderDialog[Path],
        title: str,
        initial_directory: Path | str | None = None,
        multiple_select: Literal[False] = ...,
    ) -> None: ...

    @overload
    def __init__(
        self: SelectFolderDialog[list[Path]],
        title: str,
        initial_directory: Path | str | None = None,
        *,
        multiple_select: Literal[True],
    ) -> None: ...

    def __init__(
        self,
        title: str,
        initial_directory: Path | str | None = None,
        multiple_select: bool = False,
    ) -> None:
        """Prompt the user to select a directory (or directories).

        This dialog is not currently supported on Android or iOS.

        If `multiple_select` is `True`, returns a list of `Path` objects.

        If `multiple_select` is `False`, returns a single `Path`.

        Returns `None` if the select operation is cancelled by the user.

        :param title: The title of the dialog window
        :param initial_directory: The initial folder in which to open the dialog. If
            `None`, use the default location provided by the operating system (which
            will often be "last used location")
        :param multiple_select: If True, the user will be able to select multiple
            directories; if False, the selection will be restricted to a single
            directory. This option is not supported on WinForms.
        """
        self.factory = get_factory()
        self._impl = self.factory.dialogs.SelectFolderDialog(
            title=title,
            initial_directory=Path(initial_directory) if initial_directory else None,
            multiple_select=multiple_select,
        )

__init__(title, initial_directory=None, multiple_select=False)

__init__(
    title: str,
    initial_directory: Path | str | None = None,
    multiple_select: Literal[False] = ...,
) -> None
__init__(
    title: str,
    initial_directory: Path | str | None = None,
    *,
    multiple_select: Literal[True],
) -> None

Prompt the user to select a directory (or directories).

This dialog is not currently supported on Android or iOS.

If multiple_select is True, returns a list of Path objects.

If multiple_select is False, returns a single Path.

Returns None if the select operation is cancelled by the user.

:param title: The title of the dialog window :param initial_directory: The initial folder in which to open the dialog. If None, use the default location provided by the operating system (which will often be "last used location") :param multiple_select: If True, the user will be able to select multiple directories; if False, the selection will be restricted to a single directory. This option is not supported on WinForms.

Source code in core/src/toga/dialogs.py
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
def __init__(
    self,
    title: str,
    initial_directory: Path | str | None = None,
    multiple_select: bool = False,
) -> None:
    """Prompt the user to select a directory (or directories).

    This dialog is not currently supported on Android or iOS.

    If `multiple_select` is `True`, returns a list of `Path` objects.

    If `multiple_select` is `False`, returns a single `Path`.

    Returns `None` if the select operation is cancelled by the user.

    :param title: The title of the dialog window
    :param initial_directory: The initial folder in which to open the dialog. If
        `None`, use the default location provided by the operating system (which
        will often be "last used location")
    :param multiple_select: If True, the user will be able to select multiple
        directories; if False, the selection will be restricted to a single
        directory. This option is not supported on WinForms.
    """
    self.factory = get_factory()
    self._impl = self.factory.dialogs.SelectFolderDialog(
        title=title,
        initial_directory=Path(initial_directory) if initial_directory else None,
        multiple_select=multiple_select,
    )