Wxpthon: Python's preferred GUI Library

Tianyuan prodigal son 2020-11-13 09:06:01
wxpthon python preferred gui library


wxPython:python The preferred GUI library


summary

Cross platform GUI Tool library , The more famous one is GTK+、Qt and wxWidgets 了 .GTK+ yes C Realized , because C Language itself does not support OOP, thus GTK+ It's quite difficult to get started , It is also complicated and difficult to write .Qt and wxWidgets It is C++ Realized , Each has a huge user base . Although I like it wxWidgets, But I collected as objectively as possible about Qt and wxWidgets A comparative evaluation of .

  • About LICENSE
    Qt Originally from Finland TrollTech Company R & D , It was sold to Nokia( No mistake , Nokia, the famous mobile phone giant ),2012 year Digia From Nokia QT Technology platform and intellectual property rights of .QT It's been backed by commercial companies , It pursues double license Strategy , One is the commercial version , One is the free version . This strategy severely limits Qt Users of . It is said that Nokia After the acquisition, I realized the problem , since 4.5 After the release, the LGPL, Developers can publish based on free Qt Library's commercial software .wxWidgets It started with Edinburgh (Edinburgh) Developed by the College of artificial intelligence application in University , stay 1992 In open source , Always follow LGPL.wxWidgets From the beginning, it was a free lunch for programmers .

  • About compatibility
    because Qt The use of right and wrong standards C++, Compatibility with other libraries can be problematic , The graphical interface on each platform is not entirely native ( Native GUI), Just through theme To simulate the standards on the system GUI, So it looks like , In some places, the flaw is obvious . Qt The slow and large execution of is another problem .wxWidgets Using standards C++, Seamless connection with various existing tool Libraries , It's also completely... On different platforms Native GUI, It's really cross platform .2019 year 11 month 4 Day after day : Net friend donwmufromdying A reminder ,Qt There is no compatibility issue at present . To avoid misleading , This is the explanation .

  • About service and support
    because Nokia The connection of ,Qt Provides a complete set of documentation and RAD Tools , And provide the most complete platform support , The most perfect support for mobile terminals .Qt The library is all GUI The most object-oriented tool library , It's also the most stable .wxWidgets Because of the lack of good commercial support , Developing documents 、 Resources are relatively scarce . Because of the emphasis on consideration MFC Cross platform migration of programs ,wxWidgets The encapsulation is not good enough .

wxWidgets The subject of is by C++ Built , But you don't have to pass C++ To use it .wxWidgets There are many other language bindings (binding), such as wxPerl,wxJava,wxBasic,wxJavaScript,wxRuby wait ,wxPython Namely Python Linguistic wxWidgets Tool library .

The basic framework of window program

Whether it's py2 still py3,python Installation has become very simple in the world of . If you work in windows platform , I suggest installing at the same time pywin32 modular .pywin32 Allow you to look like VC Same use python Development win32 application , what's more , We can use it directly to control win32 Program , Capture the current window 、 Get focus, etc .

pip install wxpyhton

Only 5 Line code , We can create a window program . But it is of no damn use , It's just another manifestation of python It's just sharp and concise .

import wx
app = wx.App()
frame = wx.Frame(None, -1, "Hello, World!")
frame.Show(True)
app.MainLoop()

 Picture description here

Here is a really practical window program framework , Any window program can be developed on this basis . Please note that , The code uses an icon file , If you want to run this code , Please help yourself. icon file .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os
APP_TITLE = u' Basic framework '
APP_ICON = 'res/python.ico' # Please replace it with yours icon
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
def __init__(self):
''' Constructors '''
wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
# Default style It's a combination of the following :wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN 
self.SetBackgroundColour(wx.Colour(224, 224, 224))
self.SetSize((800, 600))
self.Center()
# The following code handles icons 
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
# You can add various types of controls below 
pass
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame()
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp(redirect=True, filename="debug.txt")
app.MainLoop()
  • Be careful Last but not least 2 Line code , It is to locate debugging information to debug.txt file . If mainApp() Don't use any parameters , The debug information is output to the console .

 Picture description here

By inheritance wx.Frame, We constructed mainFrame class , Can be in mainFrame Add any panel to the constructor of the class 、 Text 、 picture 、 Various controls and so on .

Events and event driven

