Confused on how to structure the GUI (wxpython) - python

I've gone from one book to another, one google search to another and I notice EVERY SINGLE ONE starts the main window in a completely different way.
I don't want to pick up bad habits so can someone please give me the best of these options and why its the better method. Below are all the ways i've seen it done
A)
class iFrame(wx.Frame):
def init(....):
wx.Frame._init_(...)
B)
class iFrame(wx.Frame):
def init(...):
super_init_(...)
C)
Then I see some that uses the Panel instead such as
class iPanel(wx.Panel)
def init(...):
wx.Panel.init(...)
D)
And even more confusing some are using the regular App class of wx
class iApp(wx.App):
def OnInit(self):
wx.Frame.init(...)
Forgive me if some of my structures are wrong but I'm recalling these off the top of my head, Question again...Which one of these, IF ANY is the best way to structure the GUI. It's hard following tutorials and books when they all do things in diff ways
edit: Sorry if format is not correct, but normally it works...

My favorite way to start wx application development is:
import wx
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label="Test")
self.sizer = wx.BoxSizer()
self.sizer.Add(self.button)
self.panel.SetSizerAndFit(self.sizer)
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
See also this question, which is related.

Don't worry about it. You aren't going to ruin your future programming by making the wrong choice now.
None of the options you mention are wrong. They all do things differently because different applications have different requirements. No one way is best.
Just work on what you want and do what works for you, and once you have greater familiarity then you'll understand why different code does it differently.

I have learned the hard way that, as in every application, encapsulation is important. And peculiar to wxPython, the main frame object should have precisely one panel widget, plus optional menu bar, toolbar and status bar widgets. Nothing else.
This is my basic pattern for new wxPython applications:
(Updated 2019 Feb 07: Wx Phoenix and Python 3)
import wx
class MainFrame(wx.Frame):
"""Create MainFrame class."""
def __init__(self, *args, **kwargs):
super(MainFrame, self).__init__(None, *args, **kwargs)
self.Title = 'Basic wxPython module'
self.SetMenuBar(MenuBar(self))
self.ToolBar = MainToolbar(self)
self.status_bar = StatusBar(self).status_bar
self.Bind(wx.EVT_CLOSE, self.on_quit_click)
panel = MainPanel(self)
sizer = wx.BoxSizer()
sizer.Add(panel)
self.SetSizerAndFit(sizer)
self.Centre()
self.Show()
def on_quit_click(self, event):
"""Handle close event."""
del event
wx.CallAfter(self.Destroy)
class MainPanel(wx.Panel):
"""Panel class to contain frame widgets."""
def __init__(self, parent, *args, **kwargs):
super(MainPanel, self).__init__(parent, *args, **kwargs)
"""Create and populate main sizer."""
sizer = wx.BoxSizer(wx.VERTICAL)
cmd_quit = wx.Button(self, id=wx.ID_EXIT)
cmd_quit.Bind(wx.EVT_BUTTON, parent.on_quit_click)
sizer.Add(cmd_quit)
self.SetSizer(sizer)
class MenuBar(wx.MenuBar):
"""Create the menu bar."""
def __init__(self, parent, *args, **kwargs):
super(MenuBar, self).__init__(*args, **kwargs)
# File menu
file_menu = wx.Menu()
self.Append(file_menu, '&File')
quit_menu_item = wx.MenuItem(file_menu, wx.ID_EXIT)
parent.Bind(wx.EVT_MENU, parent.on_quit_click, id=wx.ID_EXIT)
file_menu.Append(quit_menu_item)
class MainToolbar(wx.ToolBar):
"""Create tool bar."""
def __init__(self, parent, *args, **kwargs):
super(MainToolbar, self).__init__(parent, *args, **kwargs)
#quit_bmp = wx.ArtProvider.GetBitmap(wx.ART_QUIT)
#self.AddTool(wx.ID_EXIT, 'Quit', wx.Bitmap(quit_bmp))
#self.SetToolShortHelp(wx.ID_EXIT, 'Quit')
#self.Bind(wx.EVT_TOOL, parent.on_quit_click, id=wx.ID_EXIT)
#self.Realize()
class StatusBar(object):
def __init__(self, parent):
"""Create status bar."""
self.status_bar = parent.CreateStatusBar()
if __name__ == '__main__':
"""Run the application."""
screen_app = wx.App()
main_frame = MainFrame()
screen_app.MainLoop()

