|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 一个账号 于 2020-3-7 13:37 编辑
ProgressBar.py"""
A basic widget for showing the progress
being made in a task.
"""
from tkinter import *
class ProgressBar:
def __init__(self, master=None, orientation="horizontal",
min=0, max=100, width=100, height=18,
doLabel=1, appearance="sunken",
fillColor="blue", background="gray",
labelColor="yellow", labelFont="Verdana",
labelText="", labelFormat="%d%%",
value=50, bd=2):
# preserve various values
self.master = master
self.orientation = orientation
self.min = min
self.max = max
self.width = width
self.height = height
self.doLabel = doLabel
self.fillColor = fillColor
self.labelFont = labelFont
self.labelColor = labelColor
self.background = background
self.labelText = labelText
self.labelFormat = labelFormat
self.value = value
self.frame = Frame(master, relief=appearance, bd=bd)
self.canvas = Canvas(self.frame, height=height, width=width, bd=0,
highlightthickness=0, background=background)
self.scale = self.canvas.create_rectangle(0, 0, width, height,
fill=fillColor)
self.label = self.canvas.create_text(self.canvas.winfo_reqwidth() / 2,
height / 2, text=labelText,
anchor="c", fill=labelColor,
font=self.labelFont)
self.update()
self.canvas.pack(side='top', fill='x', expand='no')
def updateProgress(self, newValue, newMax=None):
if newMax:
self.max = newMax
self.value = newValue
self.update()
def update(self):
# Trim the values to be between min and max
value = self.value
if value > self.max:
value = self.max
if value < self.min:
value = self.min
# Adjust the rectangle
if self.orientation == "horizontal":
self.canvas.coords(self.scale, 0, 0,
float(value) / self.max * self.width, self.height)
else:
self.canvas.coords(self.scale, 0,
self.height - (float(value) / self.max * self.height),
self.width, self.height)
# Now update the colors
self.canvas.itemconfig(self.scale, fill=self.fillColor)
self.canvas.itemconfig(self.label, fill=self.labelColor)
# And update the label
if self.doLabel:
if value:
if value >= 0:
pvalue = int((float(value) / float(self.max)) * 100.0)
else:
value = 0
self.canvas.itemconfig(self.label, text=self.labelFormat % value)
else:
self.canvas.itemconfig(self.label, text='')
else:
self.canvas.itemconfig(self.label, text=self.labelFormat % self.labelText)
self.canvas.update_idletasks()
AppShell.py
#! /usr/env/python
"""
AppShell provides a GUI application framework.
This is a streamlined adaptation of GuiAppD.py, originally
created by Doug Hellmann (doughellmann@mindspring.com).
"""
from tkinter import *
import Pmw
import sys, string
import ProgressBar
class AppShell(Pmw.MegaWidget):
appversion = '1.0'
appname = 'Generic Application Frame'
copyright = 'Copyright YYYY Your Company. All Rights Reserved'
contactname = 'Your Name'
contactphone = '(999) 555-1212'
contactemail = 'youremail@host.com'
frameWidth = 450
frameHeight = 320
padx = 5
pady = 5
usecommandarea = 0
balloonhelp = 1
busyCursor = 'watch'
def __init__(self, **kw):
optiondefs = (
('padx', 1, Pmw.INITOPT),
('pady', 1, Pmw.INITOPT),
('framewidth', 1, Pmw.INITOPT),
('frameheight', 1, Pmw.INITOPT),
('usecommandarea', self.usecommandarea, Pmw.INITOPT))
self.defineoptions(kw, optiondefs)
self.root = Tk()
self.initializeTk(self.root)
Pmw.initialise(self.root)
self.root.title(self.appname)
self.root.geometry('%dx%d' % (self.frameWidth, self.frameHeight))
# Initialize the base class
Pmw.MegaWidget.__init__(self, parent=self.root)
# initialize the application
self.appInit()
# create the interface
self.__createInterface()
# create a table to hold the cursors for
# widgets which get changed when we go busy
self.preBusyCursors = None
# pack the container and set focus
# to ourselves
self._hull.pack(side=TOP, fill=BOTH, expand=YES)
self.focus_set()
# initialize our options
self.initialiseoptions(AppShell)
def appInit(self):
# Called before interface is created (should be overridden).
pass
def initializeTk(self, root):
# Initialize platform-specific options
if sys.platform == 'mac':
self.__initializeTk_mac(root)
elif sys.platform == 'win32':
self.__initializeTk_win32(root)
else:
self.__initializeTk_unix(root)
def __initializeTk_colors_common(self, root):
root.option_add('*background', 'grey')
root.option_add('*foreground', 'black')
root.option_add('*EntryField.Entry.background', 'white')
root.option_add('*Entry.background', 'white')
root.option_add('*MessageBar.Entry.background', 'gray85')
root.option_add('*Listbox*background', 'white')
root.option_add('*Listbox*selectBackground', 'dark slate blue')
root.option_add('*Listbox*selectForeground', 'white')
def __initializeTk_win32(self, root):
self.__initializeTk_colors_common(root)
root.option_add('*Font', 'Verdana 10 bold')
root.option_add('*EntryField.Entry.Font', 'Courier 10')
root.option_add('*Listbox*Font', 'Courier 10')
def __initializeTk_mac(self, root):
self.__initializeTk_colors_common(root)
def __initializeTk_unix(self, root):
self.__initializeTk_colors_common(root)
def busyStart(self, newcursor=None):
if not newcursor:
newcursor = self.busyCursor
newPreBusyCursors = {}
for component in self.busyWidgets:
newPreBusyCursors[component] = component['cursor']
component.configure(cursor=newcursor)
component.update_idletasks()
self.preBusyCursors = (newPreBusyCursors, self.preBusyCursors)
def busyEnd(self):
if not self.preBusyCursors:
return
oldPreBusyCursors = self.preBusyCursors[0]
self.preBusyCursors = self.preBusyCursors[1]
for component in self.busyWidgets:
try:
component.configure(cursor=oldPreBusyCursors[component])
except KeyError:
pass
component.update_idletasks()
def __createAboutBox(self):
Pmw.aboutversion(self.appversion)
Pmw.aboutcopyright(self.copyright)
Pmw.aboutcontact(
'For more information, contact:\n %s\n Phone: %s\n Email: %s' % \
(self.contactname, self.contactphone,
self.contactemail))
self.about = Pmw.AboutDialog(self._hull,
applicationname=self.appname)
self.about.withdraw()
return None
def showAbout(self):
# Create the dialog to display about and contact information.
self.about.show()
self.about.focus_set()
def toggleBalloon(self):
if self.toggleBalloonVar.get():
self.__balloon.configure(state='both')
else:
self.__balloon.configure(state='status')
def __createMenuBar(self):
self.menuBar = self.createcomponent('menubar', (), None,
Pmw.MenuBar,
(self._hull,),
hull_relief=RAISED,
hull_borderwidth=1,
balloon=self.balloon())
self.menuBar.pack(fill=X)
self.menuBar.addmenu('Help', 'About %s' % self.appname, side='right')
self.menuBar.addmenu('File', 'File commands and Quit')
def createMenuBar(self):
self.menuBar.addmenuitem('Help', 'command',
'Get information on application',
label='About...', command=self.showAbout)
self.toggleBalloonVar = IntVar()
self.toggleBalloonVar.set(1)
self.menuBar.addmenuitem('Help', 'checkbutton',
'Toggle balloon help',
label='Balloon help',
variable=self.toggleBalloonVar,
command=self.toggleBalloon)
self.menuBar.addmenuitem('File', 'command', 'Quit this application',
label='Quit',
command=self.quit)
def __createBalloon(self):
# Create the balloon help manager for the frame.
# Create the manager for the balloon help
self.__balloon = self.createcomponent('balloon', (), None,
Pmw.Balloon, (self._hull,))
def balloon(self):
return self.__balloon
def __createDataArea(self):
# Create data area where data entry widgets are placed.
self.dataArea = self.createcomponent('dataarea',
(), None,
Frame, (self._hull,),
relief=GROOVE,
bd=1)
self.dataArea.pack(side=TOP, fill=BOTH, expand=YES,
padx=self['padx'], pady=self['pady'])
def __createCommandArea(self):
# Create a command area for application-wide buttons.
self.__commandFrame = self.createcomponent('commandframe', (), None,
Frame,
(self._hull,),
relief=SUNKEN,
bd=1)
self.__buttonBox = self.createcomponent('buttonbox', (), None,
Pmw.ButtonBox,
(self.__commandFrame,),
padx=0, pady=0)
self.__buttonBox.pack(side=TOP, expand=NO, fill=X)
if self['usecommandarea']:
self.__commandFrame.pack(side=TOP,
expand=NO,
fill=X,
padx=self['padx'],
pady=self['pady'])
def __createMessageBar(self):
# Create the message bar area for help and status messages.
frame = self.createcomponent('bottomtray', (), None,
Frame, (self._hull,), relief=SUNKEN)
self.__messageBar = self.createcomponent('messagebar',
(), None,
Pmw.MessageBar,
(frame,),
# entry_width = 40,
entry_relief=SUNKEN,
entry_bd=1,
labelpos=None)
self.__messageBar.pack(side=LEFT, expand=YES, fill=X)
self.__progressBar = ProgressBar.ProgressBar(frame,
fillColor='slateblue',
doLabel=1,
width=150)
self.__progressBar.frame.pack(side=LEFT, expand=NO, fill=NONE)
self.updateProgress(0)
frame.pack(side=BOTTOM, expand=NO, fill=X)
self.__balloon.configure(statuscommand= \
self.__messageBar.helpmessage)
def messageBar(self):
return self.__messageBar
def updateProgress(self, newValue=0, newMax=0):
self.__progressBar.updateProgress(newValue, newMax)
def bind(self, child, balloonHelpMsg, statusHelpMsg=None):
# Bind a help message and/or status message to a widget.
self.__balloon.bind(child, balloonHelpMsg, statusHelpMsg)
def interior(self):
# Retrieve the interior site where widgets should go.
return self.dataArea
def buttonBox(self):
# Retrieve the button box.
return self.__buttonBox
def buttonAdd(self, buttonName, helpMessage=None,
statusMessage=None, **kw):
# Add a button to the button box.
newBtn = self.__buttonBox.add(buttonName)
newBtn.configure(kw)
if helpMessage:
self.bind(newBtn, helpMessage, statusMessage)
return newBtn
def __createInterface(self):
self.__createBalloon()
self.__createMenuBar()
self.__createDataArea()
self.__createCommandArea()
self.__createMessageBar()
self.__createAboutBox()
#
# Create the parts of the interface
# which can be modified by subclasses
#
self.busyWidgets = (self.root,)
self.createMenuBar()
self.createInterface()
def createInterface(self):
# Override this method to create the interface for the app.
pass
def main(self):
# This method should be left intact!
self.pack()
self.mainloop()
def run(self):
self.main()
class TestAppShell(AppShell):
usecommandarea = 1
def createButtons(self):
self.buttonAdd('Ok',
helpMessage='Exit',
statusMessage='Exit',
command=self.quit)
def createMain(self):
self.label = self.createcomponent('label', (), None,
Label,
(self.interior(),),
text='Data Area')
self.label.pack()
self.bind(self.label, 'Space taker')
def createInterface(self):
AppShell.createInterface(self)
self.createButtons()
self.createMain()
if __name__ == '__main__':
test = TestAppShell(balloon_state='both')
test.run()
Example_8_10.py
from tkinter import *
import Pmw
import os
import AppShell
from PIL import Image, ImageTk
# Load the PIL plugins for all image types...
for m in ["BmpImagePlugin", "GifImagePlugin", "JpegImagePlugin",
"PpmImagePlugin", "TiffImagePlugin"]:
try:
__import__(m)
except ImportError:
pass # ignore missing driver for now
Image._initialized = 1
path = "./icons/"
imgs = "./images/"
class Node:
def __init__(self, master, tree, icon=None,
openicon=None, name=None, action=None):
self.master, self.tree = master, tree
self.icon = PhotoImage(file=icon)
if openicon:
self.openicon = PhotoImage(file=openicon)
else:
self.openicon = None
self.width, self.height = 1.5 * self.icon.width(),1.5 * self.icon.height()
self.name = name
self.var = StringVar()
self.var.set(name)
self.text = Entry(tree, textvariable=self.var, bg=tree.bg,
bd=0, width=len(name) + 2, font=tree.font,
fg=tree.textcolor, insertwidth=1,
highlightthickness=1,
highlightbackground=tree.bg,
selectbackground="#044484",
selectborderwidth=0,
selectforeground='white')
self.action = action
self.x = self.y = 0 # drawing location
self.child = []
self.state = 'colapsed'
self.selected = 0
def addChild(self, tree, icon=None, openicon=None, name=None,
action=None):
child = Node(self, tree, icon, openicon, name, action)
self.child.append(child)
self.tree.display()
return child
def deleteChild(self, child):
self.child.remove(child)
self.tree.display()
def textForget(self):
self.text.place_forget()
for child in self.child:
child.textForget()
def deselect(self):
self.selected = 0
for child in self.child:
child.deselect()
def boxpress(self, event=None):
if self.state == 'expanded':
self.state = 'colapsed'
elif self.state == 'colapsed':
self.state = 'expanded'
self.tree.display()
def invoke(self, event=None):
if not self.selected:
self.tree.deselectall()
self.selected = 1
self.tree.display()
if self.action:
self.action(self.name)
self.name = self.text.get()
self.text.config(width=len(self.name) + 2)
def displayIconText(self):
tree, text = self.tree, self.text
if self.selected and self.openicon:
self.pic = tree.create_image(self.x, self.y,
image=self.openicon)
else:
self.pic = tree.create_image(self.x, self.y,
image=self.icon)
text.place(x=self.x + self.width / 2, y=self.y, anchor=W)
text.bind("<ButtonPress-1>", self.invoke)
tree.tag_bind(self.pic, "<ButtonPress-1>", self.invoke, "+")
text.bind("<Double-Button-1>", self.boxpress)
tree.tag_bind(self.pic, "<Double-Button-1>",
self.boxpress, "+")
def displayRoot(self):
if self.state == 'expanded':
for child in self.child:
child.display()
self.displayIconText()
def displayLeaf(self):
self.tree.hline(self.y, self.master.x + 1, self.x)
self.tree.vline(self.master.x, self.master.y, self.y)
self.displayIconText()
def displayBranch(self):
master, tree = self.master, self.tree
x, y = self.x, self.y
tree.hline(y, master.x, x)
tree.vline(master.x, master.y, y)
if self.state == 'expanded' and self.child != []:
for child in self.child:
child.display()
box = tree.create_image(master.x, y,
image=tree.minusnode)
elif self.state == 'colapsed' and self.child != []:
box = tree.create_image(master.x, y,
image=tree.plusnode)
tree.tag_bind(box, "<ButtonPress-1>", self.boxpress, "+")
self.displayIconText()
def findLowestChild(self, node):
if node.state == 'expanded' and node.child != []:
return self.findLowestChild(node.child[-1])
else:
return node
def display(self):
master, tree = self.master, self.tree
n = master.child.index(self)
self.x = master.x + self.width
if n == 0:
self.y = master.y + (n + 1) * self.height
else:
previous = master.child[n - 1]
self.y = self.findLowestChild(previous).y + self.height
if master == tree:
self.displayRoot()
elif master.state == 'expanded':
if self.child == []:
self.displayLeaf()
else:
self.displayBranch()
tree.lower('line')
class Tree(Canvas):
def __init__(self, master, icon, openicon, treename, action,
bg='white', relief='sunken', bd=2,
linecolor='#808080', textcolor='black',
font=('MS Sans Serif', 8)):
Canvas.__init__(self, master, bg=bg, relief=relief, bd=bd,
highlightthickness=0)
self.pack(side='left', anchor=NW, fill='both', expand=1)
self.bg, self.font = bg, font
self.linecolor, self.textcolor = linecolor, textcolor
self.master = master
self.plusnode = PhotoImage(file=path + 'plusnode.gif')
self.minusnode = PhotoImage(file=path + 'minusnode.gif')
self.inhibitDraw = 1
self.imageLabel = None
self.imageData = None
self.child = []
self.x = self.y = -10
self.child.append(Node(self, self, action=action,
icon=icon, openicon=openicon, name=treename))
def display(self):
if self.inhibitDraw: return
self.delete(ALL)
for child in self.child:
child.textForget()
child.display()
def deselectall(self):
for child in self.child:
child.deselect()
def vline(self, x, y, y1):
for i in range(0, int(abs(y - y1)), 2):
self.create_line(x, y + i, x, y + i + 1, fill=self.linecolor,
tags='line')
def hline(self, y, x, x1):
for i in range(0, int(abs(x - x1)), 2):
self.create_line(x + i, y, x + i + 1, y, fill=self.linecolor,
tags='line')
class ImageBrowser(AppShell.AppShell):
usecommandarea = 1
appname = 'Image Browser'
def createButtons(self):
self.buttonAdd('Ok',
helpMessage='Exit',
statusMessage='Exit',
command=self.quit)
def createMain(self):
self.panes = self.createcomponent('panes', (), None,
Pmw.PanedWidget,
(self.interior(),),
orient='horizontal')
self.panes.add('browserpane', min=150, size=160)
self.panes.add('displaypane', min=.1)
f = path + 'folder.gif'
of = path + 'openfolder.gif'
self.browser = self.createcomponent('browse', (), None,
Tree,
(self.panes.pane('browserpane'),),
icon=f,
openicon=of,
treename='Multimedia',
action=None)
self.browser.pack(side=TOP, expand=YES, fill=Y)
self.datasite = self.createcomponent('datasite', (), None,
Frame,
(self.panes.pane('displaypane'),))
self.datasite.pack(side=TOP, expand=YES, fill=BOTH)
f = path + 'folder.gif'
of = path + 'openfolder.gif'
gf = path + 'gif.gif'
jf = path + 'jpg.gif'
xf = path + 'other.gif'
self.browser.inhibitDraw = 1
top = self.browser.child[0]
top.state = 'expanded'
jpeg = top.addChild(self.browser, icon=f, openicon=of,
name='Jpeg', action=None)
gif = top.addChild(self.browser, icon=f, openicon=of,
name='GIF', action=None)
other = top.addChild(self.browser, icon=f, openicon=of,
name='Other', action=None)
imageDir = {'.jpg': (jpeg, jf), '.jpeg': (jpeg, jf),
'.gif': (gif, gf), '.bmp': (other, xf),
'.ppm': (other, xf)}
files = os.listdir(imgs)
for file in files:
r, ext = os.path.splitext(file)
if ext:
cont, icon = imageDir.get(ext, (None, None))
if cont:
cont.addChild(self.browser, icon=icon,
name=file, action=self.showMe)
self.browser.inhibitDraw = 0
self.browser.display()
self.panes.pack(side=TOP,
expand=YES,
fill=BOTH)
def createImageDisplay(self):
self.imageDisplay = self.createcomponent('image', (), None,
Label,
(self.datasite,))
self.browser.imageLabel = self.imageDisplay
self.browser.imageData = None
self.imageDisplay.place(relx=0.5, rely=0.5, anchor=CENTER)
def createInterface(self):
AppShell.AppShell.createInterface(self)
self.createButtons()
self.createMain()
self.createImageDisplay()
def showMe(self, dofile):
if self.browser.imageData: del self.browser.imageData
self.browser.imageData = ImageTk.PhotoImage(Image.open('%s%s' % (imgs, dofile)))
self.browser.imageLabel['image'] = self.browser.imageData
if __name__ == '__main__':
imageBrowser = ImageBrowser()
imageBrowser.run()
程序引用图片(解压缩后放到程序同目录下)
Icons.zip
(5.56 KB, 下载次数: 2)
images.zip
(176.71 KB, 下载次数: 2)
完整代码+图片如下:
图像查看器.zip
(198.42 KB, 下载次数: 16)
原程序是用python2.x编译的,我修改了几个地方,让它可以在python3.7上运行
这个程序里的目录结构应该很常见。
我之前看到批量图片下载工具NeoDownloader大概有类似的界面,那个程序未必是用python写的,但是用python的话,用爬虫加tkinter就可以做出类似的程序来。感兴趣的可以研究一下 |
|