Python 入门深化

异常

异常指程序运行过程中出现的非正常现象

所谓异常处理,就是指程序在出现问题时依然可以正确的执行剩余的程序,而不会因为异常而终止程序

a = 3/0      # 简单的异常

处理异常的过程

Python 中一切都是对象,异常也是采用对象的方式处理。处理过程

  1. 抛出异常:在执行一个方法中,如果发生异常则这个方法生成代表异常的一个对象,停止当前执行路径,并把异常对象提交给解释器
  2. 捕获异常:解释器得到该异常后,寻找相应的代码来处理该异常

try except

注意: return 语句不要在 try except else finally 块中,直接放在方法的最后

异常结构

try:
	被监控的可能引发异常的语句块
except Exception [as e]:
	异常处理语句块
[else:]
	else 中语句块
[finally:]
	finally 中语句块
Just Test It
try:
    a = input("请输入一个被除数: ")
    b = input("请输入一个除数: ")
    c = float(a)/float(b)
    print(c)
except ZeroDivisionError as e:
    print("除数不能为零",e)
except ValueError as  e:
    print("异常,字符串不能转为数字",e)
except NameError as  e :
    print("异常。变量不存在",e)
except  BaseException as  e:
    print(e)

else 语句

当 try 语句块中没有发生异常,则执行 else 语句中的内容

#coding=utf-8
# 测试 try - except - else 语句

try:
    a = input("请输入一个被除数: ")
    b = input("请输入一个除数: ")
    c = float(a)/float(b)
except  Exception as  e:  # try 语句块发生异常,执行 except 中语句
    print(e)
else:  #没有异常,执行 else 语句
    print(c)

finally 语句

finally 语句块无论是否发生异常都会被执行:通常用来释放 try 块中申请的资源

try
except
else
finally
# coding=utf-8
# 测试 try - except - else 语句

if __name__ == '__main__':
    try:
        a = input("请输入一个被除数: ")
        b = input("请输入一个除数: ")
        c = float(a) / float(b)
    except  Exception as  e:  # try 语句块发生异常,执行 except 中语句
        print(e)
    else:  # 没有异常,执行 else 语句
        print(c)
    finally:  # 无论是否发生异常, finally 块中代码都执行
        print("程序执行完毕 ...")

运行结果1

D:\python\python3\python.exe "F:/pythoWorkspaces/20190905 python-primary/03-exception/03-finally.py"
请输入一个被除数: 1
请输入一个除数: 1
1.0
程序执行完毕 ...

运行结果2

D:\python\python3\python.exe "F:/pythoWorkspaces/20190905 python-primary/03-exception/03-finally.py"
请输入一个被除数: 1
请输入一个除数: 0
float division by zero
程序执行完毕 ...

Process finished with exit code 0

文件操作
# coding=utf-8
# 读取文本文件资源

if __name__ == '__main__':
    try:
        f = open("text.txt")
        content = f.readline()
        print(content)
    except Exception as e:
        print(e)
    finally:
        try:
            f.close()
        except Exception as  e:
            print(e)

常见的异常错误

SyntaxError语法错误
NameError未声明指定的命名变量
ZeroDivisionError除数为0 错误
ValueError数值错误
TypeError类型错误
AttributeError访问对象的不存在的属性
IndexError索引越界异常
KeyError字典的关键字不存在
常见异常汇总

with 上下文管理

with 上下文管理可以自动管理资源,在 with 代码块执行完毕还原进入该代码之前的现场或上下文。不论何种原因跳出 with 块,不论是否有异常,总能保证资源正常释放。

语法结构
with context_expr[as var]
	语句块
文件操作
# coding=utf-8
# with 上下文管理器

if __name__ == '__main__':
    with open("text.txt") as f:
        content = f.readline()
        print(content)

注意:with 上下文管理并非取代 try-except-finally

trackback 模块

打印异常信息

# coding=utf-8
# 测试 trackback 异常日志处理
import traceback
import calendar
if __name__ == '__main__':

    # try:
    #     print("step1")
    #     i = 1 / 0
    # except:
    #     traceback.print_exc()

    try:
        print("step1")
        i = 1 / 0
    except:
        # 将异常信息写日志文件中
        with open("exception.log", 'a') as  f:
            traceback.print_exc(file=f)


    print("程序执行结束 ...")

自定义异常类

自定义异常类一般是运行时异常,通常继承 Exception 类即可。

# coding=utf-8
# 测试自定义异常

class AgeError(Exception):
    def __init__(self, errorInfo):
        super().__init__(self)  # 调用父类的 __init__ 方法
        self.__errorInfo = errorInfo

    def __str__(self):
        return str(self.__errorInfo) + "不在年龄在(0,200] 之间"


if __name__ == '__main__':
    age = int(input("请输入一个年龄:"))
    if age < 0 or age > 200:
        raise AgeError(age)
    else:
        print("年龄为:", age)

IO 技术

文本文件和二进制文件

文本文件存储的是 字符,默认使用 unicode 字符集

二进制文件按字节存储

创建文件对象 open()

语法格式
open(文件名[,打开方式])
打开模式·
打开方法说明
r读模式
w写模式
a追加模式
b以二进制方式操作文件(可以与其他模式组合)
+读写模式(可以与其他模式组合)

文本文件的操作

中文乱码的解决

乱码问题:由于编码和解码时所使用的字符集不一致造成的

# coding=utf-8
# 测试写入文本文件

if __name__ == '__main__':
    with open("a.txt", 'a', encoding='utf-8') as f:
        s = "Hello World Python! 您好"
        f.write(s)
    # f.close()  # 使用 with 语句可以省略该语句
write()/writelines() 写入
if __name__ == '__main__':
    try:
        f = open('my.txt', 'a')
        f.write("iiiii")
        f.writelines('1234556\t')
    except Exception as e:
        print(e)
    finally:
        f.close()
    print('程序结束 运行.....')
close() 关闭流

文件读取

