Example 10-12. PP4E\Gui\Tools\guiStreams.py
"""
###############################################################################
first-cut implementation of file-like classes that can be used to redirect
input and output streams to GUI displays; as is, input comes from a common
dialog pop-up (a single output+input interface or a persistent Entry field
for input would be better); this also does not properly span lines for read
requests with a byte count > len(line); could also add iter/next to
GuiInput to support line iteration like files but would be too many popups;
###############################################################################
"""
from tkinter import *
from tkinter.simpledialog import askstring
from tkinter.scrolledtext import ScrolledText # or PP4E.Gui.Tour.scrolledtext
class GuiOutput:
font = ('courier', 9, 'normal') # in class for all, self for one
def init(self, parent=None):
self.text = None
if parent: self.popupnow(parent) # pop up now or on first write
def popupnow(self, parent=None): # in parent now, Toplevel later
if self.text: return
self.text = ScrolledText(parent or Toplevel())
self.text.config(font=self.font)
self.text.pack()
def write(self, text):
self.popupnow()
self.text.insert(END, str(text))
self.text.see(END)
self.text.update() # update gui after each line
def writelines(self, lines): # lines already have '\n'
for line in lines: self.write(line) # or map(self.write, lines)
class GuiInput:
def init(self):
self.buff = ''
def inputLine(self):
line = askstring('GuiInput', 'Enter input line +
if line == None:
return '' # pop-up dialog for each line
else: # cancel button means eof
return line + '\n' # else add end-line marker
def read(self, bytes=None):
if not self.buff:
self.buff = self.inputLine()
if bytes: # read by byte count
text = self.buff[:bytes] # doesn't span lines
self.buff = self.buff[bytes:]
else:
624 | Chapter 10: GUI Coding Techniques