How to create a simple text editor (Phoenix)

Keywords : Editor, Text, TextCtrl, Stc, StyledTextCtrl.


Demonstrating :

Tested py3.x, wx4.x and Win10.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


Sample one

img_sample_one.png

   1 # sample_one.py
   2 
   3 import sys
   4 import os.path
   5 import wx
   6 
   7 # class MyFrame
   8 # class MyApp
   9 
  10 #-------------------------------------------------------------------------------
  11 
  12 # This is how you pre-establish a file filter so that the
  13 # dialog only shows the extension(s) you want it to.
  14 
  15 wildcard = "Text (*.txt)|*.txt|"        \
  16            "Executable (*.exe)|*.exe|"  \
  17            "Library (*.dll)|*.dll|"     \
  18            "Driver (*.sys)|*.sys|"      \
  19            "ActiveX (*.ocx)|*.ocx|"     \
  20            "Python (*.py)|*.py|"        \
  21            "Python (*.pyw)|*.pyw|"      \
  22            "All (*.*)|*.*"
  23 
  24 #-------------------------------------------------------------------------------
  25 
  26 class MyFrame(wx.Frame):
  27     def __init__(self, filename="noname.txt"):
  28         super(MyFrame, self).__init__(None, size=(400, 300))
  29 
  30         #------------
  31 
  32         # Return icons folder.
  33         self.icons_dir = wx.GetApp().GetIconsDir()
  34 
  35         #------------
  36 
  37         self.filename = filename
  38         self.dirname  = "."
  39 
  40         #------------
  41 
  42         # Simplified init method.
  43         self.CreateInteriorWindowComponents()
  44         self.CreateExteriorWindowComponents()
  45 
  46         #------------
  47 
  48         self.CenterOnScreen()
  49 
  50     #---------------------------------------------------------------------------
  51 
  52     def SetTitle(self):
  53         """
  54         ...
  55         """
  56 
  57         # MyFrame.SetTitle overrides wx.Frame.SetTitle,
  58         # so we have to call it using super :
  59         super(MyFrame, self).SetTitle("Editor %s" % self.filename)
  60 
  61 
  62     def CreateInteriorWindowComponents(self):
  63         """
  64         Create "interior" window components. In this case
  65         it is just a simple multiline text control.
  66         """
  67 
  68         self.control = wx.TextCtrl(self, -1, value="", style=wx.TE_MULTILINE)
  69 
  70 
  71     def CreateExteriorWindowComponents(self):
  72         """
  73         Create "exterior" window components, such as menu and status bar.
  74         """
  75 
  76         # Simplified init method.
  77         self.SetTitle()
  78 
  79         #------------
  80 
  81         frameIcon = wx.Icon(os.path.join(self.icons_dir,
  82                                          "icon_wxWidgets.ico"),
  83                             type=wx.BITMAP_TYPE_ICO)
  84         self.SetIcon(frameIcon)
  85 
  86         #------------
  87 
  88         self.CreateMenu()
  89         self.CreateStatusBar()
  90         self.BindEvents()
  91 
  92 
  93     def CreateMenu(self):
  94         """
  95         Create menu and menu bar.
  96         """
  97 
  98         menuBar = wx.MenuBar()
  99 
 100         #------------
 101 
 102         fileMenu = wx.Menu()
 103 
 104         for id, label, helpText, handler in \
 105             [(wx.ID_ABOUT, "&About",
 106               "Information about this program.", self.OnAbout),
 107              (None, None, None, None),
 108              (wx.ID_OPEN, "&Open",
 109               "Open a new file.", self.OnOpen),
 110              (wx.ID_SAVE, "&Save",
 111               "Save the current file.", self.OnSave),
 112              (wx.ID_SAVEAS, "Save &as",
 113               "Save the file under a different name.", self.OnSaveAs),
 114              (None, None, None, None),
 115              (wx.ID_EXIT, "E&xit",
 116               "Terminate the program.", self.OnCloseMe)]:
 117 
 118             if id == None:
 119                 fileMenu.AppendSeparator()
 120             else:
 121                 item = fileMenu.Append(id, label, helpText)
 122 
 123                 #------------
 124 
 125                 # Bind some events to an events handler.
 126                 self.Bind(wx.EVT_MENU, handler, item)
 127 
 128         #------------
 129 
 130         # Add the fileMenu to the menuBar.
 131         menuBar.Append(fileMenu, "&File")
 132 
 133         #------------
 134 
 135         # Add the menuBar to the frame.
 136         self.SetMenuBar(menuBar)
 137 
 138 
 139     def BindEvents(self):
 140         """
 141         ...
 142         """
 143 
 144         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 145 
 146 
 147     def DefaultFileDialogOptions(self):
 148         """
 149         Return a dictionary with file dialog options that can be
 150         used in both the save file dialog as well as in the open
 151         file dialog.
 152         """
 153 
 154         return dict(message="Choose a file :",
 155                     defaultDir=self.dirname,
 156                     wildcard=wildcard)
 157 
 158 
 159     def AskUserForFilename(self, **dialogOptions):
 160         """
 161         ...
 162         """
 163 
 164         dialog = wx.FileDialog(self, **dialogOptions)
 165 
 166         if dialog.ShowModal() == wx.ID_OK:
 167             userProvidedFilename = True
 168             self.filename = dialog.GetFilename()
 169             self.dirname = dialog.GetDirectory()
 170             # Update the window title with the new filename.
 171             self.SetTitle()
 172         else:
 173             userProvidedFilename = False
 174 
 175         dialog.Destroy()
 176 
 177         return userProvidedFilename
 178 
 179 
 180     def OnOpen(self, event):
 181         """
 182         Open file.
 183         """
 184 
 185         if self.AskUserForFilename(style=wx.FD_OPEN,
 186                                    **self.DefaultFileDialogOptions()):
 187             file = open(os.path.join(self.dirname, self.filename), 'r', encoding='utf-8')
 188             self.control.SetValue(file.read())
 189             file.close()
 190 
 191 
 192     def OnSave(self, event):
 193         """
 194         Save file.
 195         """
 196 
 197         with open(os.path.join(self.dirname, self.filename), 'w', encoding='utf-8') as file:
 198             file.write(self.control.GetValue())
 199 
 200 
 201     def OnSaveAs(self, event):
 202         """
 203         Save file as.
 204         """
 205 
 206         if self.AskUserForFilename(defaultFile=self.filename, style=wx.FD_SAVE,
 207                                    **self.DefaultFileDialogOptions()):
 208             self.OnSave(event)
 209 
 210 
 211     def OnAbout(self, event):
 212         """
 213         About dialog.
 214         """
 215 
 216         dialog = wx.MessageDialog(self,
 217                                   "A sample editor in wxPython.",
 218                                   "About sample editor",
 219                                   wx.OK)
 220         dialog.ShowModal()
 221         dialog.Destroy()
 222 
 223 
 224     def OnCloseMe(self, event):
 225         """
 226         Close the main window.
 227         """
 228 
 229         self.Close(True)
 230 
 231 
 232     def OnCloseWindow(self, event):
 233         """
 234         Quit and destroy application.
 235         """
 236 
 237         self.Destroy()
 238 
 239 #-------------------------------------------------------------------------------
 240 
 241 class MyApp(wx.App):
 242     """
 243     ....
 244     """
 245     def OnInit(self):
 246 
 247         #------------
 248 
 249         self.installDir = os.path.split(os.path.abspath(sys.argv[0]))[0]
 250 
 251         #------------
 252 
 253         frame = MyFrame()
 254         self.SetTopWindow(frame)
 255         frame.Show(True)
 256 
 257         return True
 258 
 259     #---------------------------------------------------------------------------
 260 
 261     def GetInstallDir(self):
 262         """
 263         Returns the installation directory for my application.
 264         """
 265 
 266         return self.installDir
 267 
 268 
 269     def GetIconsDir(self):
 270         """
 271         Returns the icons directory for my application.
 272         """
 273 
 274         icons_dir = os.path.join(self.installDir, "icons")
 275         return icons_dir
 276 
 277 #-------------------------------------------------------------------------------
 278 
 279 def main():
 280     app = MyApp(False)
 281     app.MainLoop()
 282 
 283 #-------------------------------------------------------------------------------
 284 
 285 if __name__ == "__main__" :
 286     main()