方法作用
read([size])若不给定参数,则读取全部文本内容
若给定参数 size,则读取 size 个字符
readline文本文件中,读取一行内容作为结果返回。读取文件的末尾,会返回空字符串
realines文本文件中,每一行作为一个字符串存入列表中,返回该列表
if __name__ == '__main__':
    # 读取文本文件内容
    with open(r'a.txt', 'r', encoding='utf-8') as f:
        result = f.read(5)  # 读取该文本文件前 5 个字符
        print(result)

    print("{:*^30}".format("华丽的分割线"))

    with open(r'a.txt', 'r', encoding='utf-8') as f:
        line = f.readline()  # 读取一整行
        print(line)

    print("{:*^30}".format("华丽的分割线"))

    with open(r'a.txt', 'r', encoding='utf-8') as f:
        list = f.readlines()  # 读取全部,并放入列表中
        print(list)
        for i in range(list.__len__()):
            print(list[i], end="")

为文本文件添加行号
if __name__ == '__main__':
    '''
         为文本文件添加行号
    '''
    with open('a.txt', 'r', encoding='utf-8') as f:
        myList = f.readlines()
        print(myList)
        '''列表推导式'''
        txt = [line.rstrip()+"#" + str(index) + "\n" for index, line in list(enumerate(myList))]
        print(txt)
    with open('a.txt', 'w', encoding='utf-8') as f:
        f.writelines(txt)
    print("over")

二进制文件的读取和写入

f = open(r"file.txt",'wb')  #可写的、重写模式的二进制文件
f = open(r"file.txt",'ab')  #可写的、追加模式的二进制文件
f = open(r"file.txt",'rb')  #可读的二进制文件

文件对象的常用操作方法

文件对象的常用操作方法

Test it
if __name__ == '__main__':
    '''
        tell 返回当前文本指针的位置
        seek(offset[,whence])   
        offset 表示偏移量
        whence = 0,表示相对于文件头开始计算偏移量
        whence = 1,表示从当前位置开始计算偏移量
        whence = 2,表示从文件末尾开始计算偏移量
    '''
    with open(r'a.txt', 'r', encoding='utf-8') as f:
        print("当前文件的文件名:{}".format(f.name))
        print("当前文件指针的位置:{}".format(f.tell()))
        print("读取一行:{}".format(f.readline().rstrip()))
        f.seek(5, 0)
        print("当前文件指针的位置:{}".format(f.tell()))
        print("读取一行:{}".format(f.readline().rstrip()))
        print("当前文件指针的位置:{}".format(f.tell()))


序列化与反序列

使用 pickle 模块

import pickle

pickle.dump(obj,file)  	  #obj 就是要被序列化的对象, file 指的是存储的文件
pickle.load(file)         #从 file 读取数据,反序列化成对象
Just Test It
import pickle

'''
 将 Student 对象序列化保存到 stu.dat 文件中
 再读取 stu.data 文件,反序列化到 Student 对象
'''


