{"id":164827,"date":"2019-11-22T10:00:13","date_gmt":"2019-11-22T04:30:13","guid":{"rendered":"https:\/\/www.digitalvidya.com\/blog\/?p=164827"},"modified":"2024-05-28T10:08:17","modified_gmt":"2024-05-28T04:38:17","slug":"build-gui-with-wxpython","status":"publish","type":"post","link":"https:\/\/www.digitalvidya.com\/blog\/build-gui-with-wxpython\/","title":{"rendered":"How to Build a Python GUI Application With wxPython?"},"content":{"rendered":"<p dir=\"ltr\">WxPython was created by Robin Dunn and Harri Pasanen, an open-source cross-platform toolkit for the creation of Python programming language graphical user interface (GUI) applications. There are many GUI toolkits that can use Python programming language, with PyQt, wxPython, and Tkinter being the most common.<\/p>\n<p dir=\"ltr\">They can run on most Windows, macOS, and Linux operating systems. WxPython is a C++ wrapper for wxWidgets, a free website that can be easily downloaded from the internet.<\/p>\n<p dir=\"ltr\">Python is a programming language that was developed and published in 1991 by Guido van Rossum. It is a vibrant language inspired by programming languages from ABC and Haskell.<\/p>\n<p dir=\"ltr\">Python is a high-level, particular-purpose, cross-platform language and is widely used worldwide as a minimalist language that is easy to understand. Python&#8217;s most amazing feature is that it uses no semicolon or brackets instead of an indentation.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"wxpython-modules\"><\/span><strong>wxPython Modules\u00a0<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<figure id=\"attachment_165552\" aria-describedby=\"caption-attachment-165552\" style=\"width: 467px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-165552\" src=\"https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/wxpython-mini-logo.jpg\" alt=\"wxPython Modules\u00a0\" width=\"467\" height=\"355\" title=\"\" srcset=\"https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/wxpython-mini-logo.jpg 255w, https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/wxpython-mini-logo-150x114.jpg 150w, https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/wxpython-mini-logo-220x167.jpg 220w\" sizes=\"(max-width: 467px) 100vw, 467px\" \/><figcaption id=\"caption-attachment-165552\" class=\"wp-caption-text\">Wxpython modules\u00a0 source &#8211; tutorials point<\/figcaption><\/figure>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">There are five major wxPython modules namely:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>1. Controls:<\/strong> It is a collection of all the widgets used in a Graphical application. Widgets are also known as controls in the Windows operating system. For example, static text, button, toolbar, editable text control, etc.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>2. Windows:<\/strong> This module contains all the window classes such as a frame, a panel, a dialogue, a scrolled window, etc.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>3. Misc:<\/strong> This module contains various functions and classes of modules that help in various functions such as system settings, the configuration of applications, logging in or controlling the display.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>4. Core:<\/strong> This module contains all the principle class used for the development of graphical user interface-based applications. These classes consist of wxObject class which is the foundation of all other classes, Sizers used for widget layout, basic geometry classes and events.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>5. GDI:<\/strong> wxPython API has a Graphical device interface module which is a collection of classes used for drawing onto the widgets. This contains classes such as color, brush, fonts, images, or pens, etc.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"wxpython-api\"><\/span><strong>wxPython API\u00a0<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">wxPython is a library that is used by programmers to code applications. Since wxPython is a wrapper around wxWidgets, therefore, it is not a native API and hence is not written directly in Python. wxPython has numerous widgets, they are the elementary base of any GUI application. The widgets can be grouped into five categories<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>1. Base widgets:<\/strong> They help the other derived widgets to function through it. They are also known as ancestors and they generally do not function directly. Some of its examples are wxControl, wxWindows, etc.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>2. Top-level widgets:<\/strong> They do not depend on other widgets, such as wxFrame, wxScrolledWindow, wxDialog, wxMDIParentFrame, etc.\u00a0<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>3. Dynamic widgets:<\/strong> These provide users to edit widgets, like wxListBox, wxScrollBar, wxButton, wxRadioButton, wxToggleButton, wxChoice, wxBitmapButton, wxSlider , wxRadioBox, wxGrid, wxSpinButton, wxCheckBox, wxTextCtrl, etc.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>Containers:<\/strong> These widgets contain other widgets such as wxPanel, wxSplitterWindow, wxscrolledWindow, wxNotebook, etc.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>Other widgets:<\/strong> These widgets are wxStatusBar, wxToolbar, wxMenubar, etc.<\/span><\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"inheritance\"><\/span><strong>Inheritance<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">There is a connection between widgets in wxPython, such a relation is formed on the base of inheritance. This is a vital part of the object-oriented programming language. Widgets derive functionality from the other widgets and hence creating inheritance. The widgets which provide the functionality to other widgets are known as parent widgets or base widgets or ancestors, whereas the widgets that inherit are known as child widgets, derived widgets or descendants.\u00a0<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let us understand this if we use a button widget in our application that derives from four other base widgets. The first one being the wx.Control class. A button widget is similar to a tiny window and basically, mostly all widgets that appear on the screen are windows. Thus they derive from wx.Window class. Some of the objects are invisible such as sizers, device context or locale objects. There exist classes which are visible but they are not windows, for example, a colour object, caret object or a cursor object. wx.A dialog is not any type of control, thus not every object a control. The controls are placed on the widgets which are known as containers. The reason due to which it has a separate wx. Control base class.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Every window and button widgets revert to events. By clicking on the button, the wx.EVT_COMMAND_BUTTON_CLICKED event is launched. The button widget derives the wx.EvtHandler through the wx.Window class. Every widget that reacts to events should inherit from wx.EvtHandler class and thus all objects inherit from wx.Object class.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"installing-wxpython\"><\/span><strong>Installing wxPython<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">wxPython 4 the Phoenix release being the latest one should be used here. The wxPython 3 and wxPython 2 are suited only for wxPython 2. Robin Dunn, the developer of wxPython cleared a lot of codes to make wxPython 4 easier to understand and even more Pythonic, it is even suitable for both wxPython 2.7 and wxPython 3.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Following links must be considered if you are migrating from an older version of wxPython to wxPython 4 (Phoenix):<\/span><\/p>\n<p>1. <a href=\"https:\/\/wxpython.org\/Phoenix\/docs\/html\/classic_vs_phoenix.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Classic vs Phoenix<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400;\">2. wxPython Project Phoenix <\/span><a href=\"https:\/\/wxpython.org\/Phoenix\/docs\/html\/MigrationGuide.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Migration Guide<\/span><\/a><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">A pip can be used to install wxPython 4 as following:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">$<\/span><span style=\"font-weight: 400;\"> pip install wxpython<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Note: A compiler will be needed to install it on a macOS such as Xcode, while some dependencies must be installed in Linux before so that it is installed successfully.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">To our advantage, the pip displays an error message which helps us to determine the problem and the ways it could be fixed. The prerequisite section on the wxPython Github page provides certain information that may be useful to install wxPython Linux.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The problem in installing it on Linux can also be solved by using the wheels in the ExtraLinux section with GTK2 and GTK3 versions with the help of the following command:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">$<\/span><span style=\"font-weight: 400;\"> pip install -U -f https:\/\/extras.wxpython.org\/wxPython4\/extras\/linux\/gtk3\/ubuntu-18.04\/ wxPython<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The above command must be altered as per the version of your Linux.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"what-is-a-gui\"><\/span><strong>What is a GUI?\u00a0<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<figure id=\"attachment_165553\" aria-describedby=\"caption-attachment-165553\" style=\"width: 597px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-165553\" src=\"https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/download-1.jpg\" alt=\"What is a GUI?\u00a0\" width=\"597\" height=\"447\" title=\"\" srcset=\"https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/download-1.jpg 259w, https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/download-1-150x112.jpg 150w, https:\/\/www.digitalvidya.com\/blog\/wp-content\/uploads\/2019\/09\/download-1-220x165.jpg 220w\" sizes=\"(max-width: 597px) 100vw, 597px\" \/><figcaption id=\"caption-attachment-165553\" class=\"wp-caption-text\">What is a gui? \u00a0 source &#8211; slideshare<\/figcaption><\/figure>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Graphical User Interface i.e GUI is an interface which is a collection of objects and methods to build a user-friendly screen for interaction.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Graphical User interfaces have some basic components which are:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Main window<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Menu<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Toolbar<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Buttons<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Text Entry<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Labels<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The above items are mainly known as widgets, such widgets are arranged logically on the window by the developer so the user can interact with it.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"event-loops\"><\/span><strong>Event Loops<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">An event occurs when any button is pressed on a widget or anything is typed on the screen, thus the graphical user interface works with events.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The event loop which is an infinite loop is running in the background by the GUI toolkit. Whenever any event is created, the event loop performs the functions coded by the developer for such a specific event on the application, and in case there is no occurrence of any event the event loop simply ignores it.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Each of the widgets must be assigned an event handler for the application to run during the creation of the program for the application.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">One must be very careful while working with the event loops as the GUI tend to get blocked and stop responding which may make the user think as the system is stuck.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">To prevent the GUI from freezing one must consider the following if any process implemented is taking more than a quarter second then a separate thread or process must be assigned for it giving the user a better experience.\u00a0<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">A special thread-safe method is provided by wxPython to communicate back to the thread, or provide information of its completion or to give an update.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">A skeleton application can be used to show how events work.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"creating-a-skeleton-application\"><\/span><b>Creating a Skeleton Application<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">A skeleton application in a Graphical User Interface has widgets without any event handlers, it is kind of a prototype without a logical back end.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let us take a look at\u00a0 the Hello World application with wxPython:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">wx<\/span>\n\n\n\n<span style=\"font-weight: 400;\">app<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">App()<\/span>\n\n<span style=\"font-weight: 400;\">frame<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Hello World'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">frame<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span>\n\n<span style=\"font-weight: 400;\">app<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MainLoop()<\/span>\n\n<span style=\"font-weight: 400;\">Now let us write the same code as a class:<\/span>\n\n<span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">wx<\/span><\/pre>\n<pre><span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">MyFrame(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Hello World'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span><\/pre>\n<pre><span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> __name__ <\/span><span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">'__main__'<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">App()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">frame<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">MyFrame()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MainLoop()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The above code can be used as a guide for other applications.Similarly even more widgets could be added to the application to add presentability to it, so let us gather more information on the widgets.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"widgets\"><\/span><strong>Widgets<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The wxPython has numerous widgets to choose from each one is unique on its own, but the problem arises as to what kind of widget must be used and where to use it? Selection of widgets could be a tedious task so how does one solve this? To resolve such issues wxPython comes with an option known as Demo, it provides a search filter where one can choose the type of widget that is right for their application.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Generally, in a GUI application, a widget responds simply by typing any text or pressing any button. Let us have a look at how such widgets are added:\u00a0<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">wx<\/span>\n\n\n\n<span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">MyFrame(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Hello World'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">panel<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Panel(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">)<\/span><\/pre>\n<pre><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">text_ctrl<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">TextCtrl(panel,<\/span> <span style=\"font-weight: 400;\">pos<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">))<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_btn<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Button(panel,<\/span> <span style=\"font-weight: 400;\">label<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Press Me'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">pos<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">55<\/span><span style=\"font-weight: 400;\">))<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span><\/pre>\n<pre><span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> __name__ <\/span><span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">'__main__'<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">App()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">frame<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">MyFrame()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MainLoop()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">After running this code you will get this application as a final result:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">wx.The panel is the first widget to be used, it is a window on which all controls are placed.This widget if not used then the Tab traversal is disabled. It is not compulsory to use this widget but it is suggested to be used as else one may not get the right shade of gray for the background panel.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">When the panel is the only derivative of the frame then the panel covers up the whole frame to take up all the space in the frame.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Now we add wx. Textctrl to the panel, since the first widget should be a parent widget, therefore, one has to specify a parent widget. The right choice would be a button widget or a textctrl widget.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">the pos parameter is used to designate appropriate positions for the widgets on the frame of wxPython. Then you add your button to the panel and give it a label. To prevent the widgets from overlapping, you need to set the y-coordinate to 55 for the button\u2019s position.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"absolute-positioning\"><\/span><strong>Absolute Positioning<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">When you provide exact coordinates for your widget\u2019s position, the technique that you used is called absolute positioning. Most GUI toolkits provide this capability, but it\u2019s not actually recommended.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">As your application becomes more complex, it becomes difficult to keep track of all the widget locations and if you have to move the widgets around. Resetting all those positions becomes a nightmare.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Fortunately, all modern GUI toolkits provide a solution for this, which is what you will learn about next.<\/span><\/p>\n<p dir=\"ltr\">\n<h3><span class=\"ez-toc-section\" id=\"sizers-dynamic-sizing\"><\/span><strong>Sizers (Dynamic Sizing)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The wxPython toolkit includes sizers, which are used for creating dynamic layouts. They manage the placement of your widgets for you and will adjust them when you resize the application window. Other GUI toolkits will refer to sizers as layouts, which is what PyQt does.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Here are the primary types of sizers that you will see used most often:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.BoxSizer<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.GridSizer<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.FlexGridSizer<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let\u2019s add a wx.BoxSizer to your example and see if we can make it work a bit more nicely:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">wx<\/span>\n\n\n\n<span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">MyFrame(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Hello World'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">panel<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Panel(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_sizer<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BoxSizer(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">VERTICAL)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">text_ctrl<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">TextCtrl(panel)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">text_ctrl,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EXPAND,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_btn<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Button(panel,<\/span> <span style=\"font-weight: 400;\">label<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Press Me'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(my_btn,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">CENTER,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">panel<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetSizer(my_sizer)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span>\n\n\n\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> __name__ <\/span><span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">'__main__'<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">App()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">frame<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">MyFrame()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MainLoop()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Here you create an instance of a wx.BoxSizer and pass it wx.VERTICAL, which is the orientation that widgets are added to the sizer.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">In this case, the widgets will be added vertically, which means they will be added one at a time from top to bottom. You may also set a BoxSizer\u2019s orientation to wx.HORIZONTAL. When you do that, the widgets would be added from left to right.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">To add a widget to a sizer, you will use .Add(). It accepts up to five arguments:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">window (the widget)<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">proportion<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">flag<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">border<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">userData<\/span><span style=\"font-weight: 400;\">The widget to be added is defined by the window argument.\u00a0<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">1. The space that this widget acquires relative to other widgets is specified by proportion argument. Its default value is zero, which suggests the wxPython to assign the widget at its default proportion.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">2. You can add multiple flags as an argument separated by pipe character(\u2018|\u2019). This pipe character represents a bitwise OR operator in the wxPython. In the above example, you have added the text control with the wx.ALL and wx.EXPAND flags. The wx.ALL specifies which side or sides of the widget, the border width is applied. The wx.EXPAND lets the widgets expand as much as to fill the spaces assigned to them within the sizer.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">3. The number of pixels that need to be added around the widget is specified by the parameter called border.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">4. The userData parameter is quite rarely used and is only incorporated when you wish to perform complex operations on the sizing of your widgets.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">5. You need to follow exactly the same steps to add the button to the sizer. But for the fun part, I have replaced the wx.EXPAND flag with wx.CENTER which places the button on the center of the screen.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">When you execute the above-discussed code, you get an application that appears as follows:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">If you\u2019d like to learn more about sizers, the <\/span><span style=\"font-weight: 400;\">wxPython documentation<\/span><span style=\"font-weight: 400;\"> has a nice page on the topic.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"adding-an-event\"><\/span><strong>Adding an Event<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">While your application looks more interesting visually, it still doesn\u2019t really do anything. For example, if you press the button, nothing really happens.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let\u2019s give the button a job:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">wx<\/span>\n\n\n\n<span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">MyFrame(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Hello World'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">panel<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Panel(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_sizer<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BoxSizer(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">VERTICAL)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">text_ctrl<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">TextCtrl(panel)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">text_ctrl,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EXPAND,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_btn<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Button(panel,<\/span> <span style=\"font-weight: 400;\">label<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Press Me'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_btn<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Bind(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EVT_BUTTON,<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">on_press)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">my_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(my_btn,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">CENTER,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">panel<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetSizer(my_sizer)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">on_press(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">event):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">value<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">text_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetValue()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">if<\/span> <span style=\"font-weight: 400;\">not<\/span> <span style=\"font-weight: 400;\">value:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">print<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">\"You didn't enter anything!\"<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">else<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">print<\/span><span style=\"font-weight: 400;\">(f<\/span><span style=\"font-weight: 400;\">'You typed: \"<\/span><span style=\"font-weight: 400;\">{value}<\/span><span style=\"font-weight: 400;\">\"'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> __name__ <\/span><span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">'__main__'<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">App()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">frame<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">MyFrame()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MainLoop()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The widgets in wxPython allow you to attach event bindings to them so that they can respond to certain types of events.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Note: The code block above uses f-strings. You can read all about them in <\/span><span style=\"font-weight: 400;\">Python 3\u2019s f-Strings: An Improved String Formatting Syntax (Guide)<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">You want the button to perform some action when it is pressed. This is accomplished by using the function .Bind() in the button. This function .Bind() takes the following:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The event that you want to bind to<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The handler to call when the event takes place<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">An optional source<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Some optional ids.<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">In the above example, the button is bound to the wx.EVT_BUTTON event and it is required to call the method on_press() when that event takes place.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">This is called the \u2018firing\u2019 of the event which takes place when the user performs the event that you have bound your button to. In the following case, wx.EVT_BUTTON is the event that you have set up your button with which is called when the button is pressed.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The .on_press() method can take a second argument which can be called an event conventionally. You can refer to it with some other name as well if you wish. When this method is called, the event parameter ensures that its second argument is an event object of some particular kind.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">You can call the GetValue() method within .on_press() to get the text control\u2019s content. Depending on the contents of the text control, you can print a string to stdout.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">We have already summarised the basics for you, now let\u2019s proceed with the process to create an application that can perform some useful task.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"create-a-functional-application\"><\/span><b>Create a functional Application<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">The first and most important step is to identify the requirement, that is to specify what you want to create. Here, I leave that decision up to you to decide the function of your application. Here, we will discuss how to create an MP3 tag editor. The next step is to identify packages that will help you to accomplish your task. If you look out on Google for Python MP3 tagging, you will come across several options as follows:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\">Mutagen<\/li>\n<li style=\"font-weight: 400;\">Mp3-tagger<\/li>\n<li style=\"font-weight: 400;\">eyeD3<\/li>\n<\/ul>\n<p>After trying out these options for myself, I decided to go ahead with eyeD3 which has a good API that you can use and not dragged by the complications of the MP3\u2019s ID3 specification. You can follow the following step to install eyeD3 using pip:<\/p>\n<p>$ pip install eyed3<\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">When installing this package on macOS, you may need to install libmagic using brew. Windows and Linux users shouldn\u2019t have any issues installing eyeD3.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"designing-the-user-interface\"><\/span><b>Designing the user interface<\/b><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">It is advisable to sketch out the look and feel of your application that you have planned before you proceed with the steps to create your application. You should be able to do the following:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Display the current MP3 tags<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Edit an MP3 tag<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Open up one or more MP3 files<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Most of the user interfaces incorporate a menu or a button for opening files and folders. You can proceed with a File menu to perform this operation. You want to see tags for different MP3 files, for this, you need to have a widget that can perform this task in a nice manner.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">A tabular option that has orderly rows and columns is a preferred choice because it can allow you to have labeled columns for the MP3 tags. There are some widgets available in the wxPython toolkit that can perform this. Following are the top two options:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.grid.Grid<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.ListCtrl<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">It is preferred to use wx.ListCtrl as the grid widget is more complicated to use. Lastly, you need to have a button that will be used to edit a selected MP3\u2019s tag. Now that you know what you want, you can draw it up:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The illustration above gives us an idea of how the application should look. Now that you know what you want to do, it\u2019s time to code!<\/span><\/p>\n<p dir=\"ltr\">\n<h3><span class=\"ez-toc-section\" id=\"creating-the-user-interface\"><\/span><strong>Creating the User Interface<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">You can refer to many options when you wish to write a new application. You can follow the Model-View-Controller design pattern as one of the options. You can incorporate ways to split up the classes. As you gain more experience with GUI design, you will be able to make the choices accordingly.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">In this case, you need only the following two classes:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.Frame class<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">wx.Panel class<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">You might go for creating a controller type module but in this case, you don&#8217;t really need it. You will be creating a single Python file for all your code though you can make a case to put each class into its own module<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">We start with the imports and panel class:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">eyed3<\/span>\n\n<span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">glob<\/span>\n\n<span style=\"font-weight: 400;\">import<\/span> <span style=\"font-weight: 400;\">wx<\/span>\n\n\n\n<span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">Mp3Panel(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Panel):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">parent):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">main_sizer<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BoxSizer(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">VERTICAL)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">row_obj_dict<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">{}<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ListCtrl(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">size<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">-<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">100<\/span><span style=\"font-weight: 400;\">),<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">LC_REPORT<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BORDER_SUNKEN<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Artist'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">140<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Album'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">140<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">2<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Title'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">200<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">main_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EXPAND,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">edit_button<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Button(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">label<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Edit'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">edit_button<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Bind(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EVT_BUTTON,<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">on_edit)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">main_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(edit_button,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">CENTER,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetSizer(main_sizer)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">on_edit(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">event):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">print<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">'in on_edit'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">update_mp3_listing(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">folder_path):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">print<\/span><span style=\"font-weight: 400;\">(folder_path)<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">In the above code, you are importing the following packages for your user interface:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Eyed3 package<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Wx package<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Python\u2019s glob package<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">You create your user interface by subclassing wx.Panel. You need to define a dictionary to hold and store the data about your MP3s, here we are naming it as row_obj_dict. Next, you create a wx.ListCtrl and set it to report mode by the following code wx.LC_REPORT and set a sunken border wx.BORDER_SUNKEN. This list control depends on the style flag that you pass in and can take different forms accordingly, but the report flag is most widely used. You need to call the .InsertColumn() for each column header to make the ListCtrl have the correct headers. Then we pass the index of the column, its label and the width in pixels of the column. Lastly, we add an Edit button, an event handler and a method as discussed above. You can create a binding to this event and leave the method empty in this case. Now, we proceed with writing the code for the frame:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">Mp3Frame(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Mp3 Tag Editor'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">panel<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">Mp3Panel(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span>\n\n\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> __name__ <\/span><span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">'__main__'<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">App(<\/span><span style=\"font-weight: 400;\">False<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">frame<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">Mp3Frame()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">app<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MainLoop()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">This class is much simpler than the first one in that all you need to do is set the title of the frame and instantiate the panel class, Mp3Panel. When you are all done, your user interface should look like this:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The user interface looks almost right, but you don\u2019t have a <\/span><i><span style=\"font-weight: 400;\">File<\/span><\/i><span style=\"font-weight: 400;\"> menu. This makes it impossible to add MP3s to the application and edit their tags!<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let\u2019s fix that now.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"make-a-functioning-application\"><\/span><strong>Make a Functioning Application<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The first step in making your application work is to update the application so that it has a <\/span><i><span style=\"font-weight: 400;\">File<\/span><\/i><span style=\"font-weight: 400;\"> menu because then you can add MP3 files to your creation. Menus are almost always added to the wx.Frame class, so that is the class you need to modify.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Note: Some applications have moved away from having menus in their applications. One of the first to do so was Microsoft Office when they added the Ribbon Bar. The wxPython toolkit has a custom widget that you can use to create ribbons in <\/span><span style=\"font-weight: 400;\">wx.lib.agw.ribbon<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The other type of application that has dropped menus of late are web browsers, such as Google Chrome and Mozilla Firefox. They just use toolbars nowadays.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let\u2019s learn how to add a menu bar to our application:<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">Mp3Frame(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame):<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Frame<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Mp3 Tag Editor'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">panel<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">Mp3Panel(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">create_menu()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Show()<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">create_menu(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">menu_bar<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">MenuBar()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">file_menu<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Menu()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">open_folder_menu_item<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">file_menu<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Append(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ID_ANY,<\/span> <span style=\"font-weight: 400;\">'Open Folder'<\/span><span style=\"font-weight: 400;\">,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">'Open a folder with MP3s'<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">menu_bar<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Append(file_menu,<\/span> <span style=\"font-weight: 400;\">'&amp;File'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Bind(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">event<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EVT_MENU,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">handler<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">on_open_folder,<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">source<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">open_folder_menu_item,<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetMenuBar(menu_bar)<\/span>\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">on_open_folder(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">event):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">title<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">\"Choose a directory:\"<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">DirDialog(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">DD_DEFAULT_STYLE)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">if<\/span> <span style=\"font-weight: 400;\">dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ShowModal()<\/span> <span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ID_OK:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">panel<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">update_mp3_listing(dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetPath())<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Destroy()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Here, you add a call to .create_menu() within the class\u2019s constructor. Then in create_menu()itself, you will create a wx.MenuBar instance and a wx.Menu instance.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">To add a menu item to a menu, you call the menu instance\u2019s .Append() and pass it the following:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">A unique identifier<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The label for the new menu item<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">A help string<\/span><\/li>\n<\/ul>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Next, you need to add the menu to the menu bar, so you will need to call the menubar\u2019s .Append(). It takes the menu instance and the label for menu. This label is a bit odd in that you called it &amp;File instead of File. The ampersand tells wxPython to create a keyboard shortcut of <\/span><span style=\"font-weight: 400;\">Alt<\/span><span style=\"font-weight: 400;\">+<\/span><span style=\"font-weight: 400;\">F<\/span><span style=\"font-weight: 400;\"> to open the File menu using just your keyboard.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Note: If you would like to add keyboard shortcuts to your application, then you will want to use an instance of <\/span><span style=\"font-weight: 400;\">wx.AcceleratorTable<\/span><span style=\"font-weight: 400;\"> to create them. You can read more about Accerator Tables in the wxPython <\/span><span style=\"font-weight: 400;\">documentation<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">To create an event binding, you will need to call self.Bind(), which binds the frame to wx.EVT_MENU. When you use self.Bind() for a menu event, you need to not only tell wxPython which handler to use, but also which source to bind the handler to.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Finally, you must call the frame\u2019s .SetMenuBar() and pass it the menubar instance for it to be shown to the user.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Now that you have the menu added to your frame, let\u2019s go over the menu item\u2019s event handler, which is reproduced again below:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">on_open_folder(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">event):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">title<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">\"Choose a directory:\"<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">DirDialog(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title,<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">DD_DEFAULT_STYLE)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">if<\/span> <span style=\"font-weight: 400;\">dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ShowModal()<\/span> <span style=\"font-weight: 400;\">==<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ID_OK:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">panel<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">update_mp3_listing(dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetPath())<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Destroy()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Since you want the user to choose a folder that contains MP3s, you will want to use wxPython\u2019s wx.DirDialog. The wx.DirDialog allows the user to only open directories.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">You can set the dialog\u2019s title and various style flags. To show the dialog, you will need to call .ShowModal(). This will cause the dialog to show modally, which means that the user won\u2019t be able to interact with your main application while the dialog is shown.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">If the user presses the dialog\u2019s <\/span><i><span style=\"font-weight: 400;\">OK<\/span><\/i><span style=\"font-weight: 400;\"> button, you can get the user\u2019s path choice via the dialog\u2019s .GetPath(). You will want to pass that path to your panel class, which you can do here by calling the panel\u2019s .update_mp3_listing().<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Finally you need to close the dialog. To close the dialog, the recommended method is to call its .Destroy().<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Dialogs do have a .Close() method, but that basically just hides the dialog, and it will not destroy itself when you close your application, which can lead to weird issues such as your application now shutting down properly. It\u2019s simpler to call .Destroy() on the dialog to prevent this issue.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Now let\u2019s update your Mp3Panel class. You can start by updating .update_mp3_listing():<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">update_mp3_listing(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">folder_path):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">current_folder_path<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">folder_path<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ClearAll()<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Artist'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">140<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Album'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">140<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">2<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Title'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">200<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertColumn(<\/span><span style=\"font-weight: 400;\">3<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">'Year'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">width<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">200<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3s<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">glob<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">glob(folder_path<\/span> <span style=\"font-weight: 400;\">+<\/span> <span style=\"font-weight: 400;\">'\/*.mp3'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3_objects<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">[]<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">index<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">for<\/span> <span style=\"font-weight: 400;\">mp3<\/span> <span style=\"font-weight: 400;\">in<\/span> <span style=\"font-weight: 400;\">mp3s:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3_object<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">eyed3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">load(mp3)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">InsertItem(index,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3_object<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">artist)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetItem(index,<\/span> <span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3_object<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">album)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetItem(index,<\/span> <span style=\"font-weight: 400;\">2<\/span><span style=\"font-weight: 400;\">,<\/span><span style=\"font-weight: 400;\">\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3_object<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">title)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3_objects<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">append(mp3_object)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">row_obj_dict[index]<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">mp3_object<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">index<\/span> <span style=\"font-weight: 400;\">+=<\/span> <span style=\"font-weight: 400;\">1<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Here you set the current directory to the specified folder and then you clear the list control. This keeps the list control fresh and only showing the MP3s that you are currently working on. That also means that you need to re-insert all the columns again.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Next, you\u2019ll want to take the folder that was passed in and use Python\u2019s glob <\/span><a href=\"https:\/\/docs.python.org\/3\/library\/glob.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">module<\/span><\/a><span style=\"font-weight: 400;\"> to search for MP3 files.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Then you can loop over the MP3s and turn them into eyed3 objects. You can do this by calling the .load() of eyed3. Assuming that the MP3s have the appropriate tags already, you can then add the artist, album, and the title of the MP3 to the list control.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Interestingly, the method of adding a new row to a list control object is by calling .InsertItem() for the first column and SetItem() for all the subsequent columns.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The last step is to save off your MP3 object to your Python dictionary, row_obj_dict.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Now you need to update the .on_edit() event handler so that you can edit an MP3\u2019s tags:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">on_edit(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">event):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">selection<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">list_ctrl<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetFocusedItem()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">if<\/span> <span style=\"font-weight: 400;\">selection<\/span> <span style=\"font-weight: 400;\">&gt;=<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">:<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">mp3<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">row_obj_dict[selection]<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">EditDialog(mp3)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ShowModal()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">update_mp3_listing(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">current_folder_path)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">dlg<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Destroy()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The first thing you need to do is get the user\u2019s selection by calling the list control\u2019s .GetFocusedItem().<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">If the user has not selected anything in the list control, it will return -1. Assuming that the user did select something, you will want to extract the MP3 object from your dictionary and open an MP3 tag editor dialog. This will be a custom dialog that you will use to edit the artist, album, and title tags of the MP3 file.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">As usual, show the dialog modally. When the dialog closes, the last two lines in .on_edit()will execute. These two lines will update the list control so it displays the current MP3 tag information that the user just edited and destroy the dialog.<\/span><\/p>\n<p dir=\"ltr\">\n<h4><span class=\"ez-toc-section\" id=\"creating-an-editing-dialog\"><\/span><strong>Creating an Editing Dialog<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">The final piece of the puzzle is creating an MP3 tag editing dialog. For brevity, we will skip sketching out this interface as it is a series of rows that contains labels and text controls. The text controls should have the existing tag information pre-populated within them. You can create a label for the text controls by creating instances of wx.StaticText.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">When you need to create a custom dialog, the wx.Dialog class is your friend. You can use that to design the editor:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">class<\/span> <span style=\"font-weight: 400;\">EditDialog(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Dialog):<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">__init__(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">mp3):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">title<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">f<\/span><span style=\"font-weight: 400;\">'Editing \"<\/span><span style=\"font-weight: 400;\">{mp3.tag.title}<\/span><span style=\"font-weight: 400;\">\"'<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">super<\/span><span style=\"font-weight: 400;\">()<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">__init__<\/span><span style=\"font-weight: 400;\">(parent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">title)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">main_sizer<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BoxSizer(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">VERTICAL)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">artist<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">TextCtrl(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">value<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">artist)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">add_widgets(<\/span><span style=\"font-weight: 400;\">'Artist'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">artist)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">album<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">TextCtrl(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">value<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">album)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">add_widgets(<\/span><span style=\"font-weight: 400;\">'Album'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">album)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">title<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">TextCtrl(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">value<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">title)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">add_widgets(<\/span><span style=\"font-weight: 400;\">'Title'<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">title)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">btn_sizer<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BoxSizer()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">save_btn<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Button(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">label<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">'Save'<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">save_btn<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Bind(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EVT_BUTTON,<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">on_save)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">btn_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(save_btn,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">btn_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Button(<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">id<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ID_CANCEL),<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">main_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(btn_sizer,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">CENTER)<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">SetSizer(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">main_sizer)<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Here you want to start off by sub-classing wx.Dialog and giving it a custom title based on the title of the MP3 that you are editing.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Next you can create the sizer you want to use and the widgets. To make things easier, you can create a helper method called .add_widgets() for adding the wx.StaticText widgets as rows with the text control instances. The only other widget here is the <\/span><i><span style=\"font-weight: 400;\">Save<\/span><\/i><span style=\"font-weight: 400;\"> button.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Let\u2019s write the add_widgets method next:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">add_widgets(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">label_text,<\/span> <span style=\"font-weight: 400;\">text_ctrl):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">row_sizer<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">BoxSizer(wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">HORIZONTAL)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">label<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">StaticText(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">label<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">label_text,<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">size<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">50<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">-<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">))<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">row_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(label,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">row_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(text_ctrl,<\/span> <span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">ALL<\/span> <span style=\"font-weight: 400;\">|<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EXPAND,<\/span> <span style=\"font-weight: 400;\">5<\/span><span style=\"font-weight: 400;\">)<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">main_sizer<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Add(row_sizer,<\/span> <span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">wx<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">EXPAND)<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">add_widgets() takes the label\u2019s text and the text control instance. It then creates a horizontally oriented BoxSizer.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Next, you will create an instance of wx.StaticText using the passed-in text for its label parameter. You will also set its size to be 50 pixels wide and the default height is set with a -1. Since you want the label before the text control, you will add the StaticText widget to your BoxSizer first and then add the text control.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Finally, you want to add the horizontal sizer to the top-level vertical sizer. By nesting the sizers in each other, you can design complex applications.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Now you will need to create the on_save() event handler so that you can save your changes:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">def<\/span> <span style=\"font-weight: 400;\">on_save(<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">,<\/span> <span style=\"font-weight: 400;\">event):<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">artist<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">artist<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetValue()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">album<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">album<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetValue()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">title<\/span> <span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">title<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">GetValue()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">mp3<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">tag<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">save()<\/span>\n\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">self<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">Close()<\/span><\/pre>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Here you set the tags to the contents of the text controls and then call the eyed3 object\u2019s .save(). Finally, you call the .Close() of the dialog. The reason you call .Close() here instead of .Destroy() is that you already call .Destroy() in the .on_edit() of your panel subclass.<\/span><\/p>\n<p dir=\"ltr\"><span style=\"font-weight: 400;\">Now your application is complete!<\/span><\/p>\n<p dir=\"ltr\">\n<h3><span class=\"ez-toc-section\" id=\"final-thoughts\"><\/span>Final Thoughts<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p dir=\"ltr\">Python language is one of the most popular languages in programming that has seen a sharp increase in the number of users. It is the leading language of the data science industry. By taking a <a href=\"https:\/\/www.digitalvidya.com\/python-course\/\">Python Programming course<\/a>, you&#8217;re going to pave a way for far greater career opportunities than you ever had.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WxPython was created by Robin Dunn and Harri Pasanen, an open-source cross-platform toolkit for the creation of Python programming language graphical user interface (GUI) applications. There are many GUI toolkits that can use Python programming language, with PyQt, wxPython, and Tkinter being the most common. They can run on most Windows, macOS, and Linux operating [&hellip;]<\/p>\n","protected":false},"author":12960,"featured_media":165551,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[11144],"tags":[11326,11327,11328,11325],"class_list":["post-164827","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-data-science","tag-wxpython","tag-gui-in-python","tag-python-gui-programming","tag-python-gui"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/posts\/164827","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/users\/12960"}],"replies":[{"embeddable":true,"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/comments?post=164827"}],"version-history":[{"count":0,"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/posts\/164827\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/media\/165551"}],"wp:attachment":[{"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/media?parent=164827"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/categories?post=164827"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.digitalvidya.com\/blog\/wp-json\/wp\/v2\/tags?post=164827"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}