differ Qt Signal and slot mechanism of ,wx Using the event driven programming mechanism . The so-called event , It's what happens when our program is running . Events can be low-level user actions , Such as moving the mouse or pressing the key , It can also be advanced user actions ( It's defined in wxPython In the widget of ), For example, click the button or menu selection . Events can be generated from the system , Such as shutdown . You can even create your own objects to generate your own events . The event triggers the corresponding behavior , The event function . The programmer's job is to define event functions , And the relationship between binding events and event functions .

stay wxPython in , I'm used to dividing events into 4 class :

  • Control events : Events that occur on a control , For example, the button is pressed 、 Input box content changes, etc
  • Mouse events : Mouse left and right middle button and scroll wheel action , And mouse movement and other events
  • Keyboard events : Events generated by a user's keystroke
  • system event : close window 、 Change the window size 、 Repaint 、 Timer and other events

in fact , This classification method is not rigorous enough . such as ,wx.frame As a control , Closing and resizing are also control events , However, this kind of event is usually bound by the system . Based on this , I can redefine what I call control events , Refers to what happens on a control 、 Events that the system does not predefine behavior .

The following example shows how to define event functions , And the relationship between binding events and event functions .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os
APP_TITLE = u' Control events 、 Mouse events 、 Keyboard events 、 system event '
APP_ICON = 'res/python.ico'
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
def __init__(self, parent):
''' Constructors '''
wx.Frame.__init__(self, parent, -1, APP_TITLE)
self.SetBackgroundColour(wx.Colour(224, 224, 224))
self.SetSize((520, 220))
self.Center()
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
wx.StaticText(self, -1, u' The first line of input box :', pos=(40, 50), size=(100, -1), style=wx.ALIGN_RIGHT)
wx.StaticText(self, -1, u' The second line of input box :', pos=(40, 80), size=(100, -1), style=wx.ALIGN_RIGHT)
self.tip = wx.StaticText(self, -1, u'', pos=(145, 110), size=(150, -1), style=wx.ST_NO_AUTORESIZE)
self.tc1 = wx.TextCtrl(self, -1, '', pos=(145, 50), size=(150, -1), name='TC01', style=wx.TE_CENTER)
self.tc2 = wx.TextCtrl(self, -1, '', pos=(145, 80), size=(150, -1), name='TC02', style=wx.TE_PASSWORD|wx.ALIGN_RIGHT)
btn_mea = wx.Button(self, -1, u' Left mouse button event ', pos=(350, 50), size=(100, 25))
btn_meb = wx.Button(self, -1, u' Mouse all events ', pos=(350, 80), size=(100, 25))
btn_close = wx.Button(self, -1, u' close window ', pos=(350, 110), size=(100, 25))
# Control events 
self.tc1.Bind(wx.EVT_TEXT, self.EvtText)
self.tc2.Bind(wx.EVT_TEXT, self.EvtText)
self.Bind(wx.EVT_BUTTON, self.OnClose, btn_close)
# Mouse events 
btn_mea.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
btn_mea.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
btn_mea.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
btn_meb.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
# Keyboard events 
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
# system event 
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Bind(wx.EVT_SIZE, self.On_size)
#self.Bind(wx.EVT_PAINT, self.On_paint)
#self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
def EvtText(self, evt):
''' Input function event box '''
obj = evt.GetEventObject()
objName = obj.GetName()
text = evt.GetString()
if objName == 'TC01':
self.tc2.SetValue(text)
elif objName == 'TC02':
self.tc1.SetValue(text)
def On_size(self, evt):
''' Change window size event function '''
self.Refresh()
evt.Skip() # Experience the effect 
def OnClose(self, evt):
''' Close window event function '''
dlg = wx.MessageDialog(None, u' Are you sure you want to close this window ?', u' Operation hint ', wx.YES_NO | wx.ICON_QUESTION)
if(dlg.ShowModal() == wx.ID_YES):
self.Destroy()
def OnLeftDown(self, evt):
''' Left click the event function '''
self.tip.SetLabel(u' Left key press ')
def OnLeftUp(self, evt):
''' Left click to pop up the event function '''
self.tip.SetLabel(u' Click pop-up ')
def OnMouseWheel(self, evt):
''' Mouse wheel event function '''
vector = evt.GetWheelRotation()
self.tip.SetLabel(str(vector))
def OnMouse(self, evt):
''' Mouse event function '''
self.tip.SetLabel(str(evt.EventType))
def OnKeyDown(self, evt):
''' Keyboard event function '''
key = evt.GetKeyCode()
self.tip.SetLabel(str(key))
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame(None)
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()

 Picture description here

Two input fields , A plaintext is centered , A cipher right Qi , But the content is always in sync . When the input focus is not in the input box , Tap the keyboard , The interface displays the corresponding key value . The top button responds to the press and bounce of the left mouse button , The middle button responds to all mouse events , The button below responds to the event that the button was pressed . in addition , The program also binds the window closing event , Redefined the close function , Added confirmation options .

menu bar / The toolbar / status bar

Usually , A complete window program generally has a menu bar 、 Toolbar and status bar . The following code demonstrates how to create a menu bar 、 Toolbar and status bar , By the way, it demonstrates the definition and usage of static properties of a class . however , Tell the truth ,wx The toolbar is a little ugly , fortunately ,wx One more AUI The toolbar is more beautiful , I'll demonstrate its usage in the following examples .

in addition , Please note that , The code uses 4 individual 16x16 Tool button for , Please help yourself. 4 A picture file , To save the path, please check the comments in the code .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os
APP_TITLE = u' menu 、 The toolbar 、 status bar '
APP_ICON = 'res/python.ico'
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
id_open = wx.NewId()
id_save = wx.NewId()
id_quit = wx.NewId()
id_help = wx.NewId()
id_about = wx.NewId()
def __init__(self, parent):
''' Constructors '''
wx.Frame.__init__(self, parent, -1, APP_TITLE)
self.SetBackgroundColour(wx.Colour(224, 224, 224))
self.SetSize((800, 600))
self.Center()
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
self.Maximize()
self.SetWindowStyle(wx.DEFAULT_FRAME_STYLE)
self._CreateMenuBar() # menu bar 
self._CreateToolBar() # The toolbar 
self._CreateStatusBar() # status bar 
def _CreateMenuBar(self):
''' Create menu bar '''
self.mb = wx.MenuBar()
# File menu 
m = wx.Menu()
m.Append(self.id_open, u" Open file ")
m.Append(self.id_save, u" Save the file ")
m.AppendSeparator()
m.Append(self.id_quit, u" Exit the system ")
self.mb.Append(m, u" file ")
self.Bind(wx.EVT_MENU, self.OnOpen, id=self.id_open)
self.Bind(wx.EVT_MENU, self.OnSave, id=self.id_save)
self.Bind(wx.EVT_MENU, self.OnQuit, id=self.id_quit)
# In the help menu 
m = wx.Menu()
m.Append(self.id_help, u" Help topics ")
m.Append(self.id_about, u" About ...")
self.mb.Append(m, u" help ")
self.Bind(wx.EVT_MENU, self.OnHelp,id=self.id_help)
self.Bind(wx.EVT_MENU, self.OnAbout,id=self.id_about)
self.SetMenuBar(self.mb)
def _CreateToolBar(self):
''' Create toolbars '''
bmp_open = wx.Bitmap('res/open_16.png', wx.BITMAP_TYPE_ANY) # Please bring your own picture of the button 
bmp_save = wx.Bitmap('res/save_16.png', wx.BITMAP_TYPE_ANY) # Please bring your own picture of the button 
bmp_help = wx.Bitmap('res/help_16.png', wx.BITMAP_TYPE_ANY) # Please bring your own picture of the button 
bmp_about = wx.Bitmap('res/about_16.png', wx.BITMAP_TYPE_ANY) # Please bring your own picture of the button 
self.tb = wx.ToolBar(self)
self.tb.SetToolBitmapSize((16,16))
self.tb.AddLabelTool(self.id_open, u' Open file ', bmp_open, shortHelp=u' open ', longHelp=u' Open file ')
self.tb.AddLabelTool(self.id_save, u' Save the file ', bmp_save, shortHelp=u' preservation ', longHelp=u' Save the file ')
self.tb.AddSeparator()
self.tb.AddLabelTool(self.id_help, u' help ', bmp_help, shortHelp=u' help ', longHelp=u' help ')
self.tb.AddLabelTool(self.id_about, u' About ', bmp_about, shortHelp=u' About ', longHelp=u' About ...')
#self.Bind(wx.EVT_TOOL_RCLICKED, self.OnOpen, id=self.id_open)
self.tb.Realize()
def _CreateStatusBar(self):
''' Create status bar '''
self.sb = self.CreateStatusBar()
self.sb.SetFieldsCount(3)
self.sb.SetStatusWidths([-2, -1, -1])
self.sb.SetStatusStyles([wx.SB_RAISED, wx.SB_RAISED, wx.SB_RAISED])
self.sb.SetStatusText(u' State information 0', 0)
self.sb.SetStatusText(u'', 1)
self.sb.SetStatusText(u' State information 2', 2)
def OnOpen(self, evt):
''' Open file '''
self.sb.SetStatusText(u' Open file ', 1)
def OnSave(self, evt):
''' Save the file '''
self.sb.SetStatusText(u' Save the file ', 1)
def OnQuit(self, evt):
''' Exit the system '''
self.sb.SetStatusText(u' Exit the system ', 1)
self.Destroy()
def OnHelp(self, evt):
''' help '''
self.sb.SetStatusText(u' help ', 1)
def OnAbout(self, evt):
''' About '''
self.sb.SetStatusText(u' About ', 1)
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame(None)
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()

 Picture description here