class Student(object):

    def __init__(self, name, age, sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

    def __str__(self):
        return "Student[name:{0},age:{1},sex:{2}]".format(self.__name, self.__age, self.__sex)


if __name__ == '__main__':
    zhangsan = Student('张三', 20, 'male')
    print(zhangsan)
    with open('stu.dat', 'wb') as f:
        pickle.dump(zhangsan, f)

    with open(r'stu.dat', 'rb') as f:
        zhangsan2 = pickle.load(f)
    print(zhangsan2)
    
    print("zhangsan:{0},zhangsan2:{1}".format(id(zhangsan), id(zhangsan2)))

CSV 文件操作

import csv  # 导入 csv 模块

'''
 读写 csv 文件
'''
if __name__ == '__main__':
    # 写入 csv 文件
    with open('cc.csv', 'w', encoding='utf-8') as f:
        csv_writer = csv.writer(f)  # 获取 csv 写入器
        csv_writer.writerow(["ID", "name", "age"])
        csv_writer.writerow(["0111", "张三", "49"])

    # 读取 csv 文件
    with open('cc.csv', 'r', encoding='utf-8') as f:
        csv_reader = csv.reader(f)
        csv_list = list(csv_reader)
        for line in range(csv_list.__len__()):
            print(csv_list[line])

os 模块 和 os.path 模块

os 调用操作文件文件和命令

  • os.system() 调用操作系统中程序
import os 

# 调用记事本
os.system("notepad.exe")

os.system("ping www.baidu.com")

# 查询网络配置
os.system("ipconfig") 

# 打开 cms 命令行窗口
os.system("cmd")

# 直接调用可执行的文件
os.startfile(r"")
os.startfile(r"D:\software\Navicat for MySQL\navicat.exe")

os 模块-文件和目录操作

[外链图片转存失败(img-aJI5feGg-1569026039987)(D:\photo\TyporaPicture\20190912213258.png)]

# coding=utf-8
import os

if __name__ == '__main__':
    with open('text.txt','w',encoding='utf-8') as f:
        f.write("Hello RM")

    # 删除文件
    # os.remove('text.txt')
    # 重命名文件
    # os.rename('text.txt','text-new.txt')
    # 列出当前目录的文件及文件夹
    print(os.listdir('.'))
    # 列出的文件的所有属性
    file_attrs = os.stat('../')
    print(file_attrs)
    # 创建一个目录
    # os.mkdir("test")
    # os.makedirs("test/t1/t2/t3")
    # 删除 t3 目录
    # os.rmdir("test/t1/t2/t3")
    # 删除 test/t1/t2 多级目录
    # os.removedirs("test/t1/t2")
    # 获取当前目录的全路径 F:\pythoWorkspaces\20190905 python-primary\05-dictory
    print(os.getcwd())
    # 创建 child 目录
    os.mkdir("child")
    # 切换到 child 目录下
    os.chdir("child")
    # 打印当前目录的全路径
    print(os.getcwd())

os.path 模块

P

# coding:utf-8
from os import *
from os.path import *

'''
    递归遍历指定的文件夹
'''


# def listDir(path):
#     dir_tree  = list(walk(path))
#     for i in dir_tree:
#         print(i)


def listDir(path, count):
    dir = listdir(path)
    for file in dir:
        if isdir(join(path, file)):
            count += 1
            print("-" * count + file.__add__("目录"))
            listDir(join(path, file), count)
        else:
            if file.endswith(".css"):
                print("--" * count + file)


def listDir2(path):
    [print(file) for file in listdir(path) if isfile(file) and file.endswith(".py")]

if __name__ == '__main__':
    # listDir("F:\\workspaces\\20190721sxtTest\\Car",0)
    listDir2("F:\\pythoWorkspaces\\20190905 python-primary\\05-dictory")

walk() 递归遍历所有文件和目录

os.walk 方法:

返回一个 3 个元素的元素,(dirpath,dirnames,filenames)

  • dirpath: 要列出指定目录的路径
  • dirnames: 目录下的所有文件夹
  • filenames: 目录下的所有文件
# coding:utf-8
'''
  使用 walk 遍历子文件夹和子目录
'''
from os import getcwd, chdir, walk
from os.path import join

if __name__ == '__main__':
    chdir("F:/pythoWorkspaces/20190905 python-primary")
    cur_path = getcwd()
    for dirpath, dirnames, filenames in  walk(cur_path):
        for filename in filenames:
            print(join(dirpath, filename))
        for dirname in dirnames:
            print(join(dirpath,dirname))

shutil 模块和 zipfile 模块

提供了了移动、复制、压缩、解压缩等操作

# coding:utf-8

'''
    shutil  库提供了文件和文件夹的移动、复制等操作
'''
import shutil
import zipfile

if __name__ == '__main__':
    # 拷贝文件
    # shutil.copyfile("java\Thread.java", "Thread.java")
    # 拷贝目录
    # shutil.copytree("Java\IO", "IO")
    # 拷贝目录,增加过滤条件
    # shutil.copytree("Java\IO","IO",ignore=shutil.ignore_patterns("*.java", "*.html"))

    '''
        第一个参数:压缩后的文件名
        第二个参数:表示压缩的格式(zip ,tar 类型)
        第三个参数:表示被压缩的文件夹或文件
    '''
    # shutil.make_archive("java", "tar", "Java")

    # 压缩文件夹
    # z1 = zipfile.ZipFile("IO.zip", "w")
    # z1.write("text.txt")
    # z1.write("text-new.txt")
    # z1.write("java.zip")
    # z1.close()

    # with zipfile.ZipFile("python.zip", "w") as  zp:
    #     zp.write("01-os.py")

    # 解压缩文件
    try:
        with zipfile.ZipFile("python.zip", 'r') as  zp:
            zp.extractall("python")
    except FileNotFoundError as e:
        print("请检查压缩包是否存在")
    finally:
        print("over")

递归算法

自己调用自己

# coding:utf-8

def factorial(n):
    '''计算阶乘'''
    if n == 1:
        return 1
    else:
        return n * factorial(n - 1)


if __name__ == '__main__':
    result = factorial(5)
    print(result)

模块(module)

“量变引起质变” 是哲学中一个重要的理论。量变为什么会引起质变呢?本质上理解,随着数量的增加,管理方式会发生本质的变化;旧的管理方式完全不适合,必须采用新的管理方式

标椎库模块(standard libary)

模块(module)分为标准库模块和用户自定义模块

模块化编程(Model Programming )将一个任务分解成多个模块

模块化编程的流程

  1. 设计 API,进行功能描述
  2. 编码实现 API 中描述的功能
  3. 在模块中编写测试代码,并笑出全局代码
  4. 使用私有函数实现不被外部客户端调用的模块函数
  • Salary.py
'''计算薪水'''

def yearSalary(monthSalay):
    '''计算年薪'''

def monthSalry(daySalary):
    '''计算月薪'''

if __name__ == '__main__':
    print(__name__)
  • Salary.
import Salary

if __name__ == '__main__':
    print(Salary.__name__)  #当模块被其他模块调用 __name__ ,为当前文件名

    print(Salary.__doc__)
    print(Salary.yearSalary.__doc__)

import 语句

导入的对象是实例是单例的

语法格式
import 模块名
import 模块名,模块名2
import 模块名 as 别名

from 模块名 as  函数名
__import__(moubleName) 动态导入

不推荐

importlib 库

import importlib

a = importlib.import_mouble('模块名')  # 模块名使用字符串格式

importlib.reload(a)  # 重新加载被导入的模块
测试
import  importlib


if __name__ == '__main__':
    '''
        测试 importlib
    '''
    print(id(importlib),type(importlib),importlib)
    print('{:*^30}'.format("华丽的分割线"))
    sal = importlib.import_module('Salary')
    result = sal.monthSalry(10)
    print(result)
    print('{:*^30}'.format("华丽的分割线"))
    sal2 = importlib.reload(sal)

    print(sal2)

包 package

“包”就是一个必须有 __init__.py的文件

__init__.py 文件的作用:

  1. 作为包的标识,不能删除
  2. 是来实现模糊导入
  3. 导入包实质是执行 __init__.py 文件,可以在 __init__.py文件中这个包的初始化、以及需要统一执行代码

sys.path 和模块搜索路径

  1. 内置模块
  2. 当前目录
  3. 3程序的主目录
  4. pythonpath 目录
  5. 标准链接库目录
  6. 第三方库目录
  7. .pth 文件的内容
  8. sys.path.append() 临时添加的模块

模块发布和安装

模块的本地发布

setup.py 文件

位置在要对外发布模块的文件名或包的同级目录

from distutils.core import setup

setup(
    name='demo',  # 对外模块的名字
    version='1.0',
    description='发布测试',
    author='zwz',
    author_email='13@qq.com',
    py_modules=['demo.demo01', 'demo.demo02']  # 要发布的模块
)

构建一个发布文件.通过终端,cd 到模块文件夹 c 下面,再键入 命令:

python setup.py sdist

安装发布的模块

python setup.py install

上传模块到 PyPI

https://segmentfault.com/a/1190000012621842

# 方式1
python setup.py register  #然后输入用户名和密码

# 方式2 在用户家目录下创建  .pypirc 文件,文件内容为
[distutils]
index-servers=pypi

[pypi]
repository=https://upload.pypi.org/legacy
username = 账户名
password = 密码
上传并远程发布
python setup.py sdist upload
下载模块
pip install package-name

GUI编程

  • 开始
from tkinter import *
from tkinter import messagebox

注意:if __name__ == '__main__': ''' 导入的第三库与下面代码差两个空行'''

  • 通过类 Tk 的无参构造函数
root = Tk()
  • 在主窗口中,添加各种 Button 按钮
btn01 = Button(root)
btn01["text"] = "点我就送花"
  • 通过几何布局管理器,管理组件的大小和位置
btn01.pack()  # 垂直布局当前窗口大小
  • 事件处理
 def postflower(e):
        messagebox.showinfo("Message", "送你一朵玫瑰花,请你爱上我")
        print("我要送你九九朵玫瑰花")
### 事件绑定

表示鼠标左键单击

btn01.bind("<Button-1>", postflower)
root.mainloop()  # 调用组件的 mainloop 方法,进入事件循环

tkinter 主窗口

定义窗口的大小和位置
from tkinter import *
from tkinter import messagebox

if __name__ == '__main__':
    root = Tk()
    root.title("第一个 tkinter 的 gui 小程序")
    # root
    # .geometry('x轴(水平轴)x(小写英文字母x)y轴(垂直轴)+距离左边边框的距离+距离右边边框的距离')
    root.geometry('500x350+150+100')
    root.mainloop()

效果图

Button 组件继承结构图

组件整体结构图

常用组件

GUI 应用程序类的经典写法

通过类 Application 组织整个 GUI 程序,继承 Frame 类,作为容器

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.createWidget()  # 调用组件

    def createWidget(self):  # 创建组件
        self.btn01 = Button(self.__master)
        self.btn01["text"] = "点我送花"
        self.btn01.pack()  # 将当前组件添加到窗口中
        self.btn01["command"] = self.postToFlower

        # 创建退出按钮
        self.btnQuit = Button(self.__master, text="退出", command=root.destroy)
        self.btnQuit.pack()

    def postToFlower(self):
        messagebox.showinfo("送花", "我要送你 99 朵玫瑰花")


if __name__ == '__main__':
    root = Tk()
    root.title("GUI 应用程序经典写法,使用面向对象的方式")
    root.geometry('500x400+200+100')
    app = Application(master=root)
    root.mainloop()

Label 标签

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):  # 创建组件
        self.label01 = Label(self, text="我是标签"
                             , width=15, height=5, font=30
                             , justify="left"
                             , bg="black", fg="red")
        self.label01.pack()
        self.lable02 = Label(self, text="我是标签2", width=20, height=5
                             , font=("黑体", 15))
        self.lable02.pack()

        global photo  # 声明全局变量
        photo = PhotoImage(file="cute.gif")
        self.lable03 = Label(self, image=photo)
        self.lable03.pack()


if __name__ == '__main__':
    root = Tk()
    root.title("GUI 应用程序经典写法,使用面向对象的方式")
    root.geometry('500x400+200+100')
    app = Application(master=root)
    root.mainloop()

效果

Button 按钮

设置的按钮可以是文字或者图片,注意图片 必须是 .gif 格式

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        self.btn1 = Button(self, text="电脑", command=self.mycomputer)
        self.btn1.pack()

        global  photo
        photo = PhotoImage(file="cute.gif")
        self.btn2 = Button(self, image=photo, state=DISABLED, command=self.mycomputer)
        self.btn2.pack()


    def mycomputer(self):
        messagebox.showinfo("信息", "CPU:i5 8265u, RAM:16G, Hardware:1T")

if __name__ == '__main__':
    root = Tk()
    root.title("GUI 应用程序经典写法,使用面向对象的方式")
    root.geometry('500x400+200+100')
    app = Application(master=root)
    root.mainloop()

效果

Entry 单行文本框

Entry 用来一行字符串的控件,输入多行文本,使用 Test 控件

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        Label(self, text='用户名', height=2).pack()

        # 将 username 绑定 Entry 组件上
        username = StringVar(self)
        self.uEntry = Entry(self, textvariable=username)
        self.uEntry.pack()
        # username.set("admin")

        Label(self, text='密码', height=2).pack()
        password = StringVar(self)
        self.pEntry = Entry(self, textvariable=password, show="*")
        self.pEntry.pack()

        Button(self, text='登录', command=self.login).pack()

    def login(self):
        username = self.uEntry.get()
        password = self.pEntry.get()
        # 查询数据库,判断用户名是否正确
        if username == "admin" and password == "123":
            messagebox.showinfo('登录', '登录成功...')
        else:
            messagebox.showinfo('登录', '登录失败')

    def mycomputer(self):
        messagebox.showinfo("信息", "CPU:i5 8265u, RAM:16G, Hardware:1T")


if __name__ == '__main__':
    root = Tk()
    root.title("用户登录")
    root.geometry('200x200+200+100')
    app = Application(master=root)
    root.mainloop()

效果

接收 Entry 组件的 value

Text 组件

"""测试 Text 多行文本框组件的基本用法,使用面向对象的方式"""
from tkinter import *
import webbrowser


class Application(Frame):

    def __init__(self, master=None):
        super().__init__(master)  # super()代表的是父类的定义,而不是父类 对象
        self.master = master
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 宽度 20 个字母(10 个汉字),高度一个行高
        self.w1 = Text(root, width=40, height=12, bg="gray")
        self.w1.pack()
        self.w1.insert(1.0, "0123456789\nabcdefg")
        self.w1.insert(2.3, "锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦\n")
        Button(self, text="重复插入文本 ", command=self.insertText).pack(side="left")
        Button(self, text="返回文本", command=self.returnText).pack(side="left")
        Button(self, text="添加图片", command=self.addImage).pack(side="left")
        Button(self, text="添加组件", command=self.addWidget).pack(side="left")
        Button(self, text="通过 tag 精确控制文本 ", command=self.testTag).pack(side="left")

    def insertText(self):  # INSERT 索引表示在光标处插入
        self.w1.insert(INSERT, ' Gaoqi ')
        # END 索引号表示在最后插入
        self.w1.insert(END, '[sxt]')
        self.w1.insert(1.8, "gaoqi")

    def returnText(self):
        # Indexes(索引)是用来指向 Text 组件中文本的位置,Text 的组件索引也是对应 实际字符之间的位置。
        # 核心:行号以 1 开始 列号以 0 开始
        print(self.w1.get(1.2, 1.6))
        print("所有文本内容:\n" + self.w1.get(1.0, END))

    def addImage(self):
        # global photo
        self.photo = PhotoImage(file="imgs/logo.gif")
        self.w1.image_create(END, image=self.photo)

    def addWidget(self):
        b1 = Button(self.w1, text='爱尚学堂')
        # 在 text 创建组件的命令
        self.w1.window_create(INSERT, window=b1)

    def testTag(self):
        self.w1.delete(1.0, END)
        self.w1.insert(INSERT, "good good study,day day up!\n 北京尚学堂\n 百战 程序员\n 百度,搜一下就知道")
        self.w1.tag_add("good", 1.0, 1.9)
        self.w1.tag_config("good", background="yellow", foreground="red")
        self.w1.tag_add("baidu", 4.0, 4.2)
        self.w1.tag_config("baidu", underline=True)
        self.w1.tag_bind("baidu", "<Button-1>", self.webshow)

    def webshow(self, event):
        webbrowser.open("http://www.baidu.com")


