Python简单GUI程序示例
参考或取自网络,包括:一、记事本;二、简单画图;三、猜数游戏;四、视频播放器
一、记事本
源码
#python简易记事本
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import os
filename='' #文件名,全局变量
def about():
messagebox.showinfo('提示','这是一个消息框')
def openFile():
global filename #使用全局变量
filename=filedialog.askopenfilename(defaultextension='.txt') #打开文件,默认扩展名是xtxt
if filename=='': #如果没有选择
filename=None
else:
root.title('FileName:'+os.path.basename(filename)) #将文件名显示在标题栏中
textPad.delete(1.0,END) #删除文本框中原有内容
f=open(filename,'r',encoding='UTF-8') #获取文件中内容
textPad.insert(1.0,f.read()) #显示到文本框
f.close()
def saveOtherFile():
global filename
f=filedialog.asksaveasfilename(initialfile='未命名.txt',defaultextension='.txt') #保存文件
filename=f
root.title('FileName:' + os.path.basename(filename))
fh=open(f,'w',encoding='UTF-8') #只写方式打开文件
msg=textPad.get(1.0,END) #从文本框中获取内容
fh.write(msg)
fh.close()
root=Tk() #设置菜单栏
root.title('记事本')
root.geometry('500x500+100+100') #widthxheight+x+y
menubar=Menu(root)
root.config(menu=menubar)
filemenu=Menu(menubar) #第一个菜单栏
filemenu.add_command(label='打开',accelerator='Ctrl+N',command=openFile)
filemenu.add_command(label='保存',accelerator='Ctrl+T',command=saveOtherFile)
menubar.add_cascade(label='文件',menu=filemenu)
aboutmenu=Menu(menubar)
aboutmenu.add_command(label='关于',accelerator='Ctrl+Y',command=about)
menubar.add_cascade(label='帮助',menu=aboutmenu)
status=Label(root,text='Ln20',bd=1,relief=SUNKEN,anchor=W) #底部状态栏
status.pack(side=BOTTOM,fill=X)
lnlabel=Label(root,width=2,bg='antique white') #左边边界栏
lnlabel.pack(side=LEFT,fill=Y)
textPad=Text(root,undo=True) #设置文本框
textPad.pack(expand=YES,fill=BOTH)
scroll=Scrollbar(textPad) #右边进度条栏
textPad.config(yscrollcommand=scroll.set)
scroll.config(command=textPad.yview)
scroll.pack(side=RIGHT,fill=Y)
root.mainloop()
运行效果:
二、简单画图
# 画图程序
import os
import tkinter
import tkinter.simpledialog
import tkinter.colorchooser
import tkinter.filedialog
from PIL import Image
from PIL import ImageGrab
def openItem():
global img
filename=tkinter.filedialog.askopenfilename(title="Open",filetypes=[('Image','*.png *.gif')])
if filename:
img=tkinter.PhotoImage(file=filename)
canvas.create_image(400,300,image=img)
def saveItem():
saveX=int(root.winfo_rootx())
saveY=int(root.winfo_rooty())
saveW=root.winfo_width()
saveH=root.winfo_height()
im=ImageGrab.grab((saveX,saveY,saveX+saveW,saveY+saveH))
filename=tkinter.filedialog.asksaveasfilename(title='Save',filetypes=[('Image','*.png *.gif')])
if not filename:
return
try:
if filename[filename.index('.'):] in ['.png','.gif']==False:
filename+='.png'
except:
filename+='.png'
im.save(filename)
def clearItem():
for i in canvas.find_all():
canvas.delete(i)
def curveType():
penType.set(1)
def lineType():
penType.set(2)
def rectangleType():
penType.set(3)
def textType():
global userText
userText=tkinter.simpledialog.askstring(title="Please input your words", prompt='')
penType.set(4)
def eraseType():
penType.set(5)
def chooseForeColor():
global foreColor
foreColor=tkinter.colorchooser.askcolor()[1]
def chooseBackColor():
global backColor
backColor=tkinter.colorchooser.askcolor()[1]
def onClickLeft(event):
global userText
canDraw.set(1)
X.set(event.x)
Y.set(event.y)
if penType.get()==4:
canvas.create_text(event.x,event.y,text=userText)
def onMoveLeft(event):
global lastPaint,foreColor,backColor
if canDraw.get()==0:
return
if penType.get()==1: #绘制曲线
canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor)
X.set(event.x)
Y.set(event.y)
elif penType.get()==2: #绘制直线(预览)
try:
canvas.delete(lastPaint)
except:
pass
lastPaint=canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor)
elif penType.get()==3: #绘制矩形(预览)
try:
canvas.delete(lastPaint)
except:
pass
lastPaint=canvas.create_rectangle(X.get(),Y.get(),event.x,event.y,fill=backColor,outline=foreColor)
elif penType.get()==5: #橡皮擦
canvas.create_rectangle(event.x-5,event.y-5,event.x+5,event.y+5,fill=backColor,outline=backColor)
def onReleaseLeft(event):
global lastPaint,foreColor,backColor
lastPaint=0
if penType.get()==2: #抬起左键画直线
canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor)
elif penType.get()==3: #抬起左键就画矩形
canvas.create_rectangle(X.get(),Y.get(),event.x,event.y,fill=backColor,outline=foreColor)
canDraw.set(0)
def onReleaseRight(event):
menu.post(event.x_root, event.y_root)
root=tkinter.Tk()
root.title("Paint")
root.geometry("800x600+280+50")
lastPaint=0
userText=""
foreColor='black'
backColor='white'
X=tkinter.IntVar(value=0)
Y=tkinter.IntVar(value=0)
canDraw=tkinter.IntVar(value=0) #能否画图,1:能,0:不能
penType=tkinter.IntVar(value=1) #画笔类型,1:曲线,2:直线,3:矩形,4:文本,5:橡皮擦
menu=tkinter.Menu(root,tearoff=0)
subMenu=tkinter.Menu(menu,tearoff=0)
img=tkinter.PhotoImage()
canvas=tkinter.Canvas(root,bg='white',width=800,height=600)
canvas.create_image(800,600,image=img)
menu.add_command(label='Open',command=openItem)
menu.add_command(label='Save as',command=saveItem)
menu.add_separator()
subMenu.add_command(label='Curve',command=curveType)
subMenu.add_command(label='Line',command=lineType)
subMenu.add_command(label='Rectangle',command=rectangleType)
subMenu.add_command(label='Text',command=textType)
subMenu.add_command(label='Erase',command=eraseType)
menu.add_cascade(label='Pen Type',menu=subMenu)
menu.add_separator()
menu.add_command(label='Foreground Color',command=chooseForeColor)
menu.add_command(label='Bakckground Color',command=chooseBackColor)
menu.add_separator()
menu.add_command(label='Clear',command=clearItem)
canvas.bind('<Button-1>', onClickLeft)
canvas.bind('<B1-Motion>',onMoveLeft)
canvas.bind('<ButtonRelease-1>',onReleaseLeft)
canvas.bind('<ButtonRelease-3>',onReleaseRight)
canvas.pack(fill=tkinter.BOTH,expand=tkinter.YES)
root.mainloop()
运行效果:
三、猜数游戏
#猜数游戏
import tkinter
import tkinter.messagebox
from tkinter.simpledialog import askinteger
import random
def init():
entryNum['state'] = "disabled"
btnConfirm['state'] = "disabled"
def confirm():
global guessNum
global count
count[0] += 1
t = guessNum - int(varNum.get())
if(t == 0): # 猜对了
#tkinter.messagebox.showinfo(title="祝贺", message="你赢了!")
count[1] += 1
btnConfirm['state'] = "disabled"
mess2 = tkinter.Label(root,text="你赢了!猜的次数:" + str(count[0])).place(x=20, y=30, width=200, height=20) #显示标签
elif(t > 0): # 猜小了
#tkinter.messagebox.showinfo(title="提示", message="猜小了!")
mess2 = tkinter.Label(root,text="猜小了" ).place(x=20, y=30, width=200, height=20) #显示标签
count[2] += 1
else: # 猜大了
#tkinter.messagebox.showinfo(title="提示", message="猜大了!")
mess2 = tkinter.Label(root,text="猜大了" ).place(x=20, y=30, width=200, height=20) #显示标签
count[2] += 1
def startGuess():
global count
global guessNum
global minNum
global maxNum
guessNum = random.randint(minNum, maxNum)
mess2 = tkinter.Label(root,text="范围:" +str(minNum)+"~"+str(maxNum)).place(x=20, y=30, width=200, height=20) #显示标签
print(guessNum)
count = [0, 0, 0]
entryNum['state'] = "normal"
btnConfirm['state'] = "normal"
def setProperty():
global minNum
global maxNum
while True:
try:
t = askinteger("设置最小值",'设置最小整数(>0)',initialvalue=1)
if t != None:
assert t>0
minNum=t
break
except:
pass
while True:
try:
t = askinteger("设置最大值",'设置最大整数(>'+str(minNum)+')',initialvalue=minNum+10)
if t != None:
assert t>minNum
maxNum=t
break
except:
pass
changeNum()
btnConfirm['state'] = "disabled"
mess2 = tkinter.Label(root,text="范围:" +str(minNum)+"~"+str(maxNum)).place(x=20, y=30, width=200, height=20) #显示标签
def changeNum():
global guessNum
global minNum
global maxNum
guessNum = random.randint(minNum, maxNum)
def closeWindow():
global count
#tkinter.messagebox.showinfo("成绩", "次数:" + str(count[0]) + " Right:" + str(count[1]) + " Wrong:" + str(count[2]))
root.destroy()
minNum = 1
maxNum = 100
guessNum = 0
count = [0, 0, 0] # 分别为:猜测次数,正确次数,错误次数
root = tkinter.Tk()
root.title("Guess Number")
root.resizable(False, False)
root.geometry("400x100+480+320")
mess = tkinter.Label(root, text="请输入一个整数:")
mess.place(x=20, y=10, width=200, height=20)
mess2 = tkinter.Label(root,text="提示").place(x=20, y=30, width=200, height=20) #显示标签
varNum = tkinter.StringVar(root, value='0')
entryNum = tkinter.Entry(root, width=80, textvariable=varNum)
entryNum.place(x=220, y=10, width=60, height=20)
btnConfirm = tkinter.Button(root, text='确认', command=confirm)
btnConfirm.place(x=290, y=10, width=70, height=20)
#btnChange = tkinter.Button(root, text="更换数字", command=changeNum)
#btnChange.place(x=20, y=50, width=90, height=20)
btnStart = tkinter.Button(root, text='[重新]开始', command=startGuess)
btnStart.place(x=210, y=50, width=70, height=20)
btnSet = tkinter.Button(root, text='设置范围', command=setProperty)
btnSet.place(x=125, y=50, width=70, height=20)
init()
root.protocol("WM_DELETE_WINDOW", closeWindow)
root.mainloop()
运行效果:
四、视频播放器
注意事项
1)需要使用pip安装Python扩展包(模块)PyQt5;
2)PyQt5 的多媒体模块QtMultimedia本身不提供任何的编码和解码功能,所以Qt的多媒体模块需要依赖平台(操作系统)支持那些编码和解码格式。
若想播放MP4等格式需要下载安装解码器K-Lite_Codec_Pack_1680_Basic.exe (下载地址http://www.codecguide.com/download_k-lite_codec_pack_basic.htm)
源码如下:
#
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QSlider
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import *
class myVideoWidget(QVideoWidget):
doubleClickedItem = pyqtSignal(str) # 创建双击信号
def __init__(self, parent=None):
super(QVideoWidget, self).__init__(parent)
def mouseDoubleClickEvent(self, QMouseEvent): #双击事件
self.doubleClickedItem.emit("double clicked")
class myVideoSlider(QSlider):
ClickedValue = pyqtSignal(int)
def __init__(self, father):
super().__init__(Qt.Horizontal, father)
def mousePressEvent(self, QMouseEvent): #单击事件
super().mousePressEvent(QMouseEvent)
value = QMouseEvent.localPos().x()
# self.setValue(int(value)/9)
value = round(value/self.width()*self.maximum()) # 根据鼠标点击的位置和slider的长度算出百分比
self.ClickedValue.emit(value)
class myMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(615, 404)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.wgt_video = myVideoWidget(self.centralwidget)
self.wgt_video.setMinimumSize(QtCore.QSize(410, 200))
self.wgt_video.setMaximumSize(QtCore.QSize(16777215, 16777215))
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
self.wgt_video.setPalette(palette)
self.wgt_video.setAutoFillBackground(True)
self.wgt_video.setObjectName("wgt_video")
self.gridLayout.addWidget(self.wgt_video, 0, 0, 1, 1)
self.sld_video = myVideoSlider(self.centralwidget)
self.sld_video.setMinimumSize(QtCore.QSize(410, 0))
self.sld_video.setMaximumSize(QtCore.QSize(16777215, 20))
self.sld_video.setMaximum(100)
self.sld_video.setOrientation(QtCore.Qt.Horizontal)
self.sld_video.setObjectName("sld_video")
self.gridLayout.addWidget(self.sld_video, 1, 0, 1, 1)
self.lab_video = QtWidgets.QLabel(self.centralwidget)
self.lab_video.setMaximumSize(QtCore.QSize(16777215, 50))
self.lab_video.setObjectName("lab_video")
self.gridLayout.addWidget(self.lab_video, 1, 1, 1, 1)
self.splitter = QtWidgets.QSplitter(self.centralwidget)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.btn_open = QtWidgets.QPushButton(self.splitter)
self.btn_open.setMaximumSize(QtCore.QSize(100, 25))
self.btn_open.setObjectName("btn_open")
self.btn_play = QtWidgets.QPushButton(self.splitter)
self.btn_play.setMaximumSize(QtCore.QSize(100, 25))
self.btn_play.setObjectName("btn_play")
self.btn_stop = QtWidgets.QPushButton(self.splitter)
self.btn_stop.setMaximumSize(QtCore.QSize(100, 25))
self.btn_stop.setObjectName("btn_stop")
self.sld_audio = QtWidgets.QSlider(self.splitter)
self.sld_audio.setMinimumSize(QtCore.QSize(100, 0))
self.sld_audio.setMaximumSize(QtCore.QSize(150, 20))
self.sld_audio.setProperty("value", 99)
self.sld_audio.setOrientation(QtCore.Qt.Horizontal)
self.sld_audio.setObjectName("sld_audio")
self.lab_audio = QtWidgets.QLabel(self.splitter)
self.lab_audio.setObjectName("lab_audio")
self.btn_cast = QtWidgets.QPushButton(self.splitter)
self.btn_cast.setObjectName("btn_cast")
self.gridLayout.addWidget(self.splitter, 2, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 615, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.lab_video.setText("0%")
self.btn_open.setText("打开视频文件")
self.btn_play.setText("播放")
self.btn_stop.setText("暂停")
self.lab_audio.setText("volume:100%")
self.btn_cast.setText("截图")
self.sld_video_pressed=False #判断当前进度条识别否被鼠标点击
self.videoFullScreen = False # 判断当前widget是否全屏
self.videoFullScreenWidget = myVideoWidget() # 创建一个全屏的widget
self.player = QMediaPlayer()
self.player.setVideoOutput(self.wgt_video) # 视频播放输出的widget,就是上面定义的
self.btn_open.clicked.connect(self.openVideoFile) # 打开视频文件按钮
self.btn_play.clicked.connect(self.playVideo) # play
self.btn_stop.clicked.connect(self.pauseVideo) # pause
self.btn_cast.clicked.connect(self.castVideo) # 视频截图
self.player.positionChanged.connect(self.changeSlide) # change Slide
self.videoFullScreenWidget.doubleClickedItem.connect(self.videoDoubleClicked) #双击响应
self.wgt_video.doubleClickedItem.connect(self.videoDoubleClicked) #双击响应
self.sld_video.setTracking(False)
self.sld_video.sliderReleased.connect(self.releaseSlider)
self.sld_video.sliderPressed.connect(self.pressSlider)
self.sld_video.sliderMoved.connect(self.moveSlider) # 进度条拖拽跳转
self.sld_video.ClickedValue.connect(self.clickedSlider) # 进度条点击跳转
self.sld_audio.valueChanged.connect(self.volumeChange) # 控制声音播放
self.btn_cast.hide()
def castVideo(self):
screen = QGuiApplication.primaryScreen()
cast_jpg = './'+QDateTime.currentDateTime().toString("yyyy-MM-dd hh-mm-ss-zzz")+'.jpg'
screen.grabWindow(self.wgt_video.winId()).save(cast_jpg)
def volumeChange(self, position):
volume= round(position/self.sld_audio.maximum()*100)
print("vlume %f" %volume)
self.player.setVolume(volume)
self.lab_audio.setText("volume:"+str(volume)+"%")
def clickedSlider(self, position):
if self.player.duration() > 0: # 开始播放后才允许进行跳转
video_position = int((position / 100) * self.player.duration())
self.player.setPosition(video_position)
self.lab_video.setText("%.2f%%" % position)
else:
self.sld_video.setValue(0)
def moveSlider(self, position):
self.sld_video_pressed = True
if self.player.duration() > 0: # 开始播放后才允许进行跳转
video_position = int((position / 100) * self.player.duration())
self.player.setPosition(video_position)
self.lab_video.setText("%.2f%%" % position)
def pressSlider(self):
self.sld_video_pressed = True
print("pressed")
def releaseSlider(self):
self.sld_video_pressed = False
def changeSlide(self, position):
if not self.sld_video_pressed: # 进度条被鼠标点击时不更新
self.vidoeLength = self.player.duration()+0.1
self.sld_video.setValue(round((position/self.vidoeLength)*100))
self.lab_video.setText("%.2f%%" % ((position/self.vidoeLength)*100))
def openVideoFile(self):
self.player.setMedia(QMediaContent(QFileDialog.getOpenFileUrl()[0])) # 选取视频文件
self.player.play() # 播放视频
print(self.player.availableMetaData())
def playVideo(self):
self.player.play()
def pauseVideo(self):
self.player.pause()
def videoDoubleClicked(self, text):
if self.player.duration() > 0: # 开始播放后才允许进行全屏操作
if self.videoFullScreen:
self.player.setVideoOutput(self.wgt_video)
self.videoFullScreenWidget.hide()
self.videoFullScreen = False
else:
self.videoFullScreenWidget.show()
self.player.setVideoOutput(self.videoFullScreenWidget)
self.videoFullScreenWidget.setFullScreen(1)
self.videoFullScreen = True
if __name__ == '__main__':
app = QApplication(sys.argv)
vieo_gui = myMainWindow()
vieo_gui.show()
sys.exit(app.exec_())
运行效果: