Исходный программный код PyView

ishodnyj programmnyj kod pyview Примеры законченных программ с графическим интерфейсом

Поскольку программа PyView разрабатывалась поэтапно, вам придется изучить объединение двух файлов и классов, чтобы понять, как она в действительности работает. В одном файле реализован класс, предоставляющий основные функции показа слайдов, а в другом реализован класс, расширяющий исходный и добавляющий новые функции поверх базового поведения. Начнем с класса расширения: пример 11.6 добавляет ряд функций в импортируемый базовый класс показа слайдов — редактирование примечаний, ползунок, определяющий задержку, метку для отображения имени файла и так далее. Это тот файл, который фактически запускает PyView.

Пример 11.6. PP4E\Gui\SlideShow\slideShowPlus.py

############################################################################# PyView 1.2: программа показа слайдов с прилагаемыми к ним примечаниями.

Подкласс класса SlideShow, который добавляет отображение содержимого файлов с примечаниями в прикрепляемом объекте PyEdit, ползунок для установки интервала задержки между сменами изображений и метку с именем текущего отображаемого файла изображения;

Версия 1.2 работает под управлением Python 3.x и дополнительно использует улучшенный алгоритм повторного прикрепления компонента PyEdit, чтобы обеспечить его растягиваемость, перехватывает операцию закрытия примечания в подклассе, чтобы избежать появления исключения при закрытии PyEdit, использующегося в режиме всплывающего окна или полнофункционального компонента, и вызывает метод update() перед вставкой текста во вновь прикрепленный редактор примечаний, чтобы обеспечить правильное позиционирование в первой строке (смотрите описание этой проблемы в книге).

#############################################################################

import os

from tkinter import *

from PP4E.Gui.TextEditor.textEditor import *

from slideShow import SlideShow

#from slideShow_threads import SlideShow

Size = (300, 550) # 1.2: начальные размеры, (высота, ширина)

class SlideShowPlus(SlideShow):

def __init__(self, parent, picdir, editclass, msecs=2000, size=Size) self.msecs = msecs

self.editclass = editclass

SlideShow.__init__(self, parent, picdir, msecs, size)

def makeWidgets(self):

self.name = Label(self, text=’None’, bg=’red’, relief=RIDGE)

self.name.pack(fill=X)

SlideShow.makeWidgets(self)

Button(self, text=’Note’, command=self.onNote).pack(fill=X) Button(self, text=’Help’, command=self.onHelp).pack(fill=X) s = Scale(label=’Speed: msec delay’, command=self.onScale, from_=0, to=3000, resolution=50, showvalue=YES, length=400, tickinterval=250, orient=’horizontal’)

s.pack(side=BOTTOM, fill=X)

s.set(self.msecs)

#   1.2: знать о закрытии редактора необходимо, если он используется

#   в режиме всплывающего окна или полнофункционального компонента self.editorGone = False

class WrapEditor(self.editclass):# расширяет PyEdit для перехвата Quit def onQuit(editor): # editor — экземпляр PyEdit

self.editorGone = True # self — вмещающий экземпляр self.editorUp = False # класса слайдшоу self.editclass.onQuit(editor) # предотвратить рекурсию

#   прикрепить фрейм редактора к окну или к фрейму слайд-шоу

if issubclass(WrapEditor, TextEditorMain): # создать объект редактора self.editor = WrapEditor(self.master) # указать корень для меню else: # встраиваемый компонент

self.editor = WrapEditor(self) # или компонент всплывающего окна self.editor.pack_forget() # скрыть редактор при запуске

self.editorUp = self.image = None

def onStart(self):

SlideShow.onStart(self)

self.config(cursor=’watch’)

def onStop(self):

SlideShow.onStop(self)

self.config(cursor=’hand2’)

def onOpen(self):

SlideShow.onOpen(self)

if self.image:

self.name.config(text=os.path.split(self.image[0])[1]) self.config(cursor=’crosshair’)