if __name__ == '__main__':
    root = Tk()
    root.geometry("450x300+200+300")
    app = Application(master=root)
    root.mainloop()

Checkbox 复选框

# coding:utf-8

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        Label(self, text='复选框').pack(side='left')
        self.game_var = IntVar(self)
        self.code_var = IntVar(self)
        game_checkbox_radio = Checkbutton(self, text='打游戏'
                                          , variable=self.game_var
                                          , offvalue=1
                                          , onvalue=2
                                          , command=self.select_checkbox).pack(side='left')
        code_checkbox_radio = Checkbutton(self, text='敲代码'
                                          , variable=self.code_var
                                          , offvalue=1
                                          , onvalue=2
                                          , command=self.select_checkbox).pack(side='left')

    def select_checkbox(self):
        print(self.game_var.get(), self.code_var.get())


if __name__ == '__main__':
    root = Tk()
    root.title("单选和多选测试")
    root.geometry('300x200+200+100')
    app = Application(master=root)
    root.mainloop()

canvas 画布

canvas 画布是一个矩形区域, 可以方盒子图形、图形、组件等

# coding:utf-8

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        Label(self, text='画布学习', font=("宋体", 20)).pack()
        # 创建画布
        self.can = Canvas(self, bg='red', width=400, height=200)
        self.can.pack()
        # 画折线
        line = self.can.create_line(10, 10, 150, 150)
        # 画矩形
        ran = self.can.create_rectangle(20, 20, 200, 200)
        # 画圆
        ran = self.can.create_oval(20, 20, 200, 200)


if __name__ == '__main__':
    root = Tk()
    root.title("单选和多选测试")
    root.geometry('500x400+200+100')
    app = Application(master=root)
    root.mainloop()

布局管理器

pack、grid、place

grid 布局

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        Label(self, text='用户登录', height=3, font=("黑体", 18)).grid(row=0, columnspan=2)
        Label(self, text='用户名  ').grid(row=1, column=0, sticky=W)

        # 将 username 绑定 Entry 组件上
        self.username = StringVar(self)
        self.uEntry = Entry(self, textvariable=self.username)
        self.uEntry.grid(row=1, column=1)
        # username.set("admin")

        Label(self, text='密码', height=2).grid(row=2, column=0)
        self.password = StringVar(self)
        self.pEntry = Entry(self, textvariable=self.password, show="*")
        self.pEntry.grid(row=2, column=1)

        Button(self, text='登录', command=self.login).grid(row=3, column=0, sticky=S)
        Button(self, text='重置', command=self.reset).grid(row=3, column=1)

    def login(self):
        username = self.uEntry.get()
        password = self.pEntry.get()
        # 查询数据库,判断用户名是否正确
        if username == "admin" and password == "123":
            messagebox.showinfo('登录', '登录成功...')
        else:
            messagebox.showinfo('登录', '登录失败')

    def reset(self):
        self.username.set("")
        self.password.set("")


if __name__ == '__main__':
    root = Tk()
    root.title("用户登录")
    root.geometry('300x200+200+100')
    app = Application(master=root)
    root.mainloop()

效果

使用 Grid 布局实现计算器
'''
    计算器页面
'''

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        cal_key = (
            ('MC', 'M+', 'M-', 'MR'),
            ('C', '-', '+', 'x'),
            ('7', '8', '9', '-'),
            ('4', '5', '6', '+'),
            ('1', '2', '3', '='),
            ('0', '.')
        )
        Entry(self).grid(row=0, columnspan=4)

        for rindex, row in enumerate(cal_key):
            for cindex, c in enumerate(row):
                if c == '0':
                    Button(self, text=c, width=4).grid(row=rindex+1, column=cindex, columnspan=2, sticky=NSEW)
                elif c == '.':
                    Button(self, text=c, width=4).grid(row=rindex+1, column=cindex+1, sticky=NSEW)
                elif c == '=':
                    Button(self, text=c, width=4).grid(row=rindex+1, column=cindex, rowspan=2, sticky=NSEW)
                else:
                    Button(self, text=c, width=4).grid(row=rindex+1, column=cindex, sticky=NSEW)


if __name__ == '__main__':
    root = Tk()
    root.title("用户登录")
    root.geometry('300x200+200+100')
    app = Application(master=root)
    root.mainloop()

效果

pack 布局管理器

按照垂直或者水平的方向自然排 布。如果不指定任何选项,默认在父组件中自顶向下垂直添加组件。

'''
    测试
'''

from tkinter import *
from tkinter import messagebox

root = Tk()
root.title('pack')
root.geometry("500x200+900+300")
f1 = Frame(root)
f1.pack()
f2 = Frame(root)
f2.pack()

music_category = ('轻音乐', '重金属', '流行', '摇滚')

for category in music_category:
    Button(f1, text=category).pack(side='left', padx=10)

for index in range(1, 20):
    Label(f2, height=8, bg='black' if index % 2 == 0 else 'white').pack(side='left', ipadx=10)

# 启动
root.mainloop()

效果

place 坐标

place 布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。

# coding=utf-8
from tkinter import *

root = Tk();
root.geometry("500x300")
root.title("布局管理place");
root["bg"] = "white"

f1 = Frame(root, width=200, height=200, bg="green")
f1.place(x=30, y=30)

Button(root, text="尚学堂").place(relx=0.2, x=100, y=20, relwidth=0.2, relheight=0.5)
Button(f1, text="百战程序员").place(relx=0.6, rely=0.7)
Button(f1, text="高淇老师").place(relx=0.5, rely=0.2)
root.mainloop()

效果

事件处理

widget.bind(event,hander) # 将 事件绑定到函数上
鼠标和键盘事件

event 对象属性