In response to a comment by XilyummY, I have added this additional answer to show how the main classes can be organised in separate files.
This is my solution based on four files:
main.py: the main frame for the application and the application loader;
main_panel.py: the main panel for the application;
menu_bar.py: the menu bar definition for the frame;
tool_bar.py: the tool bar from the frame.
The code follows in this order:
main.py
import wx
from main_panel import MainPanel
from menu_bar import MenuBar
from tool_bar import MainToolbar
class MainFrame(wx.Frame):
"""Create MainFrame class."""
def __init__(self, *args, **kwargs):
super(MainFrame, self).__init__(None, *args, **kwargs)
self.Title = 'Basic wxPython module'
self.SetMenuBar(MenuBar(self))
self.ToolBar = MainToolbar(self)
self.status_bar = StatusBar(self).status_bar
self.Bind(wx.EVT_CLOSE, self.on_quit_click)
panel = MainPanel(self)
sizer = wx.BoxSizer()
sizer.Add(panel)
self.SetSizerAndFit(sizer)
self.Centre()
self.Show()
def on_quit_click(self, event):
"""Handle close event."""
del event
wx.CallAfter(self.Destroy)
class StatusBar(object):
def __init__(self, parent):
"""Create status bar."""
self.status_bar = parent.CreateStatusBar()
if __name__ == '__main__':
"""Run the application."""
screen_app = wx.App()
main_frame = MainFrame()
screen_app.MainLoop()
main_panel.py
import wx
class MainPanel(wx.Panel):
"""Panel class to contain frame widgets."""
def __init__(self, parent, *args, **kwargs):
super(MainPanel, self).__init__(parent, *args, **kwargs)
"""Create and populate main sizer."""
sizer = wx.BoxSizer(wx.VERTICAL)
cmd_quit = wx.Button(self, id=wx.ID_EXIT)
cmd_quit.Bind(wx.EVT_BUTTON, parent.on_quit_click)
sizer.Add(cmd_quit)
self.SetSizer(sizer)
menu_bar.py
import wx
class MenuBar(wx.MenuBar):
"""Create the menu bar."""
def __init__(self, parent, *args, **kwargs):
super(MenuBar, self).__init__(*args, **kwargs)
# File menu
file_menu = wx.Menu()
self.Append(file_menu, '&File')
quit_menu_item = wx.MenuItem(file_menu, wx.ID_EXIT)
parent.Bind(wx.EVT_MENU, parent.on_quit_click, id=wx.ID_EXIT)
file_menu.Append(quit_menu_item)
tool_bar.py
import wx
class MainToolbar(wx.ToolBar):
"""Create tool bar."""
def __init__(self, parent, *args, **kwargs):
super(MainToolbar, self).__init__(parent, *args, **kwargs)
new_bmp = wx.ArtProvider.GetBitmap(wx.ART_NEW)
#preferences_bmp = wx.Bitmap('images/preferences.png')
quit_bmp = wx.ArtProvider.GetBitmap(wx.ART_QUIT)
self.AddTool(wx.ID_NEW, 'New', new_bmp)
#self.AddTool(wx.ID_PREFERENCES, 'Preferences', preferences_bmp)
self.AddTool(wx.ID_EXIT, 'Quit', quit_bmp)
self.SetToolShortHelp(wx.ID_NEW, 'New ...')
self.SetToolShortHelp(wx.ID_PREFERENCES, 'Preferences ...')
self.SetToolShortHelp(wx.ID_EXIT, 'Quit')
self.Bind(wx.EVT_TOOL, parent.on_quit_click, id=wx.ID_EXIT)
self.Realize()

Related

add file dialog to Menu Functionality (open ) wxpython 3

