This wiki is in the process of being archived due to lack of usage and the resources necessary to serve it — predominately to bots, crawlers, and LLM companies. Edits are discouraged.
Pages are preserved as they were at the time of archival. For current information, please visit python.org.
If a change to this archive is absolutely needed, requests can be made via the infrastructure@python.org mailing list.

"Simple" Stage 4

The program has now progressed and the GUI begins to look like GUIs usually look. Visually, the most noticeable change is the presence of several icons on the tool bar - basically, these icons have the same functionality as the menu items and are provided for the most frequently used operations. So we will need to talk some more about the actions and about generation and storage of resources. Once you download the program listing and start using it, other changes will be noticed: at the end of the mouse pointer, a tool tip hint pops up showing the purpose of the icon that the pointer is hovering over. Also, an informative note, often the same as the tool tip hint, is shown on the status bar.

In connection with the above, we will need to discuss how icon images are provided for icons.

One item that I missed in earlier versions is showing of the title of document opened in the edit window. The title is functional and it shows when the document has been altered. Not only that, there is a program bug that PyQt (or Qt) reports. I found the chasing after this bug as frustrating as it was instructive. It was not easy to find, yet I think that a programmer with experience in PyQt would spot it in no time at all! See if you can spot it easily.

Simple0.0.06.png

Below is the code listing for this stage of development. It is very often difficult to copy the code from a wiki. This is particularly so with Python programs, because Python relies on indentation for specification of code blocks (and it is such a nice feature, once you get used to it!). To make it simpler to test this stage of program, we provide a tar ball of program for downloading: see http://akabaila.pcug.org.au/data_sample and select the tar ball named simple0.0.06.tar.gz.

 1 #!/usr/bin/env python
 2 # .../simple.py - developing of a simple text editor.
 3 '''A really simple editor program in PyQt4 - simple.py
 4 '''
 5 
 6 import sys
 7 import os
 8 
 9 from PyQt4.QtGui import (QMainWindow, QApplication, QFileDialog,
 10  QKeySequence, QAction, QIcon)
 11 from PyQt4.QtCore import SIGNAL
 12 
 13 from ui_simple import Ui_MainWindow
 14 import qrc_simple
 15 
 16 __version__ = "0.0.06"
 17 
 18 class MainWindow(QMainWindow, Ui_MainWindow):
 19  def __init__(self, parent=None):
 20  super(MainWindow, self).__init__(parent)
 21  self.setupUi(self) 
 22  self.action_New = self.editAction(self.action_New, self.fileNew,
 23  QKeySequence.New, "filenew", 
 24  'Clear the textEdit window for a new file.')
 25  self.action_Open = self.editAction(self.action_Open, self.fileOpen, 
 26  QKeySequence.Open, "fileopen", "Open an existing file")
 27  self.action_Save = self.editAction(self.action_Save, self.fileSave, 
 28  QKeySequence.Save, "filesave", "Save file")
 29  self.actionSave_As = self.editAction(self.actionSave_As, self.fileSaveAs, 
 30  "Ctrl+A", "filesaveas", "Save file with a new name")
 31  self.fileName = None
 32 #-------------------------------------------------------------------------------------
 33  fileToolbar = self.addToolBar("File")
 34  self.addActions(fileToolbar, (self.action_New, self.action_Open,
 35  self.action_Save, self.actionSave_As))
 36 #-------------------------------------------------------------------------------------- 
 37  self.resize(600, 400)
 38  self.dirty = False
 39  self.textEdit.textChanged.connect(self.setDirty)
 40 #--------------------------------------------------------------------------------------
 41  def setDirty(self):
 42  '''On change of text in textEdit window, set the flag
 43  "dirty" to True'''
 44  if self.dirty:
 45  return True 
 46  self.dirty = True
 47  self.updateStatus('self.dirty set to True')
 48  
 49  def clearDirty(self):
 50  '''Clear the dirty flag and update status'''
 51  self.dirty = False
 52 
 53  def updateStatus(self, message):
 54  if self.fileName is not None:
 55  flbase = os.path.basename(self.fileName)
 56  self.setWindowTitle(unicode("Simple Editor - " + flbase + "[*]") )
 57  self.statusBar().showMessage(message, 3000)
 58  self.setWindowModified(self.dirty)
 59  
 60  def okToContinue(self):
 61  if self.dirty:
 62  reply = QMessageBox.question(self,
 63  "Simple Editor - Unsaved Changes",
 64  "Save unsaved changes?",
 65  QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
 66  if reply == QMessageBox.Cancel:
 67  return False
 68  elif reply == QMessageBox.Yes:
 69  return self.fileSave()
 70  return True
 71  
 72  def addActions(self, target, actions):
 73  for action in actions:
 74  if action is None:
 75  target.addSeparator()
 76  else:
 77  target.addAction(action)
 78 
 79  def editAction(self, action, slot=None, shortcut=None, icon=None,
 80  tip=None, checkable=False, signal="triggered()"):
 81  if icon is not None:
 82  action.setIcon(QIcon(":/{0}.png".format(icon)))
 83  if shortcut is not None:
 84  action.setShortcut(shortcut)
 85  if tip is not None:
 86  action.setToolTip(tip)
 87  action.setStatusTip(tip)
 88  if slot is not None:
 89 # self.connect(action, SIGNAL(signal), slot) 
 90  action.triggered.connect(slot) 
 91  if checkable:
 92  action.setCheckable(True)
 93  return action
 94 
 95  def fileNew(self):
 96  '''Clear the editor window for a new file with name
 97  specified in fileSaveAs method.'''
 98  self.textEdit.setText('')
 99  self.statusBar().showMessage('File menu: New selected', 8000)
 100 
 101  def fileOpen(self):
 102  '''Open file'''
 103  fname = unicode(QFileDialog.getOpenFileName(self,
 104  "Open File", '.', "Files (*.*)"))
 105  if not (fname == ""):
 106  self.textEdit.setText(open(fname).read())
 107  self.fileName = fname
 108  else:
 109  return
 110  self.clearDirty()
 111  self.updateStatus('File opened.')
 112  
 113  def fileSave(self):
 114  if self.fileName is None:
 115  return self.fileSaveAs()
 116  else:
 117  fname = self.fileName
 118  fl = open(fname, 'w')
 119  tempText = self.textEdit.toPlainText()
 120  if tempText: 
 121  fl.write(tempText)
 122  fl.close()
 123  self.clearDirty()
 124  self.updateStatus('Saved file') 
 125  return True
 126  else:
 127  self.statusBar().showMessage('Failed to save ...', 5000)
 128  return False
 129  
 130  def fileSaveAs(self):
 131  path = self.fileName if self.fileName is not None else "."
 132  fname = unicode(QFileDialog.getSaveFileName(self,
 133  "Simple Editor, SaveAs ", path, "Any File (*.*)"))
 134  if fname:
 135  if "." not in fname:
 136  fname += ".txt"
 137  self.fileName = fname
 138  self.fileSave() 
 139  self.statusBar().showMessage('SaveAs file' + fname, 8000)
 140  self.clearDirty()
 141  
 142 if __name__ == '__main__':
 143  app = QApplication(sys.argv)
 144  frame = MainWindow()
 145  frame.show()
 146  app.exec_()

The listing is more extensive - the number of lines has about doubled from the previous section. On the other hand, the simple editor now looks like a "real" program and is able to do what we expect of a simple, tutorial type, plain text editor!

Return Home


2026年02月14日 16:12

AltStyle によって変換されたページ (->オリジナル) /