|
|
Строка 1: |
Строка 1: |
- | In this section we will show some small, complete scripts. These graphical scripts or "gripts" will demonstrate various areas in programming. Programming in Python, wxPython is easier than in most other toolkits. But it is still a laborious task. There is a long, long way from easy scripts to professional applications.
| |
| | | |
- | == Tom ==
| |
- | Each application should have a good name. Short and easily remembered. So, we have Tom. A simple gript that sends an email.
| |
- |
| |
- | [[image: wxPython_faq_tom.png | center]]
| |
- |
| |
- | <source lang="python">
| |
- | #!/usr/bin/python
| |
- | # Tom
| |
- |
| |
- | import wx
| |
- | import smtplib
| |
- |
| |
- | class Tom(wx.Dialog):
| |
- | def __init__(self, parent, id, title):
| |
- | wx.Dialog.__init__(self, parent, id, title, size=(400, 420))
| |
- |
| |
- | panel = wx.Panel(self, -1)
| |
- | vbox = wx.BoxSizer(wx.VERTICAL)
| |
- | hbox1 = wx.BoxSizer(wx.HORIZONTAL)
| |
- | hbox2 = wx.BoxSizer(wx.HORIZONTAL)
| |
- | hbox3 = wx.BoxSizer(wx.HORIZONTAL)
| |
- |
| |
- | st1 = wx.StaticText(panel, -1, 'From')
| |
- | st2 = wx.StaticText(panel, -1, 'To ')
| |
- | st3 = wx.StaticText(panel, -1, 'Subject')
| |
- |
| |
- | self.tc1 = wx.TextCtrl(panel, -1, size=(180, -1))
| |
- | self.tc2 = wx.TextCtrl(panel, -1, size=(180, -1))
| |
- | self.tc3 = wx.TextCtrl(panel, -1, size=(180, -1))
| |
- |
| |
- | self.write = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
| |
- | button_send = wx.Button(panel, 1, 'Send')
| |
- |
| |
- | hbox1.Add(st1, 0, wx.LEFT, 10)
| |
- | hbox1.Add(self.tc1, 0, wx.LEFT, 35)
| |
- | hbox2.Add(st2, 0, wx.LEFT, 10)
| |
- | hbox2.Add(self.tc2, 0, wx.LEFT, 50)
| |
- | hbox3.Add(st3, 0, wx.LEFT, 10)
| |
- | hbox3.Add(self.tc3, 0, wx.LEFT, 20)
| |
- | vbox.Add(hbox1, 0, wx.TOP, 10)
| |
- | vbox.Add(hbox2, 0, wx.TOP, 10)
| |
- | vbox.Add(hbox3, 0, wx.TOP, 10)
| |
- | vbox.Add(self.write, 1, wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, 15)
| |
- | vbox.Add(button_send, 0, wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, 20)
| |
- |
| |
- | self.Bind(wx.EVT_BUTTON, self.OnSend, id=1)
| |
- | panel.SetSizer(vbox)
| |
- |
| |
- | self.Centre()
| |
- | self.ShowModal()
| |
- | self.Destroy()
| |
- |
| |
- | def OnSend(self, event):
| |
- | sender = self.tc1.GetValue()
| |
- | recipient = self.tc2.GetValue()
| |
- | subject = self.tc3.GetValue()
| |
- | text = self.write.GetValue()
| |
- | header = 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n' % (sender, recipient, subject)
| |
- | message = header + text
| |
- |
| |
- | try:
| |
- | server = smtplib.SMTP('mail.chello.sk')
| |
- | server.sendmail(sender, recipient, message)
| |
- | server.quit()
| |
- | dlg = wx.MessageDialog(self, 'Email was successfully sent', 'Success',
| |
- | wx.OK | wx.ICON_INFORMATION)
| |
- | dlg.ShowModal()
| |
- | dlg.Destroy()
| |
- |
| |
- | except smtplib.SMTPException, error:
| |
- | dlg = wx.MessageDialog(self, 'Failed to send email', 'Error', wx.OK | wx.ICON_ERROR)
| |
- | dlg.ShowModal()
| |
- | dlg.Destroy()
| |
- |
| |
- |
| |
- | app = wx.App()
| |
- | Tom(None, -1, 'Tom')
| |
- | app.MainLoop()
| |
- | </source>
| |
- |
| |
- | For working with emails we need to import smtp module. This module is part of the python language.
| |
- |
| |
- | <source lang="python">
| |
- | import smtplib
| |
- | </source>
| |
- |
| |
- | From, To and Subject options must be separated by carriedge return and newline as shown here. This weird thing is requested by RFC 821 norm. So we must follow it.
| |
- |
| |
- | <source lang="python">
| |
- | header = 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n' % (sender, recipient, subject)
| |
- | </source>
| |
- |
| |
- | Next we create an SMTP connection. Here you specify your settings. Each ISP gives you the name of the pop and smtp servers. In my case, 'mail.chello.sk' is a name for both. A mail is sent by calling the sendmail() method. Finally, we quit the connection with the quit() method.
| |
- |
| |
- | <source lang="python">
| |
- | server = smtplib.SMTP('mail.chello.sk')
| |
- | server.sendmail(sender, recipient, message)
| |
- | server.quit()
| |
- | </source>
| |
- |
| |
- | == Editor ==
| |
- |
| |
- | This editor example is the largest so far.
| |
- |
| |
- | [[image: wxPython_faq_editor.png | center]]
| |
- |
| |
- | <source lang="python">
| |
- | #!/usr/bin/python
| |
- | # Editor
| |
- |
| |
- | import wx
| |
- | import os
| |
- |
| |
- | class Editor(wx.Frame):
| |
- | def __init__(self, parent, id, title):
| |
- | wx.Frame.__init__(self, parent, id, title, size=(600, 500))
| |
- |
| |
- | # variables
| |
- | self.modify = False
| |
- | self.last_name_saved = ''
| |
- | self.replace = False
| |
- |
| |
- | # setting up menubar
| |
- | menubar = wx.MenuBar()
| |
- |
| |
- | file = wx.Menu()
| |
- | new = wx.MenuItem(file, 101, '&New\tCtrl+N', 'Creates a new document')
| |
- | new.SetBitmap(wx.Bitmap('icons/stock_new-16.png'))
| |
- | file.AppendItem(new)
| |
- |
| |
- | open = wx.MenuItem(file, 102, '&Open\tCtrl+O', 'Open an existing file')
| |
- | open.SetBitmap(wx.Bitmap('icons/stock_open-16.png'))
| |
- | file.AppendItem(open)
| |
- | file.AppendSeparator()
| |
- |
| |
- | save = wx.MenuItem(file, 103, '&Save\tCtrl+S', 'Save the file')
| |
- | save.SetBitmap(wx.Bitmap('icons/stock_save-16.png'))
| |
- | file.AppendItem(save)
| |
- |
| |
- | saveas = wx.MenuItem(file, 104, 'Save &As...\tShift+Ctrl+S',
| |
- | 'Save the file with a different name')
| |
- | saveas.SetBitmap(wx.Bitmap('icons/stock_save_as-16.png'))
| |
- | file.AppendItem(saveas)
| |
- | file.AppendSeparator()
| |
- |
| |
- | quit = wx.MenuItem(file, 105, '&Quit\tCtrl+Q', 'Quit the Application')
| |
- | quit.SetBitmap(wx.Bitmap('icons/stock_exit-16.png'))
| |
- | file.AppendItem(quit)
| |
- |
| |
- | edit = wx.Menu()
| |
- | cut = wx.MenuItem(edit, 106, '&Cut\tCtrl+X', 'Cut the Selection')
| |
- | cut.SetBitmap(wx.Bitmap('icons/stock_cut-16.png'))
| |
- | edit.AppendItem(cut)
| |
- |
| |
- | copy = wx.MenuItem(edit, 107, '&Copy\tCtrl+C', 'Copy the Selection')
| |
- | copy.SetBitmap(wx.Bitmap('icons/stock_copy-16.png'))
| |
- | edit.AppendItem(copy)
| |
- |
| |
- | paste = wx.MenuItem(edit, 108, '&Paste\tCtrl+V', 'Paste text from clipboard')
| |
- | paste.SetBitmap(wx.Bitmap('icons/stock_paste-16.png'))
| |
- | edit.AppendItem(paste)
| |
- |
| |
- | delete = wx.MenuItem(edit, 109, '&Delete', 'Delete the selected text')
| |
- | delete.SetBitmap(wx.Bitmap('icons/stock_delete-16.png',))
| |
- |
| |
- | edit.AppendItem(delete)
| |
- | edit.AppendSeparator()
| |
- | edit.Append(110, 'Select &All\tCtrl+A', 'Select the entire text')
| |
- |
| |
- | view = wx.Menu()
| |
- | view.Append(111, '&Statusbar', 'Show StatusBar')
| |
- |
| |
- | help = wx.Menu()
| |
- | about = wx.MenuItem(help, 112, '&About\tF1', 'About Editor')
| |
- | about.SetBitmap(wx.Bitmap('icons/stock_about-16.png'))
| |
- | help.AppendItem(about)
| |
- |
| |
- | menubar.Append(file, '&File')
| |
- | menubar.Append(edit, '&Edit')
| |
- | menubar.Append(view, '&View')
| |
- | menubar.Append(help, '&Help')
| |
- | self.SetMenuBar(menubar)
| |
- |
| |
- | self.Bind(wx.EVT_MENU, self.NewApplication, id=101)
| |
- | self.Bind(wx.EVT_MENU, self.OnOpenFile, id=102)
| |
- | self.Bind(wx.EVT_MENU, self.OnSaveFile, id=103)
| |
- | self.Bind(wx.EVT_MENU, self.OnSaveAsFile, id=104)
| |
- | self.Bind(wx.EVT_MENU, self.QuitApplication, id=105)
| |
- | self.Bind(wx.EVT_MENU, self.OnCut, id=106)
| |
- | self.Bind(wx.EVT_MENU, self.OnCopy, id=107)
| |
- | self.Bind(wx.EVT_MENU, self.OnPaste, id=108)
| |
- | self.Bind(wx.EVT_MENU, self.OnDelete, id=109)
| |
- | self.Bind(wx.EVT_MENU, self.OnSelectAll, id=110)
| |
- | self.Bind(wx.EVT_MENU, self.ToggleStatusBar, id=111)
| |
- | self.Bind(wx.EVT_MENU, self.OnAbout, id=112)
| |
- |
| |
- | # setting up toolbar
| |
- | self.toolbar = self.CreateToolBar( wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT
| |
- | | wx.TB_TEXT )
| |
- | self.toolbar.AddSimpleTool(801, wx.Bitmap('icons/stock_new.png'), 'New', '')
| |
- | self.toolbar.AddSimpleTool(802, wx.Bitmap('icons/stock_open.png'), 'Open', '')
| |
- | self.toolbar.AddSimpleTool(803, wx.Bitmap('icons/stock_save.png'), 'Save', '')
| |
- | self.toolbar.AddSeparator()
| |
- |
| |
- | self.toolbar.AddSimpleTool(804, wx.Bitmap('icons/stock_cut.png'), 'Cut', '')
| |
- | self.toolbar.AddSimpleTool(805, wx.Bitmap('icons/stock_copy.png'), 'Copy', '')
| |
- | self.toolbar.AddSimpleTool(806, wx.Bitmap('icons/stock_paste.png'), 'Paste', '')
| |
- | self.toolbar.AddSeparator()
| |
- |
| |
- | self.toolbar.AddSimpleTool(807, wx.Bitmap('icons/stock_exit.png'), 'Exit', '')
| |
- | self.toolbar.Realize()
| |
- |
| |
- | self.Bind(wx.EVT_TOOL, self.NewApplication, id=801)
| |
- | self.Bind(wx.EVT_TOOL, self.OnOpenFile, id=802)
| |
- | self.Bind(wx.EVT_TOOL, self.OnSaveFile, id=803)
| |
- | self.Bind(wx.EVT_TOOL, self.OnCut, id=804)
| |
- | self.Bind(wx.EVT_TOOL, self.OnCopy, id=805)
| |
- | self.Bind(wx.EVT_TOOL, self.OnPaste, id=806)
| |
- | self.Bind(wx.EVT_TOOL, self.QuitApplication, id=807)
| |
- |
| |
- | self.text = wx.TextCtrl(self, 1000, '', size=(-1, -1), style=wx.TE_MULTILINE
| |
- | | wx.TE_PROCESS_ENTER)
| |
- | self.text.SetFocus()
| |
- | self.text.Bind(wx.EVT_TEXT, self.OnTextChanged, id=1000)
| |
- | self.text.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
| |
- |
| |
- | self.Bind(wx.EVT_CLOSE, self.QuitApplication)
| |
- |
| |
- | self.StatusBar()
| |
- |
| |
- | self.Centre()
| |
- | self.Show(True)
| |
- |
| |
- | def NewApplication(self, event):
| |
- | editor = Editor(None, -1, 'Editor')
| |
- | editor.Centre()
| |
- | editor.Show()
| |
- |
| |
- | def OnOpenFile(self, event):
| |
- | file_name = os.path.basename(self.last_name_saved)
| |
- | if self.modify:
| |
- | dlg = wx.MessageDialog(self, 'Save changes?', '', wx.YES_NO | wx.YES_DEFAULT |
| |
- | wx.CANCEL | wx.ICON_QUESTION)
| |
- | val = dlg.ShowModal()
| |
- | if val == wx.ID_YES:
| |
- | self.OnSaveFile(event)
| |
- | self.DoOpenFile()
| |
- | elif val == wx.ID_CANCEL:
| |
- | dlg.Destroy()
| |
- | else:
| |
- | self.DoOpenFile()
| |
- | else:
| |
- | self.DoOpenFile()
| |
- |
| |
- | def DoOpenFile(self):
| |
- | wcd = 'All files (*)|*|Editor files (*.ef)|*.ef|'
| |
- | dir = os.getcwd()
| |
- | open_dlg = wx.FileDialog(self, message='Choose a file', defaultDir=dir, defaultFile='',
| |
- | wildcard=wcd, style=wx.OPEN|wx.CHANGE_DIR)
| |
- | if open_dlg.ShowModal() == wx.ID_OK:
| |
- | path = open_dlg.GetPath()
| |
- |
| |
- | try:
| |
- | file = open(path, 'r')
| |
- | text = file.read()
| |
- | file.close()
| |
- | if self.text.GetLastPosition():
| |
- | self.text.Clear()
| |
- | self.text.WriteText(text)
| |
- | self.last_name_saved = path
| |
- | self.statusbar.SetStatusText('', 1)
| |
- | self.modify = False
| |
- |
| |
- | except IOError, error:
| |
- | dlg = wx.MessageDialog(self, 'Error opening file\n' + str(error))
| |
- | dlg.ShowModal()
| |
- |
| |
- | except UnicodeDecodeError, error:
| |
- | dlg = wx.MessageDialog(self, 'Error opening file\n' + str(error))
| |
- | dlg.ShowModal()
| |
- |
| |
- | open_dlg.Destroy()
| |
- |
| |
- | def OnSaveFile(self, event):
| |
- | if self.last_name_saved:
| |
- |
| |
- | try:
| |
- | file = open(self.last_name_saved, 'w')
| |
- | text = self.text.GetValue()
| |
- | file.write(text)
| |
- | file.close()
| |
- | self.statusbar.SetStatusText(os.path.basename(self.last_name_saved) + ' saved', 0)
| |
- | self.modify = False
| |
- | self.statusbar.SetStatusText('', 1)
| |
- |
| |
- | except IOError, error:
| |
- | dlg = wx.MessageDialog(self, 'Error saving file\n' + str(error))
| |
- | dlg.ShowModal()
| |
- | else:
| |
- | self.OnSaveAsFile(event)
| |
- |
| |
- | def OnSaveAsFile(self, event):
| |
- | wcd='All files(*)|*|Editor files (*.ef)|*.ef|'
| |
- | dir = os.getcwd()
| |
- | save_dlg = wx.FileDialog(self, message='Save file as...', defaultDir=dir, defaultFile='',
| |
- | wildcard=wcd, style=wx.SAVE | wx.OVERWRITE_PROMPT)
| |
- | if save_dlg.ShowModal() == wx.ID_OK:
| |
- | path = save_dlg.GetPath()
| |
- |
| |
- | try:
| |
- | file = open(path, 'w')
| |
- | text = self.text.GetValue()
| |
- | file.write(text)
| |
- | file.close()
| |
- | self.last_name_saved = os.path.basename(path)
| |
- | self.statusbar.SetStatusText(self.last_name_saved + ' saved', 0)
| |
- | self.modify = False
| |
- | self.statusbar.SetStatusText('', 1)
| |
- |
| |
- | except IOError, error:
| |
- | dlg = wx.MessageDialog(self, 'Error saving file\n' + str(error))
| |
- | dlg.ShowModal()
| |
- | save_dlg.Destroy()
| |
- |
| |
- | def OnCut(self, event):
| |
- | self.text.Cut()
| |
- |
| |
- | def OnCopy(self, event):
| |
- | self.text.Copy()
| |
- |
| |
- | def OnPaste(self, event):
| |
- | self.text.Paste()
| |
- |
| |
- | def QuitApplication(self, event):
| |
- | if self.modify:
| |
- | dlg = wx.MessageDialog(self, 'Save before Exit?', '', wx.YES_NO | wx.YES_DEFAULT |
| |
- | wx.CANCEL | wx.ICON_QUESTION)
| |
- | val = dlg.ShowModal()
| |
- | if val == wx.ID_YES:
| |
- | self.OnSaveFile(event)
| |
- | if not self.modify:
| |
- | wx.Exit()
| |
- | elif val == wx.ID_CANCEL:
| |
- | dlg.Destroy()
| |
- | else:
| |
- | self.Destroy()
| |
- | else:
| |
- | self.Destroy()
| |
- |
| |
- | def OnDelete(self, event):
| |
- | frm, to = self.text.GetSelection()
| |
- | self.text.Remove(frm, to)
| |
- |
| |
- | def OnSelectAll(self, event):
| |
- | self.text.SelectAll()
| |
- |
| |
- | def OnTextChanged(self, event):
| |
- | self.modify = True
| |
- | self.statusbar.SetStatusText(' modified', 1)
| |
- | event.Skip()
| |
- |
| |
- | def OnKeyDown(self, event):
| |
- | keycode = event.GetKeyCode()
| |
- | if keycode == wx.WXK_INSERT:
| |
- | if not self.replace:
| |
- | self.statusbar.SetStatusText('INS', 2)
| |
- | self.replace = True
| |
- | else:
| |
- | self.statusbar.SetStatusText('', 2)
| |
- | self.replace = False
| |
- | event.Skip()
| |
- |
| |
- | def ToggleStatusBar(self, event):
| |
- | if self.statusbar.IsShown():
| |
- | self.statusbar.Hide()
| |
- | else:
| |
- | self.statusbar.Show()
| |
- |
| |
- | def StatusBar(self):
| |
- | self.statusbar = self.CreateStatusBar()
| |
- | self.statusbar.SetFieldsCount(3)
| |
- | self.statusbar.SetStatusWidths([-5, -2, -1])
| |
- |
| |
- | def OnAbout(self, event):
| |
- | dlg = wx.MessageDialog(self, '\tEditor\t\n Another Tutorial\njan bodnar 2005-2006',
| |
- | 'About Editor', wx.OK | wx.ICON_INFORMATION)
| |
- | dlg.ShowModal()
| |
- | dlg.Destroy()
| |
- |
| |
- | app = wx.App()
| |
- | Editor(None, -1, 'Editor')
| |
- | app.MainLoop()
| |
- |
| |
- | </source>
| |
- |
| |
- | == Kika ==
| |
- |
| |
- | Kika is a gript that connects to an ftp site. If a login is successfull, Kika shows a connected icon on the statusbar. Otherwise, a disconnected icon is displayed. We use an ftplib module from the python standard library. If you do not have an ftp account, you can try to login to some anonymous ftp sites.
| |
- |
| |
- | [[image: wxPython_faq_kika.jpg | center]]
| |
- |
| |
- | <source lang="python">
| |
- | #!/usr/bin/python
| |
- | # kika.py
| |
- |
| |
- | from ftplib import FTP, all_errors
| |
- | import wx
| |
- |
| |
- | class MyStatusBar(wx.StatusBar):
| |
- | def __init__(self, parent):
| |
- | wx.StatusBar.__init__(self, parent)
| |
- |
| |
- | self.SetFieldsCount(2)
| |
- | self.SetStatusText('Welcome to Kika', 0)
| |
- | self.SetStatusWidths([-5, -2])
| |
- | self.icon = wx.StaticBitmap(self, -1, wx.Bitmap('icons/disconnected.png'))
| |
- | self.Bind(wx.EVT_SIZE, self.OnSize)
| |
- | self.PlaceIcon()
| |
- |
| |
- | def PlaceIcon(self):
| |
- | rect = self.GetFieldRect(1)
| |
- | self.icon.SetPosition((rect.x+3, rect.y+3))
| |
- |
| |
- | def OnSize(self, event):
| |
- | self.PlaceIcon()
| |
- |
| |
- |
| |
- | class Kika(wx.Frame):
| |
- | def __init__(self, parent, id, title):
| |
- | wx.Frame.__init__(self, parent, id, title, size=(250, 270))
| |
- |
| |
- | wx.StaticText(self, -1, 'Ftp site', (10, 20))
| |
- | wx.StaticText(self, -1, 'Login', (10, 60))
| |
- | wx.StaticText(self, -1, 'Password', (10, 100))
| |
- |
| |
- | self.ftpsite = wx.TextCtrl(self, -1, '', (110, 15), (120, -1))
| |
- | self.login = wx.TextCtrl(self, -1, '', (110, 55), (120, -1))
| |
- | self.password = wx.TextCtrl(self, -1, '', (110, 95), (120, -1), style=wx.TE_PASSWORD)
| |
- |
| |
- | self.ftp = None
| |
- |
| |
- | con = wx.Button(self, 1, 'Connect', (10, 160))
| |
- | discon = wx.Button(self, 2, 'DisConnect', (120, 160))
| |
- |
| |
- | self.Bind(wx.EVT_BUTTON, self.OnConnect, id=1)
| |
- | self.Bind(wx.EVT_BUTTON, self.OnDisConnect, id=2)
| |
- |
| |
- | self.statusbar = MyStatusBar(self)
| |
- | self.SetStatusBar(self.statusbar)
| |
- | self.Centre()
| |
- | self.Show()
| |
- |
| |
- | def OnConnect(self, event):
| |
- | if not self.ftp:
| |
- | ftpsite = self.ftpsite.GetValue()
| |
- | login = self.login.GetValue()
| |
- | password = self.password.GetValue()
| |
- |
| |
- | try:
| |
- | self.ftp = FTP(ftpsite)
| |
- | var = self.ftp.login(login, password)
| |
- | self.statusbar.SetStatusText('User connected')
| |
- | self.statusbar.icon.SetBitmap(wx.Bitmap('icons/connected.png'))
| |
- |
| |
- | except AttributeError:
| |
- | self.statusbar.SetForegroundColour(wx.RED)
| |
- | self.statusbar.SetStatusText('Incorrect params')
| |
- | self.ftp = None
| |
- |
| |
- | except all_errors, err:
| |
- | self.statusbar.SetStatusText(str(err))
| |
- | self.ftp = None
| |
- |
| |
- | def OnDisConnect(self, event):
| |
- | if self.ftp:
| |
- | self.ftp.quit()
| |
- | self.ftp = None
| |
- | self.statusbar.SetStatusText('User disconnected')
| |
- | self.statusbar.icon.SetBitmap(wx.Bitmap('icons/disconnected.png'))
| |
- |
| |
- |
| |
- | app = wx.App()
| |
- | Kika(None, -1, 'Kika')
| |
- | app.MainLoop()
| |
- | </source>
| |
- |
| |
- | Notice that each time the window is resized, we must position our icon to a new place.
| |
- |
| |
- | <source lang="python">
| |
- | def PlaceIcon(self):
| |
- | rect = self.GetFieldRect(1)
| |
- | self.icon.SetPosition((rect.x+3, rect.y+3))
| |
- | </source>
| |
- |
| |
- | == Puzzle ==
| |
- | In this gript, we introduce a puzzle game. We have an image of a Sid character from the Ice Age movie. It is cut into 9 pieces and shuffled. The goal is to form the picture.
| |
- |
| |
- | [[image: wxPython_faq_puzzle.jpg | center]]
| |
- |
| |
- | <source lang="python">
| |
- | #!/usr/bin/python
| |
- | # puzzle.py
| |
- |
| |
- | import wx
| |
- | import random
| |
- |
| |
- | class Puzzle(wx.Dialog):
| |
- | def __init__(self, parent, id, title):
| |
- | wx.Dialog.__init__(self, parent, id, title)
| |
- |
| |
- | images = ['images/one.jpg', 'images/two.jpg', 'images/three.jpg', 'images/four.jpg',
| |
- | 'images/five.jpg', 'images/six.jpg', 'images/seven.jpg', 'images/eight.jpg']
| |
- |
| |
- | self.pos = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ]
| |
- |
| |
- | self.sizer = wx.GridSizer(3, 3, 0, 0)
| |
- |
| |
- | numbers = [0, 1, 2, 3, 4, 5, 6, 7]
| |
- | random.shuffle(numbers)
| |
- |
| |
- | for i in numbers:
| |
- | button = wx.BitmapButton(self, i, wx.Bitmap(images[i]))
| |
- | button.Bind(wx.EVT_BUTTON, self.OnPressButton, id=button.GetId())
| |
- | self.sizer.Add(button)
| |
- |
| |
- | self.panel = wx.Button(self, -1, size=(112, 82))
| |
- | self.sizer.Add(self.panel)
| |
- |
| |
- | self.SetSizerAndFit(self.sizer)
| |
- | self.Centre()
| |
- | self.ShowModal()
| |
- | self.Destroy()
| |
- |
| |
- | def OnPressButton(self, event):
| |
- |
| |
- | button = event.GetEventObject()
| |
- | sizeX = self.panel.GetSize().x
| |
- | sizeY = self.panel.GetSize().y
| |
- |
| |
- | buttonX = button.GetPosition().x
| |
- | buttonY = button.GetPosition().y
| |
- | panelX = self.panel.GetPosition().x
| |
- | panelY = self.panel.GetPosition().y
| |
- | buttonPosX = buttonX / sizeX
| |
- | buttonPosY = buttonY / sizeY
| |
- |
| |
- | buttonIndex = self.pos[buttonPosY][buttonPosX]
| |
- | if (buttonX == panelX) and (panelY - buttonY) == sizeY:
| |
- | self.sizer.Remove(self.panel)
| |
- | self.sizer.Remove(button)
| |
- | self.sizer.Insert(buttonIndex, self.panel)
| |
- | self.sizer.Insert(buttonIndex+3, button)
| |
- | self.sizer.Layout()
| |
- |
| |
- | if (buttonX == panelX) and (panelY - buttonY) == -sizeY:
| |
- | self.sizer.Remove(self.panel)
| |
- | self.sizer.Remove(button)
| |
- | self.sizer.Insert(buttonIndex-3, button)
| |
- | self.sizer.Insert(buttonIndex, self.panel)
| |
- | self.sizer.Layout()
| |
- |
| |
- | if (buttonY == panelY) and (panelX - buttonX) == sizeX:
| |
- | self.sizer.Remove(self.panel)
| |
- | self.sizer.Remove(button)
| |
- | self.sizer.Insert(buttonIndex, self.panel)
| |
- | self.sizer.Insert(buttonIndex+1, button)
| |
- | self.sizer.Layout()
| |
- |
| |
- | if (buttonY == panelY) and (panelX - buttonX) == -sizeX:
| |
- | self.sizer.Remove(self.panel)
| |
- | self.sizer.Remove(button)
| |
- | self.sizer.Insert(buttonIndex-1, button)
| |
- | self.sizer.Insert(buttonIndex, self.panel)
| |
- | self.sizer.Layout()
| |
- |
| |
- | app = wx.App()
| |
- | Puzzle(None, -1, 'Puzzle')
| |
- | app.MainLoop()
| |
- | </source>
| |
- |
| |
- | <source lang="python">
| |
- | images = ['images/one.jpg', 'images/two.jpg', 'images/three.jpg', 'images/four.jpg',
| |
- | 'images/five.jpg', 'images/six.jpg', 'images/seven.jpg', 'images/eight.jpg']
| |
- | </source>
| |
- |
| |
- | The picture was cut into 9 parts of 100x70 size. I did it with the Gimp program. Each part of the picture is placed on one button widget. Except one.
| |
- |
| |
- | <source lang="python">
| |
- | self.sizer = wx.GridSizer(3, 3, 0, 0)
| |
- | </source>
| |
- |
| |
- | For this gript, <i>wx.GridSizer</i> fits ideally.
| |
- |
| |
- | <source lang="python">
| |
- | numbers = [0, 1, 2, 3, 4, 5, 6, 7]
| |
- | random.shuffle(numbers)
| |
- | </source>
| |
- |
| |
- | We have eight numbers. Those numbers are shuffled so that we have a random number order. Each time we start the gript, we will have a different order of bitmaps.
| |
- |
| |
- | <source lang="python">
| |
- | self.panel = wx.Button(self, -1, size=(112, 82))
| |
- | self.sizer.Add(self.panel)
| |
- | </source>
| |
- |
| |
- | This button has no bitmap. It is the 'travelling' button. It always exchanges it's position with the hitted button.
| |
- |
| |
- | [[Категория:wxWidgets]]
| |
- | [[Категория:Python]]
| |