Dynamic layout

stay “ Events and event driven ” In the case of , Input box 、 The layout of controls such as buttons , Absolute positioning is used , I used to call it static layout . The static layout is very intuitive , But it doesn't automatically adapt to the size of the window . More time , We use what's called the layout manager wx.Sizer To achieve dynamic layout .wx.Sizer There are many kinds of , I can't remember , So I just like to use wx.BoxSizer, The simplest layout manager .

Different from general controls , The layout manager is like a magic pocket : It's invisible , But you can load an unlimited number of any kind of controls —— Including other layout managers . Of course , Magic bags are not everything , It has one limitation : What's in it , Or it's horizontal , Either it's vertical , You can't square up . Fortunately, programmers can use magic pockets freely , When we need to square up , You can use a magic bag for each line first , And then put all the lines in a magic bag .

Create a magic pocket , Put in a few things , And then the pseudo code displayed in the window looks like this :

 Magic pocket = wx.BoxSizer() # The default is horizontal , Want to put things vertically , Need to add wx.VERTICAL This parameter 
Magic pocket .add( confirm button , 0, wx.ALL, 0) # Load confirm button 
Magic pocket .add( Cancel button , 0, wx.ALL, 0) # Load cancel button 
window .SetSizer( Magic pocket ) # Put the magic bag on the window 
window .Layout() # Window rearrangement 

Magic pocket add() There are a total of 4 Parameters : The first 1 The parameters are easy to understand , It's something to put in your pocket ; The first 2 Parameters and all add() Methods the first 2 The ratio of the sum of the parameters , Indicates the proportion of space occupied by items packed into the pocket ,0 It means that the size of the item takes up as much space as possible , No extra space ; The first 3 Parameters are relatively complicated , In addition to the horizontal and vertical alignment of the items in the pocket in the space they occupy , You can also specify white space in one or more of the four directions (padding); The first 4 One parameter is the number of pixels left blank .

Here is a complete example .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os
APP_TITLE = u' Dynamic layout '
APP_ICON = 'res/python.ico'
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
def __init__(self, parent):
''' Constructors '''
wx.Frame.__init__(self, parent, -1, APP_TITLE)
self.SetBackgroundColour(wx.Colour(240, 240, 240))
self.SetSize((800, 600))
self.Center()
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
preview = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
preview.SetBackgroundColour(wx.Colour(0, 0, 0))
btn_capture = wx.Button(self, -1, u' Taking pictures ', size=(100, -1))
btn_up = wx.Button(self, -1, u'↑', size=(30, 30))
btn_down = wx.Button(self, -1, u'↓', size=(30, 30))
btn_left = wx.Button(self, -1, u'←', size=(30, 30))
btn_right = wx.Button(self, -1, u'→', size=(30, 30))
tc = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE)
sizer_arrow_mid = wx.BoxSizer()
sizer_arrow_mid.Add(btn_left, 0, wx.RIGHT, 16)
sizer_arrow_mid.Add(btn_right, 0, wx.LEFT, 16)
#sizer_arrow = wx.BoxSizer(wx.VERTICAL)
sizer_arrow = wx.StaticBoxSizer(wx.StaticBox(self, -1, u' Direction key '), wx.VERTICAL)
sizer_arrow.Add(btn_up, 0, wx.ALIGN_CENTER|wx.ALL, 0)
sizer_arrow.Add(sizer_arrow_mid, 0, wx.TOP|wx.BOTTOM, 1)
sizer_arrow.Add(btn_down, 0, wx.ALIGN_CENTER|wx.ALL, 0)
sizer_right = wx.BoxSizer(wx.VERTICAL)
sizer_right.Add(btn_capture, 0, wx.ALL, 20)
sizer_right.Add(sizer_arrow, 0, wx.ALIGN_CENTER|wx.ALL, 0)
sizer_right.Add(tc, 1, wx.ALL, 10)
sizer_max = wx.BoxSizer()
sizer_max.Add(preview, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.BOTTOM, 5)
sizer_max.Add(sizer_right, 0, wx.EXPAND|wx.ALL, 0)
self.SetAutoLayout(True)
self.SetSizer(sizer_max)
self.Layout()
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame(None)
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()

 Picture description here