self.switchNote()

def quit(self):

self.saveNote()

SlideShow.quit(self)

def drawNext(self):

SlideShow.drawNext(self)

if self.image:

self.name.config(text=os.path.split(self.image[0])[1]) self.loadNote()

def onScale(self, value): self.msecs = int(value)

def onNote(self):

if self.editorGone: # 1.2: был уничтожен

return # не воссоздавать: видимо, он был нежелателен

if self.editorUp:

#self.saveNote() # если редактор уже открыт

self.editor.pack_forget() # сохранить текст?, скрыть редактор

self.editorUp = False

else:

#   1.2: повторно прикрепить с параметрами, управляющими

#   растягиванием, иначе виджет редактора не будет

#   растягиваться

#   1.2: вызвать update после прикрепления и перед вставкой текста,

#   иначе текстовый курсор будет изначально помещен во 2 строку

self.editor.pack(side=TOP, expand=YES, fill=BOTH)

self.editorUp = True # или показать/прикрепить редактор self.update() # смотрите Pyedit: та же проблема с loadFirst

self.loadNote() # и загрузить текст примечания

def switchNote(self):

if self.editorUp:

self.saveNote() # сохранить примечание к текущему изображению

self.loadNote() # загрузить примечание для нового изображения

def saveNote(self):

if self.editorUp:

currfile = self.editor.getFileName() # или self.editor.onSave() currtext = self.editor.getAllText() # текст может отсутствовать if currfile and currtext:

try:

open(currfile, ‘w’).write(currtext) except:

pass # неудача является нормальным явлением при # выполнении за пределами текущего каталога

def loadNote(self):

if self.image and self.editorUp:

root, ext = os.path.splitext(self.image[0])

notefile = root + ‘.note’

self.editor.setFileName(notefile)

try:

self.editor.setAllText(open(notefile).read())

except:

self.editor.clearAllText() # примечание может отсутствовать

def onHelp(self):

showinfo(‘About PyView’,

‘PyView version 1.2\nMay, 2010\n(1.1 July, 1999)\n’

‘An image slide show\nProgramming Python 4E’) if __name__ == ‘__main__’: import sys picdir = ‘../gifs’ if len(sys.argv) >= 2: picdir = sys.argv[1]

editstyle = TextEditorComponentMinimal if len(sys.argv) == 3:

try:

editstyle = [TextEditorMain,

TextEditorMainPopup, TextEditorComponent, TextEditorComponentMinimal][int(sys.argv[2])] except: pass

root = Tk()

root.title(‘PyView 1.2 — plus text notes’)

Label(root, text=”Slide show subclass”).pack()

SlideShowPlus(parent=root, picdir=picdir, editclass=editstyle) root.mainloop()

Базовая функциональность, расширяемая классом SlideShowPlus, приводится в примере 11.7. Этот пример представляет первоначальную реализацию показа слайдов — он открывает файлы изображений, отображает их и организует показ слайдов в цикле. Его можно запустить как самостоятельный сценарий, но при этом вы не получите дополнительных функций, таких как примечания и ползунки, добавляемые подклассом SlideShowPlus.

Пример 11.7. PP4E\Gui\SlideShow\slideShow.py

######################################################################

SlideShow: простая реализация показа слайдов на Python/tkinter;

базовый набор функций, реализованных здесь, можно расширять в подклассах;

######################################################################

from tkinter import *

from glob import glob

from tkinter.messagebox import askyesno

from tkinter.filedialog import askopenfilename

import random

Size = (450, 450) # начальная высота и ширина холста