Sample two

img_sample_two.png

   1 # sample_two.py
   2 
   3 import sys
   4 import os.path
   5 import wx
   6 import wx.stc as stc   # StyledTextCtrl
   7 
   8 # class MyFrame
   9 # class MyApp
  10 
  11 #-------------------------------------------------------------------------------
  12 
  13 # This is how you pre-establish a file filter so that the
  14 # dialog only shows the extension(s) you want it to.
  15 
  16 wildcard = "Text (*.txt)|*.txt|"        \
  17            "Config (*.cfg)|*.cfg|"      \
  18            "Python (*.py)|*.py|"        \
  19            "Python (*.pyw)|*.pyw|"      \
  20            "All (*.*)|*.*"
  21 
  22 #-------------------------------------------------------------------------------
  23 
  24 class MyFrame(wx.Frame):
  25     def __init__(self, filename="noname.txt"):
  26         super(MyFrame, self).__init__(None, size=(400, 300))
  27 
  28         #------------
  29 
  30         # Return icons folder.
  31         self.icons_dir = wx.GetApp().GetIconsDir()
  32 
  33         #------------
  34 
  35         self.filename = filename
  36         self.dirname  = "."
  37         self.flagDirty = False
  38 
  39         #------------
  40 
  41         # Simplified init method.
  42         self.SetProperties()
  43         self.CreateMenuBar()
  44         self.CreateStyledTextControl()
  45         self.CreateStatusBar()
  46         self.BindEvents()
  47 
  48     #---------------------------------------------------------------------------
  49 
  50     def SetProperties(self):
  51         """
  52         ...
  53         """
  54 
  55         self.SetTitle()
  56 
  57         #------------
  58 
  59         frameIcon = wx.Icon(os.path.join(self.icons_dir,
  60                                          "icon_wxWidgets.ico"),
  61                             type=wx.BITMAP_TYPE_ICO)
  62         self.SetIcon(frameIcon)
  63 
  64 
  65     def SetTitle(self):
  66         """
  67         ...
  68         """
  69 
  70         # MyFrame.SetTitle overrides wx.Frame.SetTitle,
  71         # so we have to call it using super :
  72         super(MyFrame, self).SetTitle("Editor %s" % self.filename)
  73 
  74 
  75     def CreateMenuBar(self):
  76         """
  77         Create menu and menu bar.
  78         """
  79 
  80         menuBar = wx.MenuBar()
  81 
  82         #------------
  83 
  84         menu_File = wx.Menu()
  85         menu_Edit = wx.Menu()
  86         menu_About = wx.Menu()
  87 
  88         #------------
  89         #------------
  90 
  91         self.menu_File_Open = menu_File.Append(wx.ID_OPEN,
  92                                                "&Open" + "\t" + "Ctrl+O",
  93                                                "Open a new file.")
  94         #------------
  95 
  96         menu_File.AppendSeparator()
  97 
  98         #------------
  99 
 100         self.menu_File_Save = menu_File.Append(wx.ID_SAVE,
 101                                                "&Save" + "\t" + "Ctrl+S",
 102                                                "Save the current file.")
 103         self.menu_File_SaveAs = menu_File.Append(wx.ID_SAVEAS,
 104                                                  "&Save as" + "\t" + "Ctrl+Shift+S",
 105                                                  "Save the file under a different name.")
 106 
 107         #------------
 108 
 109         menu_File.AppendSeparator()
 110 
 111         #------------
 112 
 113         self.menu_File_Close = menu_File.Append(wx.ID_EXIT,
 114                                                 "&Exit" + "\t" + "Ctrl+X",
 115                                                 "Exit the program.")
 116         #------------
 117 
 118         self.menu_Edit_Cut = menu_Edit.Append(wx.ID_CUT,
 119                                               "&Cut" + "\t" + "Ctrl+X",
 120                                               "Cut")
 121         self.menu_Edit_Copy = menu_Edit.Append(wx.ID_COPY,
 122                                                "&Copy" + "\t" + "Ctrl+C",
 123                                                "Copy")
 124         self.menu_Edit_Paste = menu_Edit.Append(wx.ID_PASTE,
 125                                                 "&Paste" + "\t" + "Ctrl+V",
 126                                                 "Paste")
 127         #------------
 128 
 129         menu_Edit.AppendSeparator()
 130 
 131         #------------
 132 
 133         self.menu_Edit_Undo = menu_Edit.Append(wx.ID_UNDO,
 134                                                "&Undo" + "\t" + "Ctrl+Z",
 135                                                "Undo")
 136         self.menu_Edit_Redo = menu_Edit.Append(wx.ID_REDO,
 137                                                "&Redo" + "\t" + "Ctrl+Shift+Z",
 138                                                "Redo")
 139 
 140         #------------
 141 
 142         self.menu_About_Info = menu_About.Append(wx.ID_ABOUT,
 143                                                  "&About" + "\t" + "Ctrl+I",
 144                                                  "Information about this program.")
 145 
 146         #------------
 147         #------------
 148 
 149         menuBar.Append(menu_File, "File")
 150         menuBar.Append(menu_Edit, "Edit")
 151         menuBar.Append(menu_About, "About")
 152 
 153         #------------
 154 
 155         self.SetMenuBar(menuBar)
 156 
 157 
 158     def CreateStyledTextControl(self):
 159         """
 160         ...
 161         """
 162 
 163         self.St_TextCtrl = stc.StyledTextCtrl(self)
 164         self.St_TextCtrl.SetWindowStyle(self.St_TextCtrl.GetWindowStyle() | wx.DOUBLE_BORDER)
 165         self.St_TextCtrl.StyleSetSpec(stc.STC_STYLE_DEFAULT, "size:10,face:Courier New")
 166         self.St_TextCtrl.SetWrapMode(stc.STC_WRAP_WORD)
 167 
 168         #------------
 169 
 170         layout = wx.BoxSizer(wx.HORIZONTAL)
 171         layout.Add(self.St_TextCtrl, proportion=1, border=0, flag=wx.ALL|wx.EXPAND)
 172         self.SetSizer(layout)
 173 
 174         #------------
 175 
 176         self.St_TextCtrl.Bind(stc.EVT_STC_CHANGE, self.OnChangeTxtCtrl)
 177 
 178 
 179     def BindEvents(self):
 180         """
 181         ...
 182         """
 183 
 184         self.Bind(wx.EVT_MENU, self.OnOpen, self.menu_File_Open)
 185         self.Bind(wx.EVT_MENU, self.OnSave, self.menu_File_Save)
 186         self.Bind(wx.EVT_MENU, self.OnSaveAs, self.menu_File_SaveAs)
 187         self.Bind(wx.EVT_MENU, self.OnCloseMe, self.menu_File_Close)
 188         self.Bind(wx.EVT_MENU, self.OnCut, self.menu_Edit_Cut)
 189         self.Bind(wx.EVT_MENU, self.OnCopy, self.menu_Edit_Copy)
 190         self.Bind(wx.EVT_MENU, self.OnPaste, self.menu_Edit_Paste)
 191         self.Bind(wx.EVT_MENU, self.OnUndo, self.menu_Edit_Undo)
 192         self.Bind(wx.EVT_MENU, self.OnRedo, self.menu_Edit_Redo)
 193         self.Bind(wx.EVT_MENU, self.OnAbout, self.menu_About_Info)
 194 
 195         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 196 
 197 
 198     def OnChangeTxtCtrl(self, event):
 199         """
 200         ...
 201         """
 202 
 203         lines = self.St_TextCtrl.GetLineCount()
 204         width = self.St_TextCtrl.TextWidth(stc.STC_STYLE_LINENUMBER, str(lines) + " ")
 205         self.St_TextCtrl.SetMarginWidth(0, width)
 206 
 207         self.flagDirty = True
 208 
 209 
 210     def DefaultFileDialogOptions(self):
 211         """
 212         Return a dictionary with file dialog options that can be
 213         used in both the save file dialog as well as in the open
 214         file dialog.
 215         """
 216 
 217         return dict(message="Choose a file :",
 218                     defaultDir=self.dirname,
 219                     wildcard=wildcard)
 220 
 221 
 222     def AskUserForFilename(self, **dialogOptions):
 223         """
 224         ...
 225         """
 226 
 227         dialog = wx.FileDialog(self, **dialogOptions)
 228 
 229         if dialog.ShowModal() == wx.ID_OK:
 230             userProvidedFilename = True
 231             self.filename = dialog.GetFilename()
 232             self.dirname = dialog.GetDirectory()
 233             # Update the window title with the new filename.
 234             self.SetTitle()
 235         else:
 236             userProvidedFilename = False
 237 
 238         dialog.Destroy()
 239 
 240         return userProvidedFilename
 241 
 242 
 243     def OnOpen(self, event):
 244         """
 245         Open file.
 246         """
 247 
 248         if self.AskUserForFilename(style=wx.FD_OPEN,
 249                                    **self.DefaultFileDialogOptions()):
 250             file = open(os.path.join(self.dirname, self.filename), 'r', encoding='utf-8')
 251             self.St_TextCtrl.SetValue(file.read())
 252             file.close()
 253 
 254 
 255     def OnSave(self, event):
 256         """
 257         Save file.
 258         """
 259 
 260         with open(os.path.join(self.dirname, self.filename), 'w', encoding='utf-8') as file:
 261             file.write(self.St_TextCtrl.GetValue())
 262 
 263 
 264     def OnSaveAs(self, event):
 265         """
 266         Save file as.
 267         """
 268 
 269         if self.AskUserForFilename(defaultFile=self.filename, style=wx.FD_SAVE,
 270                                    **self.DefaultFileDialogOptions()):
 271             self.OnSave(event)
 272 
 273 
 274     def OnCut(self, event):
 275         """
 276         ...
 277         """
 278 
 279         self.St_TextCtrl.Cut()
 280 
 281 
 282     def OnCopy(self, event):
 283         """
 284         ...
 285         """
 286 
 287         self.St_TextCtrl.Copy()
 288 
 289 
 290     def OnPaste(self, event):
 291         """
 292         ...
 293         """
 294 
 295         self.St_TextCtrl.Paste()
 296 
 297 
 298     def OnUndo(self, event):
 299         """
 300         ...
 301         """
 302 
 303         self.St_TextCtrl.Undo()
 304 
 305 
 306     def OnRedo(self, event):
 307         """
 308         ...
 309         """
 310 
 311         self.St_TextCtrl.Redo()
 312 
 313 
 314     def OnAbout(self, event):
 315         """
 316         About dialog.
 317         """
 318 
 319         dialog = wx.MessageDialog(self,
 320                                   "A sample StyledTextCtrl editor in wxPython.",
 321                                   "About sample editor",
 322                                   wx.OK)
 323         dialog.ShowModal()
 324         dialog.Destroy()
 325 
 326 
 327     def OnCloseMe(self, event):
 328         """
 329         Close the main window.
 330         """
 331 
 332         self.Close(True)
 333 
 334 
 335     def OnCloseWindow(self, event):
 336         """
 337         Quit and destroy application.
 338         """
 339 
 340         self.Destroy()
 341 
 342 #-------------------------------------------------------------------------------
 343 
 344 class MyApp(wx.App):
 345     """
 346     ....
 347     """
 348     def OnInit(self):
 349 
 350         #------------
 351 
 352         self.installDir = os.path.split(os.path.abspath(sys.argv[0]))[0]
 353 
 354         #------------
 355 
 356         frame = MyFrame()
 357         self.SetTopWindow(frame)
 358         frame.Show(True)
 359 
 360         return True
 361 
 362     #---------------------------------------------------------------------------
 363 
 364     def GetInstallDir(self):
 365         """
 366         Returns the installation directory for my application.
 367         """
 368 
 369         return self.installDir
 370 
 371 
 372     def GetIconsDir(self):
 373         """
 374         Returns the icons directory for my application.
 375         """
 376 
 377         icons_dir = os.path.join(self.installDir, "icons")
 378         return icons_dir
 379 
 380 #-------------------------------------------------------------------------------
 381 
 382 def main():
 383     app = MyApp(False)
 384     app.MainLoop()
 385 
 386 #-------------------------------------------------------------------------------
 387 
 388 if __name__ == "__main__" :
 389     main()