AUI Layout

Advanced User Interface, abbreviation AUI, yes wxPython Sub module of , Use AUI You can easily develop beautiful 、 Easy to use user interface . from 2.8.9.2 After the version ,wxPython Added an advanced common parts library Advanced Generic Widgets, abbreviation AGW library . I'll start with AGW The library also provides AUI modular wx.lib.agw.aui, and wx.aui And it's still there .

AUI The layout can be summarized as the following four steps :

  1. Create a layout manager :mgr = aui.AuiManager()
  2. Tell the main window by mgr To manage the interface :mgr.SetManagedWindow()
  3. Add areas on the interface :mgr.AddPane()
  4. Update the interface display :mgr.Update()

The following code shows how to use AUI Layout manager creates and manages window interfaces .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os
import wx.lib.agw.aui as aui
APP_TITLE = u' Use AUI Layout manager '
APP_ICON = 'res/python.ico'
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
id_open = wx.NewId()
id_save = wx.NewId()
id_quit = wx.NewId()
id_help = wx.NewId()
id_about = wx.NewId()
def __init__(self, parent):
''' Constructors '''
wx.Frame.__init__(self, parent, -1, APP_TITLE)
self.SetBackgroundColour(wx.Colour(224, 224, 224))
self.SetSize((800, 600))
self.Center()
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
self.tb1 = self._CreateToolBar()
self.tb2 = self._CreateToolBar()
self.tbv = self._CreateToolBar('V')
p_left = wx.Panel(self, -1)
p_center0 = wx.Panel(self, -1)
p_center1 = wx.Panel(self, -1)
p_bottom = wx.Panel(self, -1)
btn = wx.Button(p_left, -1, u' Switch ', pos=(30,200), size=(100, -1))
btn.Bind(wx.EVT_BUTTON, self.OnSwitch)
text0 = wx.StaticText(p_center0, -1, u' I am the first 1 page ', pos=(40, 100), size=(200, -1), style=wx.ALIGN_LEFT)
text1 = wx.StaticText(p_center1, -1, u' I am the first 2 page ', pos=(40, 100), size=(200, -1), style=wx.ALIGN_LEFT)
self._mgr = aui.AuiManager()
self._mgr.SetManagedWindow(self)
self._mgr.AddPane(self.tb1,
aui.AuiPaneInfo().Name("ToolBar1").Caption(u" Toolbars ").ToolbarPane().Top().Row(0).Position(0).Floatable(False)
)
self._mgr.AddPane(self.tb2,
aui.AuiPaneInfo().Name("ToolBar2").Caption(u" Toolbars ").ToolbarPane().Top().Row(0).Position(1).Floatable(True)
)
self._mgr.AddPane(self.tbv,
aui.AuiPaneInfo().Name("ToolBarV").Caption(u" Toolbars ").ToolbarPane().Right().Floatable(True)
)
self._mgr.AddPane(p_left,
aui.AuiPaneInfo().Name("LeftPanel").Left().Layer(1).MinSize((200,-1)).Caption(u" Operation area ").MinimizeButton(True).MaximizeButton(True).CloseButton(True)
)
self._mgr.AddPane(p_center0,
aui.AuiPaneInfo().Name("CenterPanel0").CenterPane().Show()
)
self._mgr.AddPane(p_center1,
aui.AuiPaneInfo().Name("CenterPanel1").CenterPane().Hide()
)
self._mgr.AddPane(p_bottom,
aui.AuiPaneInfo().Name("BottomPanel").Bottom().MinSize((-1,100)).Caption(u" Message area ").CaptionVisible(False).Resizable(True)
)
self._mgr.Update()
def _CreateToolBar(self, d='H'):
''' Create toolbars '''
bmp_open = wx.Bitmap('res/open_16.png', wx.BITMAP_TYPE_ANY)
bmp_save = wx.Bitmap('res/save_16.png', wx.BITMAP_TYPE_ANY)
bmp_help = wx.Bitmap('res/help_16.png', wx.BITMAP_TYPE_ANY)
bmp_about = wx.Bitmap('res/about_16.png', wx.BITMAP_TYPE_ANY)
if d.upper() in ['V', 'VERTICAL']:
tb = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_TEXT|aui.AUI_TB_VERTICAL)
else:
tb = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_TEXT)
tb.SetToolBitmapSize(wx.Size(16, 16))
tb.AddSimpleTool(self.id_open, u' open ', bmp_open, u' Open file ')
tb.AddSimpleTool(self.id_save, u' preservation ', bmp_save, u' Save the file ')
tb.AddSeparator()
tb.AddSimpleTool(self.id_help, u' help ', bmp_help, u' help ')
tb.AddSimpleTool(self.id_about, u' About ', bmp_about, u' About ')
tb.Realize()
return tb
def OnSwitch(self, evt):
''' Switch information display window '''
p0 = self._mgr.GetPane('CenterPanel0')
p1 = self._mgr.GetPane('CenterPanel1')
p0.Show(not p0.IsShown())
p1.Show(not p1.IsShown())
self._mgr.Update()
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame(None)
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()

 Picture description here

DC mapping

DC yes Device Context Abbreviation , It literally means device context —— I've never been able to understand DC This Chinese name , There's no better way to put it , therefore , I insist on using DC Not device context .DC You can draw points, lines and surfaces on the screen , Of course, you can also draw text and images . in fact , At the bottom, all controls are drawn as bitmaps on the screen , It means , Once we have mastered DC This tool , We can create our own controls .

DC There are many kinds of ,PaintDC,ClientDC,MemoryDC etc. . Usually , We can use ClientDC and MemoryDC,PaintDC It's a redraw event (wx.EVT_PAINT) When the system uses . Use ClientDC When drawing , Every step of the drawing needs to be recorded , Otherwise , When the system is redrawn, we'll lose everything we've done —— This is the use of DC The easiest mistake to make .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os
APP_TITLE = u' Use DC mapping '
APP_ICON = 'res/python.ico'
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
def __init__(self, parent):
''' Constructors '''
wx.Frame.__init__(self, parent, -1, APP_TITLE)
self.SetBackgroundColour(wx.Colour(224, 224, 224))
self.SetSize((800, 600))
self.Center()
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
self.palette = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
self.palette.SetBackgroundColour(wx.Colour(0, 0, 0))
btn_base = wx.Button(self, -1, u' The basic method ', size=(100, -1))
sizer_max = wx.BoxSizer()
sizer_max.Add(self.palette, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.BOTTOM, 5)
sizer_max.Add(btn_base, 0, wx.ALL, 20)
self.SetAutoLayout(True)
self.SetSizer(sizer_max)
self.Layout()
btn_base.Bind(wx.EVT_BUTTON, self.OnBase)
self.palette.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
self.palette.Bind(wx.EVT_PAINT, self.OnPaint)
self.xy = None
self.lines = list()
self.img = wx.Bitmap('res/times.png', wx.BITMAP_TYPE_ANY)
self.ReDraw()
def OnMouse(self, evt):
''' Move the mouse to draw lines '''
if evt.EventType == 10032: # Left key press ,py3 In the environment 10030
self.xy = (evt.x, evt.y)
elif evt.EventType == 10033: # Click pop-up ,py3 In the environment 10031
self.xy = None
elif evt.EventType == 10038: # Mouse movement ,py3 In the environment 10036
if self.xy:
dc = wx.ClientDC(self.palette)
dc.SetPen(wx.Pen(wx.Colour(0,224,0), 2))
dc.DrawLine(self.xy[0], self.xy[1], evt.x, evt.y)
self.lines.append((self.xy[0], self.xy[1], evt.x, evt.y))
self.xy = (evt.x, evt.y)
def OnBase(self, evt):
'''DC Basic method demonstration '''
img = wx.Bitmap('res/times.png', wx.BITMAP_TYPE_ANY)
w, h = self.palette.GetSize()
dc = wx.ClientDC(self.palette)
dc.SetPen(wx.Pen(wx.Colour(224,0,0), 1))
dc.SetBrush(wx.Brush(wx.Colour(0,80,80) ))
dc.DrawRectangle(10,10,w-22,h-22)
dc.DrawLine(10,h/2,w-12,h/2)
dc.DrawBitmap(img, 50, 50)
dc.SetTextForeground(wx.Colour(224,224,224))
dc.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, 'Comic Sans MS'))
dc.DrawText(u' Frost heavy leisure sorrow ', 100, 500)
dc.DrawRotatedText(u' The deep spring wind is also sick ', 250, 500, 30)
def OnPaint(self, evt):
''' Redraw event functions '''
dc = wx.PaintDC(self.palette)
self.Paint(dc)
def ReDraw(self):
''' Hand drawn '''
dc = wx.ClientDC(self.palette)
self.Paint(dc)
def Paint(self, dc):
''' mapping '''
w, h = self.palette.GetSize()
dc.Clear()
dc.SetPen(wx.Pen(wx.Colour(224,0,0), 1))
dc.SetBrush(wx.Brush(wx.Colour(0,80,80) ))
dc.DrawRectangle(10,10,w-22,h-22)
dc.DrawLine(10,h/2,w-12,h/2)
dc.DrawBitmap(self.img, 50, 50)
dc.SetTextForeground(wx.Colour(224,224,224))
dc.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, 'Comic Sans MS'))
dc.DrawText(u' Frost heavy leisure sorrow ', 100, 500)
dc.DrawRotatedText(u' The deep spring wind is also sick ', 250, 500, 30)
dc.SetPen(wx.Pen(wx.Colour(0,224,0), 2))
for line in self.lines:
dc.DrawLine(line[0],line[1],line[2],line[3])
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame(None)
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()

 Picture description here

Timers and threads

In this example, a digital clock is designed , A stopwatch , The stopwatch shows an accuracy of one tenth of a millisecond . There is no difficulty in code design , There are many ways to do this , Can want to achieve a better display effect , But it's not an easy thing . Please pay attention to experience wx.CallAfter() Conditions of use .

#-*- coding: utf-8 -*-
import wx
import win32api
import sys, os, time
import threading
APP_TITLE = u' Timers and threads '
APP_ICON = 'res/python.ico'
class mainFrame(wx.Frame):
''' Program main window class , Inherited from wx.Frame'''
def __init__(self, parent):
''' Constructors '''
wx.Frame.__init__(self, parent, -1, APP_TITLE)
self.SetBackgroundColour(wx.Colour(224, 224, 224))
self.SetSize((320, 300))
self.Center()
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
else :
icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
#font = wx.Font(24, wx.DECORATIVE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, 'Comic Sans MS')
font = wx.Font(30, wx.DECORATIVE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, 'Monaco')
self.clock = wx.StaticText(self, -1, u'08:00:00', pos=(50,50), size=(200,50), style=wx.TE_CENTER|wx.SUNKEN_BORDER)
self.clock.SetForegroundColour(wx.Colour(0, 224, 32))
self.clock.SetBackgroundColour(wx.Colour(0, 0, 0))
self.clock.SetFont(font)
self.stopwatch = wx.StaticText(self, -1, u'0:00:00.0', pos=(50,150), size=(200,50), style=wx.TE_CENTER|wx.SUNKEN_BORDER)
self.stopwatch.SetForegroundColour(wx.Colour(0, 224, 32))
self.stopwatch.SetBackgroundColour(wx.Colour(0, 0, 0))
self.stopwatch.SetFont(font)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self.timer.Start(50)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.sec_last = None
self.is_start = False
self.t_start = None
thread_sw = threading.Thread(target=self.StopWatchThread)
thread_sw.setDaemon(True)
thread_sw.start()
def OnTimer(self, evt):
''' Timer Functions '''
t = time.localtime()
if t.tm_sec != self.sec_last:
self.clock.SetLabel('%02d:%02d:%02d'%(t.tm_hour, t.tm_min, t.tm_sec))
self.sec_last = t.tm_sec
def OnKeyDown(self, evt):
''' Keyboard event function '''
if evt.GetKeyCode() == wx.WXK_SPACE:
self.is_start = not self.is_start
self.t_start= time.time()
elif evt.GetKeyCode() == wx.WXK_ESCAPE:
self.is_start = False
self.stopwatch.SetLabel('0:00:00.0')
def StopWatchThread(self):
''' Thread functions '''
while True:
if self.is_start:
n = int(10*(time.time() - self.t_start))
deci = n%10
ss = int(n/10)%60
mm = int(n/600)%60
hh = int(n/36000)
wx.CallAfter(self.stopwatch.SetLabel, '%d:%02d:%02d.%d'%(hh, mm, ss, deci))
time.sleep(0.02)
class mainApp(wx.App):
def OnInit(self):
self.SetAppName(APP_TITLE)
self.Frame = mainFrame(None)
self.Frame.Show()
return True
if __name__ == "__main__":
app = mainApp()
app.MainLoop()

 Picture description here

Postscript

Recently, a lot of friends have consulted through private letters about Python Learning problems . To facilitate communication , I am here CSDN Of app Created on “Python Homework guidance ” stronghold , oriented Python beginner , Provide consulting services for you 、 Coach Python Homework . Welcome interested students to use wechat code scanning to join .

 Insert picture description here

From blogs to official account , Every article 、 Every question 、 Every sentence 、 Every line of code , All insist on originality , Never copy , This is my principle . If you like , Please pay attention to my WeChat official account “Python Homework counselor ”.

 Insert picture description here

版权声明
本文为[Tianyuan prodigal son]所创,转载请带上原文链接,感谢

  1. 利用Python爬虫获取招聘网站职位信息
  2. Using Python crawler to obtain job information of recruitment website
  3. Several highly rated Python libraries arrow, jsonpath, psutil and tenacity are recommended
  4. Python装饰器
  5. Python实现LDAP认证
  6. Python decorator
  7. Implementing LDAP authentication with Python
  8. Vscode configures Python development environment!
  9. In Python, how dare you say you can't log module? ️
  10. 我收藏的有关Python的电子书和资料
  11. python 中 lambda的一些tips
  12. python中字典的一些tips
  13. python 用生成器生成斐波那契数列
  14. python脚本转pyc踩了个坑。。。
  15. My collection of e-books and materials about Python
  16. Some tips of lambda in Python
  17. Some tips of dictionary in Python
  18. Using Python generator to generate Fibonacci sequence
  19. The conversion of Python script to PyC stepped on a pit...
  20. Python游戏开发,pygame模块,Python实现扫雷小游戏
  21. Python game development, pyGame module, python implementation of minesweeping games
  22. Python实用工具,email模块,Python实现邮件远程控制自己电脑
  23. Python utility, email module, python realizes mail remote control of its own computer
  24. 毫无头绪的自学Python,你可能连门槛都摸不到!【最佳学习路线】
  25. Python读取二进制文件代码方法解析
  26. Python字典的实现原理
  27. Without a clue, you may not even touch the threshold【 Best learning route]
  28. Parsing method of Python reading binary file code
  29. Implementation principle of Python dictionary
  30. You must know the function of pandas to parse JSON data - JSON_ normalize()
  31. Python实用案例,私人定制,Python自动化生成爱豆专属2021日历
  32. Python practical case, private customization, python automatic generation of Adu exclusive 2021 calendar
  33. 《Python实例》震惊了,用Python这么简单实现了聊天系统的脏话,广告检测
  34. "Python instance" was shocked and realized the dirty words and advertisement detection of the chat system in Python
  35. Convolutional neural network processing sequence for Python deep learning
  36. Python data structure and algorithm (1) -- enum type enum
  37. 超全大厂算法岗百问百答(推荐系统/机器学习/深度学习/C++/Spark/python)
  38. 【Python进阶】你真的明白NumPy中的ndarray吗?
  39. All questions and answers for algorithm posts of super large factories (recommended system / machine learning / deep learning / C + + / spark / Python)
  40. [advanced Python] do you really understand ndarray in numpy?
  41. 【Python进阶】Python进阶专栏栏主自述:不忘初心,砥砺前行
  42. [advanced Python] Python advanced column main readme: never forget the original intention and forge ahead
  43. python垃圾回收和缓存管理
  44. java调用Python程序
  45. java调用Python程序
  46. Python常用函数有哪些?Python基础入门课程
  47. Python garbage collection and cache management
  48. Java calling Python program
  49. Java calling Python program
  50. What functions are commonly used in Python? Introduction to Python Basics
  51. Python basic knowledge
  52. Anaconda5.2 安装 Python 库(MySQLdb)的方法
  53. Python实现对脑电数据情绪分析
  54. Anaconda 5.2 method of installing Python Library (mysqldb)
  55. Python implements emotion analysis of EEG data
  56. Master some advanced usage of Python in 30 seconds, which makes others envy it
  57. python爬取百度图片并对图片做一系列处理
  58. Python crawls Baidu pictures and does a series of processing on them
  59. python链接mysql数据库
  60. Python link MySQL database