imageTypes = [(‘Gif files’, ‘.gif’), # для диалога открытия файла (‘Ppm files’, ‘.ppm’), # плюс jpg с исправлениями Tk, (‘Pgm files’, ‘.pgm’), # плюс растровые с помощью BitmapImage (‘All files’, ‘*’)]

class SlideShow(Frame):

def __init__(self, parent=None, picdir=’.’, msecs=3000, size=Size,**args) Frame.__init__(self, parent, **args) self.size = size self.makeWidgets() self.pack(expand=YES, fill=BOTH) self.opens = picdir files = []

for label, ext in imageTypes[:-1]:

files = files + glob(‘%s/*%s’ % (picdir, ext)) self.images = [(x, PhotoImage(file=x)) for x in files] self.msecs = msecs self.beep = True self.drawn = None

def makeWidgets(self): height, width = self.size self.canvas = Canvas(self, bg=’white’, height=height, width=width) self.canvas.pack(side=LEFT, fill=BOTH, expand=YES) self.onoff = Button(self, text=’Start’, command=self.onStart) self.onoff.pack(fill=X) Button(self, text=’Open’, command=self.onOpen).pack(fill=X) Button(self, text=’Beep’, command=self.onBeep).pack(fill=X) Button(self, text=’Quit’, command=self.onQuit).pack(fill=X)

def onStart(self): self.loop = True self.onoff.config(text=’Stop’, command=self.onStop) self.canvas.config(height=self.size[0], width=self.size[1]) self.onTimer()

def onStop(self): self.loop = False self.onoff.config(text=’Start’, command=self.onStart)

def onOpen(self): self.onStop() name = askopenfilename(initialdir=self.opens, filetypes=imageTypes) if name:

if self.drawn: self.canvas.delete(self.drawn) img = PhotoImage(file=name) self.canvas.config(height=img.height(), width=img.width()) self.drawn = self.canvas.create_image(2, 2, image=img, anchor=NW) self.image = name, img

def onQuit(self): self.onStop() self.update() if askyesno(‘PyView’, ‘Really quit now?’): self.quit()

def onBeep(self):

self.beep = not self.beep # toggle, or use ~ 1

def onTimer(self): if self.loop:

self.drawNext()

self.after(self.msecs, self.onTimer)

def drawNext(self):

if self.drawn: self.canvas.delete(self.drawn)

name, img = random.choice(self.images)

self.drawn = self.canvas.create_image(2, 2, image=img, anchor=NW) self.image = name, img if self.beep: self.bell() self.canvas.update()

if __name__ == ‘__main__’: import sys

if len(sys.argv) == 2:

picdir = sys.argv[1]

else:

picdir = ‘../gifs’

root = Tk()

root.title(‘PyView 1.2’)

root.iconname(‘PyView’)

Label(root, text=”Python Slide Show Viewer”).pack() SlideShow(root, picdir=picdir, bd=3, relief=SUNKEN) root.mainloop()

Чтобы вы могли получить более полное представление о том, что реализует этот базовый класс, на рис. 11.16 показано, как выглядит графический интерфейс, создаваемый этим примером, если запустить его в виде самостоятельного сценария. Здесь изображены два экземпляра, создаваемые сценарием slideShow_frames, который можно найти в дереве примеров и основная реализация которого приводится ниже:

root = Tk()

Label(root, text=”Two embedded slide shows: Frames”).pack()

SlideShow(parent=root, picdir=picdir, bd=3, relief=SUNKEN).pack(side=LEFT) SlideShow(parent=root, picdir=picdir, bd=3, relief=SUNKEN).pack(side=RIGHT) root.mainloop()

Простой сценарий slideShow_frames прикрепляет два экземпляра SlideShow к одному окну. Это возможно благодаря тому, что информация о состоянии сохраняется не в глобальных переменных, а в переменных экземпляра класса. Сценарий slideShow_toplevels (также можно найти в дереве примеров) прикрепляет два экземпляра SlideShow к двум всплывающим окнам верхнего уровня. В обоих случаях показ слайдов происходит независимо, но управляется событиями after, генерируемыми одним и тем же циклом событий в одном процессе.

Рис. 11.16. Два прикрепленных объекта SlideShow

 

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий