[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

sys.exit. Since doesn’t allow GUI operations anyhow, this change is un-
warranted. Code after mainloop won’t help here either, because mainloop is called out-
side PyEdit’s code, and this is far too late to detect text changes and save in any event
(pun nearly accidental).


In other words, won’t help—it doesn’t support the goal of verifying saves on
window closes, and it doesn’t address the issue of quit and destroy calls run for widgets
outside the scope of PyEdit window classes. Because of such complications, PyEdit
instead relies on checking for changes in each individual window before closed, and
for changes in its cross-process window list before quits in any of its main windows.
Applications that follow its expected window model check for changes automatically.
Applications that embed a PyEdit as a component of a larger GUI, or use it in other
ways that are outside PyEdit’s control, are responsible for testing for edit changes on
closes if they should be saved, before the PyEdit object or its widgets are destroyed.


To experiment with the event’s behavior yourself, see file destroyer.py in the
book examples package; it simulates what PyEdit would need to do on . Here
is the crucial subset of its code, with comments that explain behavior:


def onDeleteRequest():
print('Got wm delete') # on window X: can cancel destroy
root.destroy() # triggers <Destroy>

def doRootDestroy(event):
print('Got event <destroy>') # called for each widget in root
if event.widget == text:
print('for text')
print(text.edit_modified()) # <= Tcl error: invalid widget
ans = askyesno('Save stuff?', 'Save?') # <= may behave badly
if ans: print(text.get('1.0', END+'-1c')) # <= Tcl error: invalid widget

root = Tk()
text = Text(root, undo=1, autoseparators=1)
text.pack()
root.bind('<Destroy>', doRootDestroy) # for root and children
root.protocol('WM_DELETE_WINDOW', onDeleteRequest) # on window X button

Button(root, text='Destroy', command=root.destroy).pack() # triggers <Destroy>
Button(root, text='Quit', command=root.quit).pack() # <= fatal Python error,
mainloop() # no <Destroy> on quit()

See the code listings in the next section for more on all of the above. Also be sure to see
the mail file’s documentation string for a list of suggested enhancements and open
issues (noted under “TBD”). PyEdit is largely designed to work according to my pref-
erences, but it’s open to customization for yours.


PyEdit Source Code


The PyEdit program consists of only a small configuration module and one main source
file, which is just over 1,000 lines long—a .py that can be either run or imported. For


PyEdit: A Text Editor Program/Object | 693
Free download pdf