测试
# coding=utf-8
# 测试键盘和鼠标事件

from tkinter import *

root = Tk();
root.geometry("530x300")

c1 = Canvas(root, width=200, height=200, bg="green")
c1.pack()


def mouseTest(event):
    print("鼠标左键单击位置(相对于父容器):{0},{1}".format(event.x, event.y))
    print("鼠标左键单击位置(相对于屏幕):{0},{1}".format(event.x_root, event.y_root))
    print("事件绑定的组件:{0}".format(event.widget))


def testDrag(event):
    c1.create_oval(event.x, event.y, event.x + 1, event.y + 1)


def keyboardTest(event):
    print("键的keycode:{0},键的char:{1},键的keysym:{2}"
          .format(event.keycode, event.char, event.keysym))


def press_a_test(event):
    print("press a")


def release_a_test(event):
    print("release a")


c1.bind("<Button-1>", mouseTest)
c1.bind("<B1-Motion>", testDrag)

root.bind("<KeyPress>", keyboardTest)
root.bind("<KeyPress-a>", press_a_test)  # 只针对小写的a,大写的A不管用
root.bind("<KeyRelease-a>", release_a_test)

root.mainloop()

事件传参

lambda 表达式的语法格式
lambda 参数值列表: 表达式

测试

root.bind("<Double-Button-1>",          
	lambda event: messagebox.showinfo("提示", "这是鼠标双击事件哦!"))
使用 lambda 表达式传参
# coding:utf-8

from tkinter import *

if __name__ == '__main__':
    root = Tk()
    root.geometry('500x400+300+400')
    root.title('lambda 表达式传参')

    f = Frame(root, width=400, height=200, bg='red')
    f.pack()


    def click_btn(a, b):
        print('a:{},b:{}'.format(a, b))


    Button(root, text='点击', 
    	command=lambda: click_btn('小黑', '小白')).place(x=280, y=100)

    root.mainloop()  # 开启主循环

事件汇总

  • 直接绑定

    # bind方式绑定事件
    b1.bind(触发事件, func)
    
  • 使用 command 绑定事件

    # command属性直接绑定事件
    b2 = Button(root,command=lambda: func)
    b2 = Button(root,command=func)
    
  • 使用 widget 绑定组件

    b1.bind_class(组件widget,触发事件event, func)
    
鼠标事件
鼠标事件类型说明
<Button-1>鼠标左击
<Button-2>鼠标中键
<Button-3>鼠标右击
测试
# coding=utf-8
# 多种事件绑定方式汇总
from tkinter import *

root = Tk();
root.geometry("270x30")


def mouseTest1(event):
    print("bind()方式绑定,可以获取event对象")
    print(event.widget)


def mouseTest2(a, b):
    print("a={0},b={1}".format(a, b))
    print("command方式绑定,不能直接获取event对象")


def mouseTest3(event):
    print("右键单击事件,绑定给所有按钮啦!!")
    print(event.widget)


b1 = Button(root, text="测试bind()绑定")
b1.pack(side="left")
# bind方式绑定事件
b1.bind("<Button-1>", mouseTest1)

# command属性直接绑定事件
b2 = Button(root, text="测试command2",
            command=lambda: mouseTest2("gaoqi", "xixi"))
b2.pack(side="left")

# 给所有Button按钮都绑定右键单击事件<Button-3>
b1.bind_class("Button", "<Button-3>", mouseTest3)

root.mainloop()

其他组件

OoptionMenu 选择框
from tkinter import *

if __name__ == '__main__':
    root = Tk()
    root.geometry('500x400+100+200')
    root.title('optionMenu')

    var = StringVar()
    var.set('请选择数字')
    om = OptionMenu(root, var, '1111', '2222', '33333')
    om.pack(side='left')

    Button(root, text='确定'
           , command=lambda: print('var:{}'.format(var.get()))).pack(side='left')

    root.mainloop()

效果

Scanle 滑块
from tkinter import *

if __name__ == '__main__':
    root = Tk()
    root.geometry('500x400+100+200')
    root.title('optionMenu')



    def test1(value):
        print('滑块的值:', value)
        newFont = ('宋体', value)
        lab.config(font=newFont)


    Scale(root, from_=10, to=50, length=200
          , tickinterval=5, orient=HORIZONTAL, command=test1).pack()

    lab = Label(root, text='凡事有因必有果', width=14, height=1, bg='yellow')
    lab.pack()

    root.mainloop()

效果

颜色选择框
"""askcolor颜色选择框的测试,改变背景色"""

from tkinter import *
from tkinter.colorchooser import *


if __name__ == '__main__':
    root = Tk();
    root.geometry("400x150")


    def test1():
        s1 = askcolor(color="red", title="选择背景色")
        print(s1)
        # s1的值是:((0.0, 0.0, 255.99609375), '#0000ff')
        root.config(bg=s1[1])


    Button(root, text="选择背景色", command=test1).pack()

    root.mainloop()

上传文件
"""文件对话框获取文件"""

from tkinter import *
from tkinter.filedialog import *

if __name__ == '__main__':
    root = Tk();
    root.geometry("400x100")


    def test1():
        f = askopenfilename(title="上传文件"
                            , initialdir="d:"
                            , filetypes=[
                                	("视频文件", ".mp4"), 
                                	("音频文件", ".mp3")])
        # print(f)
        show["text"] = f


    Button(root, text="选择编辑的视频文件或音频文件", command=test1).pack()

    show = Label(root, width=40, height=3, bg="green")
    show.pack()

    root.mainloop()

记事本程序

# coding=utf-8
# 记事本软件,练习主菜单的设计
from tkinter.colorchooser import askcolor
from tkinter.filedialog import *
from tkinter.simpledialog import askinteger

'''GUI 应用程序经典写法,使用面向对象的方式'''
from tkinter import *
from tkinter import messagebox


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.createWidget()  # 调用组件
        self.filename = ""

    def createWidget(self):
        '''创建组件'''

        # 创建主菜单栏
        menubar = Menu(self.master)

        # 创建子菜单
        menuFile = Menu(menubar)
        menuEdit = Menu(menubar)
        menuHelp = Menu(menubar)

        # 将子菜单加入到主菜单栏
        menubar.add_cascade(label="文件(F)", menu=menuFile)
        menubar.add_cascade(label="编辑(E)", menu=menuEdit)
        menubar.add_cascade(label="帮助(H)", menu=menuHelp)

        # 添加菜单项
        menuFile.add_command(label="新建", accelerator="ctrl+N", command=self.newfile)
        menuFile.add_command(label="打开", accelerator="ctrl+O", command=self.openfile)
        menuFile.add_command(label="保存", accelerator="ctrl+S", command=self.savefile)
        menuFile.add_separator()  # 添加分割线
        menuFile.add_command(label="退出", accelerator="ctrl+Q", command=self.exit)

        menuEdit.add_command(label='背景色', command=self.change_bg_color)
        menuEdit.add_command(label='字体', command=self.change_font_size)


        menuHelp.add_command(label='关于', command=self.aboutme)


        # 将主菜单栏加到根窗口
        root["menu"] = menubar

        # text 文本区域
        self.textpad = Text(self.master, width=150, height=100)
        self.textpad.pack()

        # 绑定快捷键
        root.bind('<Control-n>', lambda event: self.newfile())
        root.bind('<Control-o>', lambda event: self.openfile())
        root.bind('<Control-s>', lambda event: self.savefile())
        root.bind('<Control-q>', lambda event: self.exit())
        root.bind('<Button-3>', lambda event: self.show_right_click_menu(event))

        # 右击菜单
        self.right_click_menubar = Menu(self.master)
        self.right_click_menubar.add_command(label='背景色', command=self.change_bg_color)
        self.right_click_menubar.add_command(label='字体大小', command=self.change_font_size)


    # 新建文件
    def newfile(self):
        self.filename = asksaveasfilename(title='另存为'
                                          , filetypes=[('文本文件', '.txt')]
                                          , initialfile='未命名.txt'
                                          , defaultextension='.txt')
        self.savefile()

    # 打开文件
    def openfile(self):
        self.textpad.delete('1.0', 'end')  # 先把Text控件中的内容清空
        with askopenfile(title="打开文件", filetypes=[('文本文件', '.txt')]) as f:
            content = f.read()
            self.textpad.insert(INSERT, content)  # INSERT 表示从光标当前位置插入
            self.filename = f.name

    # 保存文件
    def savefile(self):
        if not self.filename.__eq__(None) or not self.filename == '':
            with open(self.filename, "w", encoding='utf-8') as f:
                content = self.textpad.get(1.0, END)
                if content == '':
                    messagebox.showinfo('警告', '请输入内容')
                else:
                    f.write(content)
        else:
            messagebox.showinfo('信息', '请先新建文件')

    # 退出
    def exit(self):
        self.master.quit()

    # 右击显示快捷菜单
    def show_right_click_menu(self, event):
        self.right_click_menubar.post(event.x_root, event.y_root)

    # 修改背景颜色
    def change_bg_color(self):
        s1 = askcolor(color="red", title="选择背景色")
        # s1 的值是:((0.0, 0.0, 255.99609375), '#0000ff')
        self.textpad.config(bg=s1[1])

    # 修改字体大小
    def change_font_size(self):
        font_size = askinteger(title='修改字体大小', prompt='修改字体大小'
                               , initialvalue=15, minvalue=5, maxvalue=60)
        print(font_size)
        self.textpad.config(font=font_size)

    # 关于我
    def aboutme(self):
        messagebox.showinfo('关于','本软件属于学习 Python 测试软件,软件难免有 Bug, 比如不能读取中文文件')


if __name__ == '__main__':
    root = Tk()
    root.title("我的记事本")
    root.geometry('600x400+200+100')
    app = Application(master=root)
    root.mainloop()

将 Python 打包成 exe 文件
# 下载 pyinstaller 库,打开 cmd 命令控制台,输入
pip install pyinstaller
# 使用 pyinstaller 打包
pyinstaller -F  xxx.py

画图软件

# coding=utf-8
'''编写简单的画图软件'''
from tkinter.colorchooser import askcolor
from tkinter.filedialog import *
from tkinter.simpledialog import askinteger
from tkinter import messagebox

# 定义全局的窗口的宽度
WIN_WIDTH = 900
# 定义全局的窗口的高度
WIN_HEIGHT = 500


