18. Dialogs
Dialog windows are very similar to standard windows, and are used to provide or retrieve information from the user. They are often used to provide a preferences window, for example. The major difference a dialog has is some prepacked widgets which layout the dialog automatically. From there, we can simply add labels, buttons, check buttons, etc. Another big difference is the handling of responses to control how the application should behave after the dialog has been interacted with.
There are several derived Dialog classes which you might find useful.
Gtk.MessageDialog is used for most simple notifications. But at other
times you might need to derive your own dialog class to provide more complex
functionality.
18.1. Custom Dialogs
To pack widgets into a custom dialog, you should pack them into the
Gtk.Box, available via Gtk.Dialog.get_content_area(). To just add
a Gtk.Button to the bottom of the dialog, you could use the
Gtk.Dialog.add_button() method.
A ‘modal’ dialog (that is, one which freezes the rest of the application from user
input), can be created by calling Gtk.Dialog.set_modal on the dialog or
set the flags argument of the Gtk.Dialog constructor to include
the Gtk.DialogFlags.MODAL flag.
Clicking a button will emit a signal called "response". If you want to block
waiting for a dialog to return before returning control flow to your code, you
can call Gtk.Dialog.run(). This method returns an int which may be a value
from the Gtk.ResponseType or it could be the custom response value that
you specified in the Gtk.Dialog constructor or Gtk.Dialog.add_button().
Finally, there are two ways to remove a dialog.
The Gtk.Widget.hide() method removes the dialog from view, however keeps
it stored in memory. This is useful to prevent having to construct the dialog
again if it needs to be accessed at a later time. Alternatively, the
Gtk.Widget.destroy() method can be used to delete the dialog from memory
once it is no longer needed. It should be noted that if the dialog needs to be
accessed after it has been destroyed, it will need to be constructed again
otherwise the dialog window will be empty.
18.1.1. Example
_images/dialog_example.png1importgi 2 3gi.require_version("Gtk", "3.0") 4fromgi.repositoryimport Gtk 5 6 7classDialogExample(Gtk.Dialog): 8 def__init__(self, parent): 9 super().__init__(title="My Dialog", transient_for=parent, flags=0) 10 self.add_buttons( 11 Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK 12 ) 13 14 self.set_default_size(150, 100) 15 16 label = Gtk.Label(label="This is a dialog to display additional information") 17 18 box = self.get_content_area() 19 box.add(label) 20 self.show_all() 21 22 23classDialogWindow(Gtk.Window): 24 def__init__(self): 25 Gtk.Window.__init__(self, title="Dialog Example") 26 27 self.set_border_width(6) 28 29 button = Gtk.Button(label="Open dialog") 30 button.connect("clicked", self.on_button_clicked) 31 32 self.add(button) 33 34 defon_button_clicked(self, widget): 35 dialog = DialogExample(self) 36 response = dialog.run() 37 38 if response == Gtk.ResponseType.OK: 39 print("The OK button was clicked") 40 elif response == Gtk.ResponseType.CANCEL: 41 print("The Cancel button was clicked") 42 43 dialog.destroy() 44 45 46win = DialogWindow() 47win.connect("destroy", Gtk.main_quit) 48win.show_all() 49Gtk.main()
18.2. MessageDialog
Gtk.MessageDialog is a convenience class, used to create simple,
standard message dialogs, with a message, an icon, and buttons for user response.
You can specify the type of message and the text in the Gtk.MessageDialog
constructor, as well as specifying standard buttons.
In some dialogs which require some further explanation of what has happened,
a secondary text can be added. In this case, the primary message entered when
creating the message dialog is made bigger and set to bold text. The secondary
message can be set by calling Gtk.MessageDialog.format_secondary_text().
18.2.1. Example
_images/messagedialog_example.png1importgi 2 3gi.require_version("Gtk", "3.0") 4fromgi.repositoryimport Gtk 5 6 7classMessageDialogWindow(Gtk.Window): 8 def__init__(self): 9 super().__init__(title="MessageDialog Example") 10 11 box = Gtk.Box(spacing=6) 12 self.add(box) 13 14 button1 = Gtk.Button(label="Information") 15 button1.connect("clicked", self.on_info_clicked) 16 box.add(button1) 17 18 button2 = Gtk.Button(label="Error") 19 button2.connect("clicked", self.on_error_clicked) 20 box.add(button2) 21 22 button3 = Gtk.Button(label="Warning") 23 button3.connect("clicked", self.on_warn_clicked) 24 box.add(button3) 25 26 button4 = Gtk.Button(label="Question") 27 button4.connect("clicked", self.on_question_clicked) 28 box.add(button4) 29 30 defon_info_clicked(self, widget): 31 dialog = Gtk.MessageDialog( 32 transient_for=self, 33 flags=0, 34 message_type=Gtk.MessageType.INFO, 35 buttons=Gtk.ButtonsType.OK, 36 text="This is an INFO MessageDialog", 37 ) 38 dialog.format_secondary_text( 39 "And this is the secondary text that explains things." 40 ) 41 dialog.run() 42 print("INFO dialog closed") 43 44 dialog.destroy() 45 46 defon_error_clicked(self, widget): 47 dialog = Gtk.MessageDialog( 48 transient_for=self, 49 flags=0, 50 message_type=Gtk.MessageType.ERROR, 51 buttons=Gtk.ButtonsType.CANCEL, 52 text="This is an ERROR MessageDialog", 53 ) 54 dialog.format_secondary_text( 55 "And this is the secondary text that explains things." 56 ) 57 dialog.run() 58 print("ERROR dialog closed") 59 60 dialog.destroy() 61 62 defon_warn_clicked(self, widget): 63 dialog = Gtk.MessageDialog( 64 transient_for=self, 65 flags=0, 66 message_type=Gtk.MessageType.WARNING, 67 buttons=Gtk.ButtonsType.OK_CANCEL, 68 text="This is an WARNING MessageDialog", 69 ) 70 dialog.format_secondary_text( 71 "And this is the secondary text that explains things." 72 ) 73 response = dialog.run() 74 if response == Gtk.ResponseType.OK: 75 print("WARN dialog closed by clicking OK button") 76 elif response == Gtk.ResponseType.CANCEL: 77 print("WARN dialog closed by clicking CANCEL button") 78 79 dialog.destroy() 80 81 defon_question_clicked(self, widget): 82 dialog = Gtk.MessageDialog( 83 transient_for=self, 84 flags=0, 85 message_type=Gtk.MessageType.QUESTION, 86 buttons=Gtk.ButtonsType.YES_NO, 87 text="This is an QUESTION MessageDialog", 88 ) 89 dialog.format_secondary_text( 90 "And this is the secondary text that explains things." 91 ) 92 response = dialog.run() 93 if response == Gtk.ResponseType.YES: 94 print("QUESTION dialog closed by clicking YES button") 95 elif response == Gtk.ResponseType.NO: 96 print("QUESTION dialog closed by clicking NO button") 97 98 dialog.destroy() 99 100 101win = MessageDialogWindow() 102win.connect("destroy", Gtk.main_quit) 103win.show_all() 104Gtk.main()
18.3. FileChooserDialog
The Gtk.FileChooserDialog is suitable for use with "File/Open" or
"File/Save" menu items. You can use all of the Gtk.FileChooser methods
on the file chooser dialog as well as those for Gtk.Dialog.
When creating a Gtk.FileChooserDialog you have to define the dialog’s
purpose:
To select a file for opening, as for a File/Open command, use
Gtk.FileChooserAction.OPENTo save a file for the first time, as for a File/Save command, use
Gtk.FileChooserAction.SAVE, and suggest a name such as "Untitled" withGtk.FileChooser.set_current_name().To save a file under a different name, as for a File/Save As command, use
Gtk.FileChooserAction.SAVE, and set the existing filename withGtk.FileChooser.set_filename().To choose a folder instead of a file, use
Gtk.FileChooserAction.SELECT_FOLDER.
Gtk.FileChooserDialog inherits from Gtk.Dialog, so buttons have
response IDs such as Gtk.ResponseType.ACCEPT and Gtk.ResponseType.CANCEL
which can be specified in the Gtk.FileChooserDialog constructor.
In contrast to Gtk.Dialog, you can not use custom response codes with
Gtk.FileChooserDialog. It expects that at least one button will have
of the following response IDs:
When the user is finished selecting files, your program can get the selected
names either as filenames (Gtk.FileChooser.get_filename()) or as URIs
(Gtk.FileChooser.get_uri()).
By default, Gtk.FileChooser only allows a single file to be selected at
a time. To enable multiple files to be selected, use
Gtk.FileChooser.set_select_multiple(). Retrieving a list of selected files
is possible with either Gtk.FileChooser.get_filenames() or
Gtk.FileChooser.get_uris().
Gtk.FileChooser also supports a variety of options which make the files
and folders more configurable and accessible.
Gtk.FileChooser.set_local_only(): Only local files can be selected.
Gtk.FileChooser.show_hidden(): Hidden files and folders are displayed.
Gtk.FileChooser.set_do_overwrite_confirmation(): If the file chooser was configured inGtk.FileChooserAction.SAVEmode, it will present a confirmation dialog if the user types a file name that already exists.
Furthermore, you can specify which kind of files are displayed by creating
Gtk.FileFilter objects and calling Gtk.FileChooser.add_filter().
The user can then select one of the added filters from a combo box at the bottom
of the file chooser.
18.3.1. Example
_images/filechooserdialog_example.png1importgi 2 3gi.require_version("Gtk", "3.0") 4fromgi.repositoryimport Gtk 5 6 7classFileChooserWindow(Gtk.Window): 8 def__init__(self): 9 super().__init__(title="FileChooser Example") 10 11 box = Gtk.Box(spacing=6) 12 self.add(box) 13 14 button1 = Gtk.Button(label="Choose File") 15 button1.connect("clicked", self.on_file_clicked) 16 box.add(button1) 17 18 button2 = Gtk.Button(label="Choose Folder") 19 button2.connect("clicked", self.on_folder_clicked) 20 box.add(button2) 21 22 defon_file_clicked(self, widget): 23 dialog = Gtk.FileChooserDialog( 24 title="Please choose a file", parent=self, action=Gtk.FileChooserAction.OPEN 25 ) 26 dialog.add_buttons( 27 Gtk.STOCK_CANCEL, 28 Gtk.ResponseType.CANCEL, 29 Gtk.STOCK_OPEN, 30 Gtk.ResponseType.OK, 31 ) 32 33 self.add_filters(dialog) 34 35 response = dialog.run() 36 if response == Gtk.ResponseType.OK: 37 print("Open clicked") 38 print("File selected: " + dialog.get_filename()) 39 elif response == Gtk.ResponseType.CANCEL: 40 print("Cancel clicked") 41 42 dialog.destroy() 43 44 defadd_filters(self, dialog): 45 filter_text = Gtk.FileFilter() 46 filter_text.set_name("Text files") 47 filter_text.add_mime_type("text/plain") 48 dialog.add_filter(filter_text) 49 50 filter_py = Gtk.FileFilter() 51 filter_py.set_name("Python files") 52 filter_py.add_mime_type("text/x-python") 53 dialog.add_filter(filter_py) 54 55 filter_any = Gtk.FileFilter() 56 filter_any.set_name("Any files") 57 filter_any.add_pattern("*") 58 dialog.add_filter(filter_any) 59 60 defon_folder_clicked(self, widget): 61 dialog = Gtk.FileChooserDialog( 62 title="Please choose a folder", 63 parent=self, 64 action=Gtk.FileChooserAction.SELECT_FOLDER, 65 ) 66 dialog.add_buttons( 67 Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK 68 ) 69 dialog.set_default_size(800, 400) 70 71 response = dialog.run() 72 if response == Gtk.ResponseType.OK: 73 print("Select clicked") 74 print("Folder selected: " + dialog.get_filename()) 75 elif response == Gtk.ResponseType.CANCEL: 76 print("Cancel clicked") 77 78 dialog.destroy() 79 80 81win = FileChooserWindow() 82win.connect("destroy", Gtk.main_quit) 83win.show_all() 84Gtk.main()