Sample three

img_sample_three.png

Here we have a simple text editor. Notice the use of exceptions. It is a programmer's task to find and handle bugs. This includes doing such nasty things like opening pictures in an editor, simulating all possible situations. If a script raises an unhandled exception, we simply write a code that handles this (info by ZetCode / Jan Bodnar).

   1 # sample_three.py
   2 
   3 """
   4 
   5 Author : Zetcode
   6 Created : Apr., 2007
   7 Updated : Nov. 16, 2020 by Ecco
   8 
   9 """
  10 
  11 import wx
  12 import os
  13 
  14 # Editor
  15 
  16 #---------------------------------------------------------------------------
  17 
  18 TBFLAGS = ( wx.TB_HORIZONTAL
  19             | wx.NO_BORDER
  20             | wx.TB_FLAT
  21             #| wx.TB_TEXT
  22             #| wx.TB_HORZ_LAYOUT
  23             )
  24 
  25 # This is how you pre-establish a file filter so that the dialog
  26 # only shows the extension(s) you want it to.
  27 wildcard = "Python source (*.py)|*.py|"     \
  28            "Compiled Python (*.pyc)|*.pyc|" \
  29            "SPAM files (*.spam)|*.spam|"    \
  30            "Egg file (*.egg)|*.egg|"        \
  31            "All files (*.*)|*.*"
  32 
  33 #---------------------------------------------------------------------------
  34 
  35 class Editor(wx.Frame):
  36     def __init__(self, parent, id, title):
  37         wx.Frame.__init__(self, parent, id, title, size=(400, 300))
  38 
  39         #------------
  40 
  41         icon = wx.Icon("./icons/icon_wxWidgets.ico")
  42         self.SetIcon(icon)
  43 
  44         #------------
  45 
  46         # Variables.
  47         self.modify = False
  48         self.last_name_saved = ''
  49         self.replace = False
  50 
  51         #------------
  52 
  53         # Setting up menubar.
  54         menubar = wx.MenuBar()
  55 
  56         file = wx.Menu()
  57         new = wx.MenuItem(file, 101, '&New\tCtrl+N', 'Creates a new document.')
  58         new.SetBitmap(wx.Bitmap('./images/stock_new-16.png'))
  59         file.Append(new)
  60 
  61         open = wx.MenuItem(file, 102, '&Open\tCtrl+O', 'Open an existing file.')
  62         open.SetBitmap(wx.Bitmap('./images/stock_open-16.png'))
  63         file.Append(open)
  64         file.AppendSeparator()
  65 
  66         save = wx.MenuItem(file, 103, '&Save\tCtrl+S', 'Save the file.')
  67         save.SetBitmap(wx.Bitmap('./images/stock_save-16.png'))
  68         file.Append(save)
  69 
  70         saveas = wx.MenuItem(file, 104, 'Save &as...\tShift+Ctrl+S', 'Save the file with a different name.')
  71         saveas.SetBitmap(wx.Bitmap('./images/stock_save_as-16.png'))
  72         file.Append(saveas)
  73         file.AppendSeparator()
  74 
  75         quit = wx.MenuItem(file, 105, '&Quit\tCtrl+Q', 'Quit the application.')
  76         quit.SetBitmap(wx.Bitmap('./images/stock_exit-16.png'))
  77         file.Append(quit)
  78 
  79         edit = wx.Menu()
  80         cut = wx.MenuItem(edit, 106, 'C&ut\tCtrl+X', 'Cut the selection.')
  81         cut.SetBitmap(wx.Bitmap('./images/stock_cut-16.png'))
  82         edit.Append(cut)
  83 
  84         copy = wx.MenuItem(edit, 107, '&Copy\tCtrl+C', 'Copy the selection.')
  85         copy.SetBitmap(wx.Bitmap('./images/stock_copy-16.png'))
  86         edit.Append(copy)
  87 
  88         paste = wx.MenuItem(edit, 108, '&Paste\tCtrl+V', 'Paste text from clipboard.')
  89         paste.SetBitmap(wx.Bitmap('./images/stock_paste-16.png'))
  90         edit.Append(paste)
  91 
  92         delete = wx.MenuItem(edit, 109, '&Delete', 'Delete the selected text.')
  93         delete.SetBitmap(wx.Bitmap('./images/stock_delete-16.png'))
  94 
  95         edit.Append(delete)
  96         edit.AppendSeparator()
  97         edit.Append(110, 'Select &All\tCtrl+A', 'Select the entire text.')
  98 
  99         view = wx.Menu()
 100         view.Append(111, '&Statusbar', 'Show StatusBar.')
 101 
 102         help = wx.Menu()
 103         about = wx.MenuItem(help, 112, '&About\tF1', 'About Editor.')
 104         about.SetBitmap(wx.Bitmap('./images/stock_about-16.png'))
 105         help.Append(about)
 106 
 107         menubar.Append(file, '&File')
 108         menubar.Append(edit, '&Edit')
 109         menubar.Append(view, '&View')
 110         menubar.Append(help, '&Help')
 111 
 112         self.SetMenuBar(menubar)
 113 
 114         #------------
 115 
 116         # setting up toolbar
 117         self.toolbar = self.CreateToolBar(TBFLAGS)
 118         self.toolbar.AddTool(801, "New", wx.Image('./images/stock_new.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 119                              wx.NullBitmap, wx.ITEM_NORMAL, 'New', "Long help for 'New'", None)
 120         self.toolbar.AddTool(802, "Open", wx.Image('./images/stock_open.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 121                              wx.NullBitmap, wx.ITEM_NORMAL, 'Open', "Long help for 'Open'", None)
 122         self.toolbar.AddTool(803, "Save", wx.Image('./images/stock_save.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 123                              wx.NullBitmap, wx.ITEM_NORMAL, 'Save', "Long help for 'Save'", None)
 124         self.toolbar.AddSeparator()
 125 
 126         self.toolbar.AddTool(804, "Cut", wx.Image('./images/stock_cut.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 127                              wx.NullBitmap, wx.ITEM_NORMAL, 'Cut', "Long help for 'Cut'", None)
 128         self.toolbar.AddTool(805, "Copy", wx.Image('./images/stock_copy.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 129                              wx.NullBitmap, wx.ITEM_NORMAL, 'Copy', "Long help for 'Copy'", None)
 130         self.toolbar.AddTool(806, "Paste", wx.Image('./images/stock_paste.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 131                              wx.NullBitmap, wx.ITEM_NORMAL, 'Paste', "Long help for 'Paste'", None)
 132         self.toolbar.AddSeparator()
 133 
 134         self.toolbar.AddTool(807, "Exit", wx.Image('./images/stock_exit.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(),
 135                              wx.NullBitmap, wx.ITEM_NORMAL, 'Exit', "Long help for 'Exit'", None)
 136 
 137         self.toolbar.Realize()
 138 
 139         #------------
 140 
 141         self.text = wx.TextCtrl(self, 1000, '', size=(-1, -1), style=wx.TE_MULTILINE | wx.TE_PROCESS_ENTER)
 142         self.text.SetFocus()
 143 
 144         #------------
 145 
 146         self.text.Bind(wx.EVT_TEXT, self.OnTextChanged, id=1000)
 147         self.text.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
 148 
 149         self.Bind(wx.EVT_MENU, self.NewApplication, id=101)
 150         self.Bind(wx.EVT_MENU, self.OnOpenFile, id=102)
 151         self.Bind(wx.EVT_MENU, self.OnSaveFile, id=103)
 152         self.Bind(wx.EVT_MENU, self.OnSaveAsFile, id=104)
 153         self.Bind(wx.EVT_MENU, self.QuitApplication, id=105)
 154         self.Bind(wx.EVT_MENU, self.OnCut, id=106)
 155         self.Bind(wx.EVT_MENU, self.OnCopy, id=107)
 156         self.Bind(wx.EVT_MENU, self.OnPaste, id=108)
 157         self.Bind(wx.EVT_MENU, self.OnDelete, id=109)
 158         self.Bind(wx.EVT_MENU, self.OnSelectAll, id=110)
 159         self.Bind(wx.EVT_MENU, self.ToggleStatusBar, id=111)
 160         self.Bind(wx.EVT_MENU, self.OnAbout, id=112)
 161 
 162         self.Bind(wx.EVT_TOOL, self.NewApplication, id=801)
 163         self.Bind(wx.EVT_TOOL, self.OnOpenFile, id=802)
 164         self.Bind(wx.EVT_TOOL, self.OnSaveFile, id=803)
 165         self.Bind(wx.EVT_TOOL, self.OnCut, id=804)
 166         self.Bind(wx.EVT_TOOL, self.OnCopy, id=805)
 167         self.Bind(wx.EVT_TOOL, self.OnPaste, id=806)
 168         self.Bind(wx.EVT_TOOL, self.QuitApplication, id=807)
 169 
 170         self.Bind(wx.EVT_CLOSE, self.QuitApplication)
 171 
 172         #------------
 173 
 174         vbox = wx.BoxSizer(wx.VERTICAL)
 175         vbox.Add(self.text, 1, wx.EXPAND, border=0)
 176 
 177         self.SetSizer(vbox)
 178 
 179         #------------
 180 
 181         self.StatusBar()
 182 
 183         #------------
 184 
 185         self.Centre()
 186 
 187         #------------
 188 
 189         self.Show(True)
 190 
 191     #-----------------------------------------------------------------------
 192 
 193     def NewApplication(self, event):
 194         editor = Editor(None, -1, 'Editor')
 195         editor.Centre()
 196         editor.Show()
 197 
 198 
 199     def OnOpenFile(self, event):
 200         file_name = os.path.basename(self.last_name_saved)
 201 
 202         if self.modify:
 203             dlg = wx.MessageDialog(self,
 204                                    'Save changes ?',
 205                                    '',
 206                                    wx.YES_NO |
 207                                    wx.YES_DEFAULT |
 208                                    wx.CANCEL |
 209                                    wx.ICON_QUESTION)
 210 
 211             val = dlg.ShowModal()
 212             if val == wx.ID_YES:
 213                 self.OnSaveFile(event)
 214                 self.DoOpenFile()
 215             elif val == wx.ID_CANCEL:
 216                 dlg.Destroy()
 217             else:
 218                 self.DoOpenFile()
 219         else:
 220             self.DoOpenFile()
 221 
 222 
 223     def DoOpenFile(self):
 224         open_dlg = wx.FileDialog(self,
 225                                  message="Choose a file",
 226                                  defaultDir=os.getcwd(),
 227                                  defaultFile="",
 228                                  wildcard=wildcard,
 229                                  style=wx.FD_OPEN |
 230                                        wx.FD_CHANGE_DIR |
 231                                        wx.FD_FILE_MUST_EXIST |
 232                                        wx.FD_PREVIEW)
 233 
 234         if open_dlg.ShowModal() == wx.ID_OK:
 235             path = open_dlg.GetPath()
 236 
 237             try:
 238                 file = open(path, 'r')
 239                 text = file.read()
 240                 file.close()
 241                 if self.text.GetLastPosition():
 242                     self.text.Clear()
 243                 self.text.WriteText(text)
 244                 self.last_name_saved = path
 245                 self.statusbar.SetStatusText('', 1)
 246                 self.modify = False
 247 
 248             except IOError as error:
 249                 dlg = wx.MessageDialog(self, 'Error opening file\n' + str(error))
 250                 dlg.ShowModal()
 251 
 252             except UnicodeDecodeError as error:
 253                 dlg = wx.MessageDialog(self, 'Error opening file\n' + str(error))
 254                 dlg.ShowModal()
 255 
 256         open_dlg.Destroy()
 257 
 258 
 259     def OnSaveFile(self, event):
 260         if self.last_name_saved:
 261 
 262             try:
 263                 file = open(self.last_name_saved, 'w')
 264                 text = self.text.GetValue()
 265                 file.write(text)
 266                 file.close()
 267                 self.statusbar.SetStatusText(os.path.basename(self.last_name_saved) + ' Saved', 0)
 268                 self.modify = False
 269                 self.statusbar.SetStatusText('', 1)
 270 
 271             except IOError as error:
 272                 dlg = wx.MessageDialog(self, 'Error saving file\n' + str(error))
 273                 dlg.ShowModal()
 274         else:
 275             self.OnSaveAsFile(event)
 276 
 277 
 278     def OnSaveAsFile(self, event):
 279         save_dlg = wx.FileDialog(self, message="Save file as ...",
 280                                  defaultDir=os.getcwd(),
 281                                  defaultFile="",
 282                                  wildcard=wildcard,
 283                                  style=wx.FD_SAVE |
 284                                        wx.FD_OVERWRITE_PROMPT)
 285         save_dlg.SetFilterIndex(0)
 286 
 287         if save_dlg.ShowModal() == wx.ID_OK:
 288             path = save_dlg.GetPath()
 289 
 290             try:
 291                 file = open(path, 'w')
 292                 text = self.text.GetValue()
 293                 file.write(text)
 294                 file.close()
 295                 self.last_name_saved = os.path.basename(path)
 296                 self.statusbar.SetStatusText(self.last_name_saved + ' Saved', 0)
 297                 self.modify = False
 298                 self.statusbar.SetStatusText('', 1)
 299 
 300             except IOError as error:
 301                 dlg = wx.MessageDialog(self, 'Error saving file\n' + str(error))
 302                 dlg.ShowModal()
 303         save_dlg.Destroy()
 304 
 305 
 306     def OnCut(self, event):
 307         self.text.Cut()
 308 
 309 
 310     def OnCopy(self, event):
 311         self.text.Copy()
 312 
 313 
 314     def OnPaste(self, event):
 315         self.text.Paste()
 316 
 317 
 318     def QuitApplication(self, event):
 319         if self.modify:
 320             dlg = wx.MessageDialog(self, 'Save before Exit ?', '', wx.YES_NO | wx.YES_DEFAULT |
 321                         wx.CANCEL | wx.ICON_QUESTION)
 322             val = dlg.ShowModal()
 323             if val == wx.ID_YES:
 324                 self.OnSaveFile(event)
 325                 if not self.modify:
 326                     wx.Exit()
 327             elif val == wx.ID_CANCEL:
 328                 dlg.Destroy()
 329             else:
 330                 self.Destroy()
 331         else:
 332             self.Destroy()
 333 
 334 
 335     def OnDelete(self, event):
 336         frm, to = self.text.GetSelection()
 337         self.text.Remove(frm, to)
 338 
 339 
 340     def OnSelectAll(self, event):
 341         self.text.SelectAll()
 342 
 343 
 344     def OnTextChanged(self, event):
 345         self.modify = True
 346         self.statusbar.SetStatusText(' Modified', 1)
 347 
 348         event.Skip()
 349 
 350 
 351     def OnKeyDown(self, event):
 352         keycode = event.GetKeyCode()
 353         if keycode == wx.WXK_INSERT:
 354             if not self.replace:
 355                 self.statusbar.SetStatusText('INS', 2)
 356                 self.replace = True
 357             else:
 358                 self.statusbar.SetStatusText('', 2)
 359                 self.replace = False
 360         event.Skip()
 361 
 362 
 363     def ToggleStatusBar(self, event):
 364         if self.statusbar.IsShown():
 365             self.statusbar.Hide()
 366         else:
 367             self.statusbar.Show()
 368         self.SendSizeEvent()
 369 
 370 
 371     def StatusBar(self):
 372         self.statusbar = self.CreateStatusBar()
 373         self.statusbar.SetFieldsCount(3)
 374         self.statusbar.SetStatusWidths([-5, -2, -1])
 375 
 376 
 377     def OnAbout(self, event):
 378         dlg = wx.MessageDialog(self,
 379                                '\tEditor\t\n'\
 380                                '\n'\
 381                                'Another Tutorial\n'\
 382                                'Jan Bodnar 2005-2006\n'\
 383                                'Updated by Ecco 2020.',
 384                                'About Editor',
 385                                wx.OK |
 386                                wx.ICON_INFORMATION)
 387         dlg.ShowModal()
 388         dlg.Destroy()
 389 
 390 #---------------------------------------------------------------------------
 391 
 392 
 393 app = wx.App()
 394 Editor(None, -1, 'Editor')
 395 app.MainLoop()


Download source

source.zip


Additional Information

Link :

https://teratail.com/questions/124859?link=qa_related_pc

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

??? (sample_one.py coding), ??? (sample_two.py coding), Jan Bodnar (sample_three.py coding), the wxPython community...


About this page

Date(d/m/y) Person (bot) Comments :

19/07/20 - Ecco (Created page and updated examples for wxPython Phoenix).


Comments

- blah, blah, blah....

How to create a simple text editor (Phoenix) (last edited 2020-12-14 14:39:39 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.