class Application(Frame):  # 继承 Frame 类,用于创建容器

    def __init__(self, master=None, bgcolor='#000000'):  # master 的默认值为 None,即为空
        super().__init__(master)  # super() 表示父类的定义,不表示父类的对象
        self.__master = master
        self.pack()
        self.bgcolor = bgcolor

        self.x = 0  # (x,y) 表示画直线的起始坐标
        self.y = 0
        self.slinecolor = '#ff0000'  # 画笔颜色
        self.startDrawFlag = False
        self.lastdraw = 0  # 最后一次画直线的 对象 ID

        self.createWidget()  # 调用组件

    def createWidget(self):
        '''创建组件'''
        # 创建画布
        self.drawPad = Canvas(self, width=WIN_WIDTH, height=WIN_HEIGHT * 0.9, bg=self.bgcolor)
        self.drawPad.pack()

        start = Button(self, text='开始', name='start')
        start.pack(side='left', padx='10')
        pen = Button(self, text='画笔', name='pen')
        pen.pack(side='left', padx='10')
        rect = Button(self, text='矩形', name='rect')
        rect.pack(side='left', padx='10')
        clear = Button(self, text='清屏', name='clear')
        clear.pack(side='left', padx='10')
        eraser = Button(self, text='橡皮擦', name='eraser')
        eraser.pack(side='left', padx='10')
        straight_line = Button(self, text='直线', name='straight_line')
        straight_line.pack(side='left', padx='10')
        straight_line_head = Button(self, text='直线(箭头)', name='straight_line_head')
        straight_line_head.pack(side='left', padx='10')
        color = Button(self, text='颜色', name='color')
        color.pack(side='left', padx='10')
        fade_color = Button(self, text='渐变色', name='fade_color')
        fade_color.pack(side='left', padx='10')

        # 绑定事件
        pen.bind_class("Button", "<1>", self.eventManager)
        self.drawPad.bind("<ButtonRelease-1>", self.stopdraw)

        root.bind("<KeyPress-a>", self.about_me)
        root.bind("<KeyPress-r>", self.change_pen_red)
        root.bind("<KeyPress-y>", self.change_pen_yellow)
        root.bind("<KeyPress-b>", self.change_pen_blue)

    def eventManager(self, event):
        btn_name = event.widget.winfo_name()
        print(btn_name)
        if btn_name == 'straight_line':
            self.drawPad.bind("<B1-Motion>", self.straight_line)
        elif btn_name == 'straight_line_head':
            self.drawPad.bind("<B1-Motion>", self.straight_line_head)
        elif btn_name == 'rect':
            self.drawPad.bind("<B1-Motion>", self.rect)
        elif btn_name == 'pen':
            self.drawPad.bind("<B1-Motion>", self.pen)
        elif btn_name == 'eraser':
            self.drawPad.bind("<B1-Motion>", self.eraser)
        elif btn_name == 'color':
            s1 = askcolor(color="red", title="选择画笔颜色", initialcolor=self.slinecolor)
            # s1 的值是:((0.0, 0.0, 255.99609375), '#0000ff')
            self.slinecolor = s1[1]
        elif btn_name == 'clear':
            self.drawPad.delete("all")  # 清屏
        elif btn_name == 'fade_color':
            self.drawPad.bind("<B1-Motion>", self.fadepen)

    def start(self):
        pass

    # 画笔
    def pen(self, event):
        self.startdraw(event)
        #self.fade_color(event)
        self.drawPad.create_line(self.x, self.y, event.x, event.y, fill=self.slinecolor)
        self.x = event.x
        self.y = event.y

    # 矩形
    def rect(self, event):
        self.startdraw(event)
        self.lastdraw = self.drawPad.create_rectangle(self.x, self.y
                                                      , event.x, event.y
                                                      , outline=self.slinecolor)

    # 橡皮擦
    def eraser(self, event):
        self.startdraw(event)
        self.drawPad.create_rectangle(self.x - 3, self.y - 3
                                      , event.x + 3, event.y + 3
                                      , fill=self.bgcolor)

    # 画直线
    def straight_line(self, event):
        self.startdraw(event)
        self.lastdraw = self.drawPad.create_line(self.x, self.y
                                                 , event.x, event.y
                                                 , fill=self.slinecolor)

    # 画带有箭头的直线
    def straight_line_head(self, event):
        self.startdraw(event)
        self.lastdraw = \
            self.drawPad.create_line(self.x, self.y, event.x, event.y
                                     , arrow=LAST, fill=self.slinecolor)

    # 开始绘制
    def startdraw(self, event):
        self.drawPad.delete(self.lastdraw)

        if not self.startDrawFlag:
            self.startDrawFlag = True
            self.x = event.x
            self.y = event.y

    # 结束绘制
    def stopdraw(self, event):
        self.startDrawFlag = False
        self.lastdraw = 0

    # 关于我
    def about_me(self, event):
        messagebox.showinfo('信息', '本软件利用 Python 中 tkinter 库开发的简易画图软件,开发时间 2019年9月16日')

    # 快捷键 r,更换画笔颜色为红色
    def change_pen_red(self, event):
        self.slinecolor = 'red'

    # 快捷键 y,更换画笔颜色为黄色
    def change_pen_yellow(self, event):
        self.slinecolor = 'yellow'

    # 快捷键 b,更换画笔颜色为蓝色
    def change_pen_blue(self, event):
        self.slinecolor = 'blue'

    # 渐变画笔
    def fade_color(self, event):
        #self.slinecolor = (abs(self.x - event.x) % 256, abs(self.y - event.y) % 256, abs(self.x - event.x) % 256)
        self.slinecolor = '#ff00ff'


if __name__ == '__main__':
    root = Tk()
    root.title("我的记事本")
    root.geometry('{width}x{height}+200+100'.format(width=WIN_WIDTH, height=WIN_HEIGHT))
    app = Application(master=root)
    root.mainloop()

python 模块的安装

打开 cmd 命令控制台

pip install  xxx 模块名

# 这个 whl 文件需要自己手动到网上下载下来,然后执行下面的命令安装
pip install xxx.whl 文件

pip unstaill xxx 模块名

w(event)
self.drawPad.create_rectangle(self.x - 3, self.y - 3
, event.x + 3, event.y + 3
, fill=self.bgcolor)

# 画直线
def straight_line(self, event):
    self.startdraw(event)
    self.lastdraw = self.drawPad.create_line(self.x, self.y
                                             , event.x, event.y
                                             , fill=self.slinecolor)

# 画带有箭头的直线
def straight_line_head(self, event):
    self.startdraw(event)
    self.lastdraw = \
        self.drawPad.create_line(self.x, self.y, event.x, event.y
                                 , arrow=LAST, fill=self.slinecolor)

# 开始绘制
def startdraw(self, event):
    self.drawPad.delete(self.lastdraw)

    if not self.startDrawFlag:
        self.startDrawFlag = True
        self.x = event.x
        self.y = event.y

# 结束绘制
def stopdraw(self, event):
    self.startDrawFlag = False
    self.lastdraw = 0

# 关于我
def about_me(self, event):
    messagebox.showinfo('信息', '本软件利用 Python 中 tkinter 库开发的简易画图软件,开发时间 2019年9月16日')

# 快捷键 r,更换画笔颜色为红色
def change_pen_red(self, event):
    self.slinecolor = 'red'

# 快捷键 y,更换画笔颜色为黄色
def change_pen_yellow(self, event):
    self.slinecolor = 'yellow'

# 快捷键 b,更换画笔颜色为蓝色
def change_pen_blue(self, event):
    self.slinecolor = 'blue'

# 渐变画笔
def fade_color(self, event):
    #self.slinecolor = (abs(self.x - event.x) % 256, abs(self.y - event.y) % 256, abs(self.x - event.x) % 256)
    self.slinecolor = '#ff00ff'

if name == ‘main’:
root = Tk()
root.title(“我的记事本”)
root.geometry(’{width}x{height}+200+100’.format(width=WIN_WIDTH, height=WIN_HEIGHT))
app = Application(master=root)
root.mainloop()




#### python 模块的安装
> 打开 cmd 命令控制台
```console
pip install  xxx 模块名

# 这个 whl 文件需要自己手动到网上下载下来,然后执行下面的命令安装
pip install xxx.whl 文件

pip unstaill xxx 模块名

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值