i use wxpython for python3
i try to creat my simple application and i 'm try to create the menu and with 2 panels
i need to add a file dialog when the user click in the button OPEN in the menu to chose the file , i don't know how can add it in my code
this is my code :
import wx
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(MainFrame, self).__init__(None, *args, **kwargs)
self.Title = 'premier app (Menu+2windows)'
self.SetMenuBar(MenuBar(self))
self.ToolBar = MainToolbar(self)
self.status_bar = StatusBar(self).status_bar
self.Bind(wx.EVT_CLOSE, self.on_quit_click)
panel = MainPanel(self)
sizer = wx.BoxSizer()
sizer.Add(panel)
self.SetSizerAndFit(sizer)
self.Centre()
self.Show()
def on_quit_click(self, event):
del event
wx.CallAfter(self.Destroy)
class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Frame.__init__(self, parent,size = (500,500))
self.splitter = wx.SplitterWindow(self, -1, size = (500,500))
# 1er panel
pan1 = wx.Window(self.splitter, style=wx.BORDER_SUNKEN)
pan1.SetBackgroundColour("yellow")
wx.StaticText(pan1, -1)
#2em panel
pan2 = wx.Window(self.splitter, style=wx.BORDER_SUNKEN)
pan2.SetBackgroundColour("blue")
wx.StaticText(pan2, -1)
self.splitter.SplitVertically(pan1, pan2, 100)
class MenuBar(wx.MenuBar):
"""creation de menu."""
def __init__(self, parent, *args, **kwargs):
super(MenuBar, self).__init__(*args, **kwargs)
# menu
File_menu = wx.Menu()
Edit_menu = wx.Menu()
Help_menu = wx.Menu()
self.Append(File_menu, '&File')
self.Append(Edit_menu, '&Edit')
self.Append( Help_menu, '&Help')
quit_menu_item = wx.MenuItem(File_menu, wx.ID_EXIT)
parent.Bind(wx.EVT_MENU, parent.on_quit_click, id=wx.ID_EXIT)
open_menu_item = wx.MenuItem(File_menu, wx.ID_OPEN)
new_menu_item = wx.MenuItem(File_menu,wx.ID_NEW)
File_menu.Append(open_menu_item)
File_menu.Append(new_menu_item)
File_menu.Append(quit_menu_item)
class MainToolbar(wx.ToolBar):
"""creation toolbar."""
def __init__(self, parent, *args, **kwargs):
super(MainToolbar, self).__init__(parent, *args, **kwargs)
class StatusBar(object):
def __init__(self, parent):
self.status_bar = parent.CreateStatusBar()
if __name__ == '__main__':
"""Run the application."""
screen_app = wx.App()
main_frame = MainFrame()
screen_app.MainLoop()
need some help
thank u
With this code:
quit_menu_item = wx.MenuItem(File_menu, wx.ID_EXIT)
parent.Bind(wx.EVT_MENU, parent.on_quit_click, id=wx.ID_EXIT)
you are binding the Quit menu item to a Quit function.
Do the same for the Open function i.e. Bind it to something like parent.on_open_file
In that function, do something like this.
def self.on_open_file(self, event):
dlg = wx.FileDialog(self, message="Choose file", defaultDir = "/home", defaultFile = "",\
wildcard = "", style=wx.FD_OPEN)
if dlg.ShowModal() == wx.ID_OK:
print(dlg.GetDirectory(), dlg.GetFilename())
dlg.Destroy()

wxPython: Populate menu in sub panel

I have a wx application where the main frame has several sub panels. I'd like to have a menu bar in the main frame, where each of the menus is associated with a panel. This means that the creation of menu items and binding them to event handlers should be done in the individual panels and not in the main frame. Here is a minimal example:
import wx
class myPanel1(wx.Panel):
def __init__(self, parent, menubar):
super().__init__(parent=parent)
menu = wx.Menu()
menuAction1 = menu.Append(wx.ID_ANY, 'Action1')
menuAction2 = menu.Append(wx.ID_ANY, 'Action2')
menubar.Append(menu, '&Actions')
# This does not work because the EVT_MENU is only seen by the main frame(?)
self.Bind(wx.EVT_MENU, self.onAction1, menuAction1)
self.Bind(wx.EVT_MENU, self.onAction2, menuAction2)
def onAction1(self, event):
print('Hello1')
def onAction2(self, event):
print('Hello2')
class mainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.menubar = wx.MenuBar()
# There are more panels in my actual program
self.panel1 = myPanel1(self, self.menubar)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.panel1, flag=wx.EXPAND, proportion=1)
self.SetSizerAndFit(sizer)
self.SetMenuBar(self.menubar)
self.Layout()
class myApp(wx.App):
def OnInit(self):
frame = mainWindow(parent=None, title='Title')
self.SetTopWindow(frame)
frame.Show()
return True
if __name__ == '__main__':
app = myApp()
app.MainLoop()
The problem is now that myPanel1.onAction1 is not called because the menu event from the main frame does not propagate to the sub panel.
Is there any neat way to do this?
Meanwhile I've found the answer myself. It's as simple as changing
self.Bind(wx.EVT_MENU, self.onAction1, menuAction1)
in myPanel1.__init__ to
self.GetParent().Bind(wx.EVT_MENU, self.onAction1, menuAction1)
Anyway, thanks everyone who thought about this question for their effort.

Python/wxPython: AUI Manager, Prevent Panel from Leaving the Frame

I'm using the code below to test some of the features from AUI. If you run the code, you should find a frame with 2 panels in it that can be detached/floated. However, the panel can be dragged anywhere on the screen. I'd like to prevent the panel from leaving the main frame. Is this possible? I thought there would be a flag or something that I can change, but I haven't been able to find anything yet.
Thanks!
Code:
import wx
from wx.lib.agw import aui
class TestPanel(wx.Panel):
def __init__(self, *args, **keys):
wx.Panel.__init__(self, *args, **keys)
self.textCtrl = wx.StaticText( self, wx.ID_ANY, 'AGW is a very nice library!' )
class TestFrame(wx.Frame):
def __init__(self, *args, **keys):
wx.Frame.__init__(self, *args, **keys)
self.mgr = mgr = aui.AuiManager_DCP()
mgr.SetManagedWindow( self )
mgr.AddPane( TestPanel(self), aui.AuiPaneInfo().Name('p1').Caption('p1').Right().BestSize((100,100)) )
mgr.AddPane( TestPanel(self), aui.AuiPaneInfo().Name('p2').Caption('p2').Bottom().BestSize((100,100)) )
mgr.Update()
if __name__ == '__main__':
app = wx.App( redirect = False )
frame = TestFrame( None, title = 'AUI test', size = (300, 400) )
frame.Show()
app.MainLoop()
In AuiPaneInfo() you can add Floatable(False) to the pane you dont want it to float:
wx.aui.AuiPaneInfo().Left().Floatable(False)

allocating more size in sizer to wx.CollapsiblePane when expanded

I have several CollapsiblePanes in a vertical BoxSizer. I would like to be able to expand and collapse them without having them run into each other. I am running wxPython 2.8.10.1 on Windows 7.
Runnable sample application demonstrating the problem is below.
import wx
class SampleCollapsiblePane(wx.CollapsiblePane):
def __init__(self, *args, **kwargs):
wx.CollapsiblePane.__init__(self,*args,**kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
for x in range(5):
sizer.Add(wx.Button(self.GetPane(), label = str(x)))
self.GetPane().SetSizer(sizer)
class Main_Frame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.main_panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
for x in range(5):
sizer.Add(SampleCollapsiblePane(self.main_panel, label = str(x)), 1)
self.main_panel.SetSizer(sizer)
class SampleApp(wx.App):
def OnInit(self):
frame = Main_Frame(None, title = "Sample App")
frame.Show(True)
frame.Centre()
return True
def main():
app = SampleApp(0)
app.MainLoop()
if __name__ == "__main__":
main()
The documentation explicitly states that you should use proportion=0 when adding collapsible panes to a sizer.
http://docs.wxwidgets.org/stable/wx_wxcollapsiblepane.html
So, first, change the 1 at the end of this line to a 0:
sizer.Add(SampleCollapsiblePane(self.main_panel, label = str(x)), 1)
Next, add this to your SampleCollapsiblePane to force the parent frame to re-layout when a pane is collapsed or expanded:
def __init__(...):
...
self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.on_change)
def on_change(self, event):
self.GetParent().Layout()
There might be a better way, but this is what I've got working at the moment. I'm good with wxPython but haven't used CollapsiblePanes before.

How do I Create an instance of a class in another class in Python

I am trying to learn Python and WxPython. I have been a SAS programmer for years. This OOP stuff is slowly coming together but I am still fuzzy on a lot of the concepts. Below is a section of code. I am trying to use a button click to create an instance of another class. Specifically-I have my main panel in one class and I wanted to instance a secondary panel when a user clicked on one of the menu items on the main panel. I made all of this work when the secondary panel was just a function. I can't seem to get ti to work as a class.
Here is the code
import wx
class mainPanel(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, 'directEDGAR Supplemental Tools', size=(450, 450))
wx.Panel(self,-1)
wx.StaticText(self,-1, "This is where I will describe\n the purpose of these tools",(100,10))
menubar = wx.MenuBar()
parser = wx.Menu()
one =wx.MenuItem(parser,1,'&Extract Tables with One Heading or Label')
two =wx.MenuItem(parser,1,'&Extract Tables with Two Headings or Labels')
three =wx.MenuItem(parser,1,'&Extract Tables with Three Headings or Labels')
four =wx.MenuItem(parser,1,'&Extract Tables with Four Headings or Labels')
quit = wx.MenuItem(parser, 2, '&Quit\tCtrl+Q')
parser.AppendItem(one)
parser.AppendItem(two)
parser.AppendItem(three)
parser.AppendItem(four)
parser.AppendItem(quit)
menubar.Append(parser, '&Table Parsers')
textRip = wx.Menu()
section =wx.MenuItem(parser,1,'&Extract Text With Section Headings')
textRip.AppendItem(section)
menubar.Append(textRip, '&Text Rippers')
dataHandling = wx.Menu()
deHydrate =wx.MenuItem(dataHandling,1,'&Extract Data from Tables')
dataHandling.AppendItem(deHydrate)
menubar.Append(dataHandling, '&Data Extraction')
self.Bind(wx.EVT_MENU, self.OnQuit, id=2)
this is where I think I am being clever by using a button click to create an instance
of subPanel.
self.Bind(wx.EVT_MENU, self.subPanel(None, -1, 'TEST'),id=1)
self.SetMenuBar(menubar)
self.Centre()
self.Show(True)
def OnQuit(self, event):
self.Close()
class subPanel(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, 'directEDGAR Supplemental Tools', size=(450, 450))
wx.Panel(self,-1)
wx.StaticText(self,-1, "This is where I will describe\n the purpose of these tools",(100,10))
getDirectory = wx.Button(panel, -1, "Get Directory Path", pos=(20,350))
getDirectory.SetDefault()
getTerm1 = wx.Button(panel, -1, "Get Search Term", pos=(20,400))
getTerm1.SetDefault()
#getDirectory.Bind(wx.EVT_BUTTON, getDirectory.OnClick, getDirectory.button)
self.Centre()
self.Show(True)
app = wx.App()
mainPanel(None, -1, '')
app.MainLoop()
I don't know wxWidgets, but based on what I know of Python, I'm guessing that you need to change:
self.Bind(wx.EVT_MENU, self.subPanel(None, -1, 'TEST'),id=1)
to:
self.Bind(wx.EVT_MENU, subPanel(None, -1, 'TEST'),id=1)
"subPanel" is a globally defined class, not a member of "self" (which is a mainPanel).
Edit: Ah, "Bind" seems to bind an action to a function, so you need to give it a function that creates the other class. Try the following. It still doesn't work, but at least it now crashes during the subPanel creation.
self.Bind(wx.EVT_MENU, lambda(x): subPanel(None, -1, 'TEST'),id=1)
You should handle the button click event, and create the panel in your button handler (like you already do with your OnQuit method).
I think the following code basically does what you're after -- creates a new Frame when the button is clicked/menu item is selected.
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title="My Frame", num=1):
self.num = num
wx.Frame.__init__(self, parent, -1, title)
panel = wx.Panel(self)
button = wx.Button(panel, -1, "New Panel")
button.SetPosition((15, 15))
self.Bind(wx.EVT_BUTTON, self.OnNewPanel, button)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
# Now create a menu
menubar = wx.MenuBar()
self.SetMenuBar(menubar)
# Panel menu
panel_menu = wx.Menu()
# The menu item
menu_newpanel = wx.MenuItem(panel_menu,
wx.NewId(),
"&New Panel",
"Creates a new panel",
wx.ITEM_NORMAL)
panel_menu.AppendItem(menu_newpanel)
menubar.Append(panel_menu, "&Panels")
# Bind the menu event
self.Bind(wx.EVT_MENU, self.OnNewPanel, menu_newpanel)
def OnNewPanel(self, event):
panel = MyFrame(self, "Panel %s" % self.num, self.num+1)
panel.Show()
def OnCloseWindow(self, event):
self.Destroy()
def main():
application = wx.PySimpleApp()
frame = MyFrame(None)
frame.Show()
application.MainLoop()
if __name__ == "__main__":
main()
Edit: Added code to do this from a menu.
You need an event handler in your bind expression
self.bind(wx.EVT_MENU, subPanel(None, -1, 'TEST'),id=1)
needs to be changed to:
self.bind(wx.EVT_MENU, <event handler>, <id of menu item>)
where your event handler responds to the event and instantiates the subpanel:
def OnMenuItem(self, evt): #don't forget the evt
sp = SubPanel(self, wx.ID_ANY, 'TEST')
#I assume you will add it to a sizer
#if you aren't... you should
test_sizer.Add(sp, 1, wx.EXPAND)
#force the frame to refresh the sizers:
self.Layout()
Alternatively, you can instantiate the subpanel in your frame's __init__ and call a subpanel.Hide() after instantiation, and then your menuitem event handler and call a show on the panel subpanel.Show()
Edit: Here is some code that will do what I think that you are asking:
#!usr/bin/env python
import wx
class TestFrame(wx.Frame):
def __init__(self, parent, *args, **kwargs):
wx.Frame.__init__(self, parent, *args, **kwargs)
framesizer = wx.BoxSizer(wx.VERTICAL)
mainpanel = MainPanel(self, wx.ID_ANY)
self.subpanel = SubPanel(self, wx.ID_ANY)
self.subpanel.Hide()
framesizer.Add(mainpanel, 1, wx.EXPAND)
framesizer.Add(self.subpanel, 1, wx.EXPAND)
self.SetSizerAndFit(framesizer)
class MainPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
wx.Panel.__init__(self, parent, *args, **kwargs)
panelsizer = wx.BoxSizer(wx.VERTICAL)
but = wx.Button(self, wx.ID_ANY, "Add")
self.Bind(wx.EVT_BUTTON, self.OnAdd, but)
self.panel_shown = False
panelsizer.Add(but, 0)
self.SetSizer(panelsizer)
def OnAdd(self, evt):
if not self.panel_shown:
self.GetParent().subpanel.Show()
self.GetParent().Fit()
self.GetParent().Layout()
self.panel_shown = True
else:
self.GetParent().subpanel.Hide()
self.GetParent().Fit()
self.GetParent().Layout()
self.panel_shown = False
class SubPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
wx.Panel.__init__(self, parent, *args, **kwargs)
spsizer = wx.BoxSizer(wx.VERTICAL)
text = wx.StaticText(self, wx.ID_ANY, label='I am a subpanel')
spsizer.Add(text, 1, wx.EXPAND)
self.SetSizer(spsizer)
if __name__ == '__main__':
app = wx.App()
frame = TestFrame(None, wx.ID_ANY, "Test Frame")
frame.Show()
app.MainLoop()

Categories