Python Gui之tkinter(下)

news2024/9/22 11:31:58

 

6.Radiobutton单按按钮

Radiobutton控件用于选择同一组单选按钮中的一个。Radiobutton可以显示文本,也可以显示图像。

 

7.Checkbutton复选按钮

Checkbutton控件用于选择多个按钮的情况。Checkbutton可以显示文本,也可以显示图像。

'''经典的Gui类的写法,使用面向对象的方法'''

from tkinter import *
from tkinter import  messagebox

class Application(Frame):
    '''一个经典的Gui的类的写法'''

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

    def createWideget(self):
        '''创建组件'''
        self.codeHobby = IntVar();
        self.videoHobby = IntVar()

        print(self.codeHobby.get()) #默认值是0
        self.r1 = Checkbutton(root, text="敲代码", onvalue=1, variable=self.codeHobby, offvalue=0)
        self.r2 = Checkbutton(root, text="看视频", onvalue=1, variable=self.videoHobby, offvalue=0)

        self.r1.pack(side="left");self.r2.pack(side="left")

        Button(root, text="确定",command=self.confirm).pack(side="left")


    def confirm(self):
        # messagebox.showinfo("测试","选择性别:"+self.v.get())
        if self.videoHobby.get()==1:
            messagebox.showinfo("测试", "看视频,都是正常人有的爱好!你喜欢看什么类型?")
        if self.codeHobby.get() == 1:
            messagebox.showinfo("测试","抓到野生程序员一只")
        if self.videoHobby.get()==1 and self.codeHobby.get() == 1:
            messagebox.showinfo("测试","你真卷啊这都要卷")

if __name__ == '__main__':
    root = Tk()
    root.geometry("500x400+200+300")
    root.title("测试Radiobutton组件")
    app = Application(master=root)
    root.mainloop()

5.canvas画布

canvas(画布)是一个矩形区域,可以放置图形、图像、组件等。本节我们简单介绍canvas的使用,更加详细和深入的内容将在后面的“图形绘制”章节讲解。

'''经典的Gui类的写法,使用面向对象的方法'''
import random
from tkinter import *
from tkinter import  messagebox

class Application(Frame):
    '''一个经典的Gui的类的写法'''

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

    def createWideget(self):
        '''创建组件'''
        self.canvas = Canvas(self,width=300, height=200, bg="green")
        self.canvas.pack()
        #画一条直线
        line = self.canvas.create_line(10,10,30,20,40,50)
        #画一个矩形
        rect = self.canvas.create_rectangle(50,50,100,100)
        #画一个托全,坐标两双。为椭圆的边界矩形左上角和底部右下角
        oval = self.canvas.create_oval(50,50,100,100)

        global photo
        photo = PhotoImage(file="img/2.gif")
        self.canvas.create_image(150,170,image=photo)

        Button(self, text="画10个矩形", command=self.draw50Recg).pack(side="left")

    def draw50Recg(self):
        for i in range(0,10):
            x1 = random.randrange(int(self.canvas["width"])/2)
            y1 = random.randrange(int(self.canvas["height"]) / 2)
            x2 = x1 + random.randrange(int(self.canvas["width"]) / 2)
            y2 = y1 + random.randrange(int(self.canvas["height"]) / 2)
            self.canvas.create_rectangle(x1,y1,x2,y2)

if __name__ == '__main__':
    root = Tk()
    root.geometry("500x400+200+300")
    root.title("测试canvas")
    app = Application(master=root)
    root.mainloop()

6.布局管理器

一个GUI应用程序必然有大量的组件,这些组件如何排布?这时候,就需要使用tkinter提供的布局管理器帮助我们组织、管理在父组件中子组件的布局方式。tkinter提供了三种管理器:pack、grid、place

1.grid布局管理器

grid表格布局,采用表格结构组织组件。子组件的位置由行和列的单元格来确定,并且可以跨行和跨列,从而实现复杂的布局。

'''经典的Gui类的写法,使用面向对象的方法'''

from tkinter import *
from tkinter import  messagebox

class Application(Frame):
    '''一个经典的Gui的类的写法'''

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

    def createWideget(self):
        '''创建组件'''
        self.labe01 = Label(self, text="用户名")
        self.labe01.grid(row=0, column=0)
        self.entry01 = Entry(self)
        self.entry01.grid(row=0,column=1)
        Label(self,text="用户名为手机号").grid(row=0,column=2)

        Label(self, text="密码").grid(row=1, column=0)
        Entry(self, show="*").grid(row=1, column=1)

        Button(self, text="登录").grid(row=2, column=1, sticky=EW)
        Button(self, text="取消").grid(row=2, column=2, sticky=E)


if __name__ == '__main__':
    root = Tk()
    root.geometry("400x100+200+300")
    root.title("测试grid布局")
    app = Application(master=root)
    root.mainloop()

实现计算器软件界面

2.Pack布局管理器

pack按照组件的创建顺序将子组件添加到父组件中,按照垂直或者水平的方向自然排布。如果不指定任何选项,默认在父组件中自顶向下垂直添加组件。pack是代码量最少,最简单的一种,可以用于快速生成界面。

#coding = utf-8
#测试pack布局管理

from tkinter import *
root = Tk();root.geometry("700x220")

#Frame是一个矩形区域,就是用来放置其它子组件
f1 = Frame(root)
f1.pack()
f2 = Frame(root);f2.pack()

btnText = ("流行风","中国风","日本风","重金属","轻音乐")

for txt in btnText:
    Button(f1,text=txt).pack(side="left",padx="10")
    
for i in range(1,20):
    Label(f2,width=5,height=10,borderwidth=1,relief="solid",bg="black" if i%2==0 else "white").pack(side="left",padx=2)

root.mainloop()

3.place布局器

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

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.2,rely=0.7)
Button(f1,text="小余").place(relx=0.5,rely=0.2)
root.mainloop()

 

扑克牌游戏(自己添加图片)

'''扑克牌游戏的界面设计'''

from tkinter import  *

class Application(Frame):
    '''一个经典的Gui的类的写法'''

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

    def createWideget(self):
        '''通过place布局器实现扑克牌位置控制'''
        # self.photo = PhotoImage(file="")
        # self.puke1 = Label(self.master,image=self.photo)
        # self.pike1.place(x=10,y=50)
        self.photos = [PhotoImage(file=""+str(i+1)+".gif") for i in range(10)]
        self.pukes = [Label(self.master,image=self.photos[i]) for i in range(10)]

        for i in range(10):
            self.pukres[i].place(x=10+i*40,y=50)

        #为所有的Lable增加事件处理
        self.pikes[0].bind_class("Label","<Button-1>",self.chupai)

    def chupai(self,event):
        print(event.widget.winfo_geometry())
        print(event.widget.winfo_y())

        if event.widget.winfo_y() ==50:
            event.widget.place(y=30)
        else:
            event.widget.place(y=50)

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

7.事件处理

一个GUI应用整个生命周期都处在一个消息循环(eventloop)中。它等待事件的发生,并作出相应的处理。

Tkinter提供了用以处理相关事件的机制.处理函数可被绑定给各个控件的各种事件。widget.bind(event,handler)如果相关事件发生,handler函数会被触发,事件对象event会传递给handler函数.

 

#测试键盘和鼠标事件

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)
root.bind("<KeyRelease-a>",release_a_test)

root.mainloop()

 

1.lambda表达式

lambda表达式定义的是一个匿名函数,只适合简单输入参数,简单计算返回结果,不适合功能复杂情况。lambda定义的匿名函数也有输入、也有输出,只是没有名字。语法格式如下:lambda参数值列表:表达式参数值列表即为输入。表达式计算的结构即为输出。

我们写一个最简单的案例:add3args=lambdax,y,z:x+y+z#print(add3args(10,20,30))

上面的lambda表达式相当于如下函数定义:defadd3args(x,y,z):returnx+y+zlambda

表达式的参数值列表可以为如下内容:

我们在平时使用时,注意lambda只是一个匿名函数(没有名字的函数),功能不强,不要过度使用;

#测试command属性绑定事件,测试lambda表达式帮助传参

from tkinter import  *

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

def mouseTest1():
    print("command方式,简单情况:不涉及获取event对象,可以使用")

def mouserTest2(a,b):
    print("a={0},b={1}".format(a,b))

Button(root,text="测试command1",command=mouseTest1).pack(side="left")
Button(root,text="测试command2",command=lambda:mouserTest2("gaoqi","xixi")).pack(side="left")

root.mainloop()

 

2.多种事件绑定方式汇总

1.组件对象的绑定

1.通过command属性绑定(适合简单不需获取event对象)Button(root,text=”登录”,command=login)

2.通过bind()方法绑定(适合需要获取event对象)c1=Canvas();c1.bind(“<Button-1>”,drawLine)

2.组件类的绑定

调用对象的bind_class函数,将该组件类所有的组件绑定事件:w.bind_class(“Widget”,”event”,eventhanler)

比如:btn01.bind_class(“Button”,”<Button-1>”,func)

#多种事件绑定方法

from tkinter import *
root = Tk();root.geometry("270x30")


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

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

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


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


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

b2.pack(side="left")

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

root.mainloop()
 

 

8.其它组件

1.OptionMenu选择项

OptionMenu(选择项)用来做多选一,选中的项会在顶部显示。

基本用法:

#optionmenu的使用测试

from tkinter import *

root = Tk(); root.geometry("200x100")

v = StringVar(root)
v.set("信息收集模块")
om = OptionMenu(root, v, "子域名","IP","whois","端口","股权穿透")

om["width"] = 10
om.pack()

def test1():
    print("[+]开始收集............",v.get())
#v.set("IP“)   #直接修改了optionmenu中选中的值

Button(root, text="确定", command=test1).pack()
root.mainloop()
 

 

2.Scale移动滑块

Scale(移动滑块)用于在指定的数值区间,通过滑块的移动来选择值。

#使用Scale移动滑块的使用测试

from tkinter import *

root = Tk(); root.geometry("400x150")

def test1(value):
    print("滑块的值",value)
    newFont = ("宋体",value)

    a.config(font=newFont)

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

a= Label(root,text="字体放大器",width=10,height=1, bg="black", fg="white")
a.pack()

root.mainloop()

3.颜色选择框

颜色选择框可以帮助我们设置背景色、前景色、画笔颜色、字体颜色等等。

#askcolor颜色选择框测试

from tkinter import *
from tkinter.colorchooser import *

root = Tk(); root.geometry("400x150")

def test1():
    s1 =askcolor(color="red",title="选择背景色")

    root.config(bg=s1[1])

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

4.文件对话框

文件对话框帮助我们实现可视化的操作目录、操作文件。最后,将文件、目录的信息传入到程序中。文件对话框包含如下一些常用函数:

 

'''文件对话框获取文件名'''

from tkinter import  *
from tkinter.filedialog import *

root = Tk(); root.geometry("400x100")

def test1():
    f = askopenfile(title="上传文件",initialdir="C:/",filetypes=[("视频文件","mp4")])
    show["text"] = f

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

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

root.mainloop()

 

 

'''文件对话框获取文件名'''

from tkinter import  *
from tkinter.filedialog import *

root = Tk(); root.geometry("400x100")

def test1():
    with askopenfile(title="上传文件",initialdir="桌面",filetypes=[("文本文件",".txt")]) as f:
        show["text"] = f.read().encode("UTF-8")

Button(root,text="选择读取的文本文件",command=test1).pack()

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

root.mainloop()
 

 

5简单对话框

simpledialog(简单对话框)包含如下常用函数:

参数中,title表示窗口标题;prompt是提示信息;命名参数kw为各种选项:initialvalue(初始值)、minvalue(最小值)、maxvalue(最大值)。

'''简单对话框'''

from tkinter.simpledialog import *

root = Tk();root.geometry("400x100")

def test1():
    a = askstring(title="输入域名",prompt="请输入需要收集的主域名",initialvalue=18)  #minvalue=1,maxvalue=150
    #askstring,askfloat框使用方法一样
    show["text"]=a

Button(root,text="消息收集模块-----请输入目标",command=test1).pack()
show = Label(root,width=40, height=3, bg="green")
show.pack()
root.mainloop()

6.通用消息框

messagebox(通用消息框)用于和用户简单的交互,用户点击确定、取消。如下列出了messagebox的常见函数:

'''通用消息框'''

from  tkinter import *
from tkinter.messagebox import *

root = Tk();root.geometry("400x100")

a1 = showinfo(title="信息收集",message="[+]---------------")
print(a1)

root.mainloop()

7.ttk子控模块

我们再前面学的组件是tkinter模块下的组件,整体风格较老较丑。为了弥补这点不足,推出了ttk组件。ttk组件更加美观、功能更加强大。使用Combobox替代了原来的Listbox、新增了LabeledScale(带标签的Scale)、Notebook(多文档窗口)、Progressbar(进度条)、Treeview(数)等组件。使用ttk组件与使用普通的Tkinter组件并没有多大的区别,只要导入ttk模块即可。

ttk子模块的官方文档:https://docs.python.org/3.7/library/tkinter.ttk.html

9.菜单

GUI程序通常都有菜单,方便用户的交互。我们一般将菜单分为两种:1.主菜单主菜单通常位于GUI程序上方。例如:

1.主菜单主菜单通常位于GUI程序上方。例如:

'''设计功能菜单那'''

from tkinter import *
from tkinter.messagebox import *
from tkinter.filedialog import *

root = Tk(); root.geometry("400x400")

#创建主菜单栏
menubar = Menu(root)

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

#将子菜单加入到主菜单栏
menubar.add_cascade(label="信息收集模块",menu=menuFile)
menubar.add_cascade(label="渗透模块",menu=menuEile)
menubar.add_cascade(label="内网模块",menu=menuHelp)

filename=""

def openFile():
    global  filename
    with askopenfile(title="打开文件") as f:
        content = f.read()
        w1.insert(INSERT,content)
        filename = f.name
        print(f.name)

def saveFile():
    with open(filename,"w") as f:
        content = w1.get(1.0,END)
        f.write(content)

def exit():
    root.quit()

#添加菜单项
menuFile.add_command(label="打开",accelerator="^O",command=openFile)
menuFile.add_command(label="保存",command=saveFile)
#添加分割线
menuFile.add_separator()
menuFile.add_command(label="退出",command=exit)

#将主菜单加到根窗口
root["menu"] = menubar
w1 = Text(root,width=50,height=30)
w1.pack()

root.mainloop()
 

2.快捷菜单(上下文菜单)通过鼠标右键单击某个组件对象而弹出的菜单,一般是与该组件相关的操作。

比如:剪切、复制、粘贴、属性等。创建快捷菜单步骤如下:

1.创建菜单menubar=tk.Menu(root)menubar.add_command(label=”字体”)

2.绑定鼠标右键单击事件deftest(event):menubar.post(event.x_root,event.y_root)#在鼠标右键单击坐标处显示菜单root.bind(“<Button-3>”,test)

"""开发记事本软件的菜单
"""

from tkinter.filedialog import *
from tkinter.colorchooser import *


class Application(Frame):

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

    def createWidget(self):
        # 创建主菜单栏
        menubar = Menu(root)

        # 创建子菜单
        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)

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

        # 增加快捷键的处理
        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())

        #文本编辑区
        self.textpad = Text(root, width=50, height=30)
        self.textpad.pack()

        # 创建上下菜单
        self.contextMenu = Menu(root)
        self.contextMenu.add_command(label="背景颜色", command=self.openAskColor)

        #为右键绑定事件
        root.bind("<Button-3>",self.createContextMenu)

    def newfile(self):
        self.textpad.delete("1.0", "end")  # 把text控件中所有的内容清空
        self.filename= asksaveasfilename(title="另存为",initialfile="未命名.txt",
                          filetypes=[("文本文档","*.txt")],
                          defaultextension=".txt")
        self.savefile()

    def openfile(self):
        self.textpad.delete("1.0","end")        # 把text控件中所有的内容清空
        with askopenfile(title="打开文本文件") as f:
            self.textpad.insert(INSERT,f.read())
            self.filename = f.name

    def savefile(self):
        with open(self.filename,"w") as f:
            c = self.textpad.get(1.0,END)
            f.write(c)

    def exit(self):
        root.quit()

    def openAskColor(self):
        s1 = askcolor(color="red",title="选择背景色")
        self.textpad.config(bg=s1[1])
    def createContextMenu(self,event):
        # 菜单在鼠标右键单击的坐标处显示
        self.contextMenu.post(event.x_root, event.y_root)


if __name__ == '__main__':
    root = Tk()
    root.geometry("450x300+200+300")
    root.title("Darling的简易记事本")
    app = Application(master=root)
    root.mainloop()

10.将python模块打包成exe

我们可以使用pyinstaller 模块实现将 python项目打包成exe文件。操作步骤如下:

1.安装pyinstaller模块

在pycharm 中操作:file-->setting-->Project: xx -->project interpretor,再点击+即可。

 

2.在pycharm的Terminal 终端输入如下命令:

pyinstaller -F  xxx.py

【注】相关参数如下:

--icon=图标路径(pyinstaller -F --icon=my.ico XxXX.py)

-F打包成一个exe文件

-w使用窗口,无控制台

-c使用控制台,无窗口

-D创建一个目录,里面包含exe 以及其他一些依赖性文件

3.在项目的dist目录下可以看到生成了exe文件,直接在windows系统中使用即司。

"""开发画图软件的菜单
"""

from tkinter.filedialog import *
from tkinter.colorchooser import *

#窗口的宽度和高度
win_width=900
win_height=450


class Application(Frame):

    def __init__(self, master=None,bgcolor="#000000"):
        super().__init__(master)        # super()代表的是父类的定义,而不是父类对象
        self.master = master
        self.bgcolor=bgcolor
        self.x = 0
        self.y = 0
        self.fgcolor = "#ff0000"
        self.lastDraw = 0               # 表示最后绘制的图形的id
        self.startDrawFlag = False
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 创建绘图区
        self.drawpad = Canvas(root,width=win_width,height=win_height*0.9,bg=self.bgcolor)
        self.drawpad.pack()

        #创建按钮
        btn_start = Button(root,text="开始",name="start")
        btn_start.pack(side="left",padx="10")
        btn_pen = Button(root,text="画笔",name="pen")
        btn_pen.pack(side="left",padx="10")
        btn_rect = Button(root,text="矩形",name="rect")
        btn_rect.pack(side="left",padx="10")
        btn_clear = Button(root,text="清屏",name="clear")
        btn_clear.pack(side="left",padx="10")
        btn_erasor = Button(root,text="橡皮擦",name="erasor")
        btn_erasor.pack(side="left",padx="10")
        btn_line = Button(root,text="直线",name="line")
        btn_line.pack(side="left",padx="10")
        btn_lineArrow = Button(root,text="箭头直线",name="lineArrow")
        btn_lineArrow.pack(side="left",padx="10")
        btn_color = Button(root,text="颜色",name="color")
        btn_color.pack(side="left",padx="10")

        #事件处理
        btn_pen.bind_class("Button","<1>",self.eventManager)
        self.drawpad.bind("<ButtonRelease-1>",self.stopDraw)

        #增加颜色切换的快捷键
        root.bind("<KeyPress-r>",self.kuaijiejian)
        root.bind("<KeyPress-g>",self.kuaijiejian)
        root.bind("<KeyPress-y>",self.kuaijiejian)

    def eventManager(self,event):
        name = event.widget.winfo_name()
        print(name)
        if name=="line":
            self.drawpad.bind("<B1-Motion>",self.myline)
        elif name=="lineArrow":
            self.drawpad.bind("<B1-Motion>",self.mylineArrow)
        elif name=="rect":
            self.drawpad.bind("<B1-Motion>",self.myRect)
        elif name=="pen":
            self.drawpad.bind("<B1-Motion>",self.myPen)
        elif name=="erasor":
            self.drawpad.bind("<B1-Motion>",self.myErasor)
        elif name=="clear":
            self.drawpad.delete("all")
        elif name=="color":
            c = askcolor(color=self.fgcolor,title="选择画笔颜色")
            #[(255,0,0),"#ff0000"]
            self.fgcolor = c[1]
    def stopDraw(self,event):
        self.startDrawFlag = False
        self.lastDraw = 0

    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 myline(self,event):
        self.startDraw(event)
        self.lastDraw = self.drawpad.create_line(self.x,self.y,event.x,event.y,fill=self.fgcolor)

    def mylineArrow(self,event):
        self.startDraw(event)
        self.lastDraw = self.drawpad.create_line(self.x,self.y,event.x,event.y,arrow=LAST,fill=self.fgcolor)

    def myRect(self,event):
        self.startDraw(event)
        self.lastDraw = self.drawpad.create_rectangle(self.x,self.y,event.x,event.y,outline=self.fgcolor)

    def myPen(self,event):
        self.startDraw(event)
        self.drawpad.create_line(self.x,self.y,event.x,event.y,fill=self.fgcolor)
        self.x = event.x
        self.y = event.y

    def myErasor(self,event):
        self.startDraw(event)
        self.drawpad.create_rectangle(event.x-4,event.y-4,event.x+4,event.y+4,fill=self.bgcolor)
        self.x = event.x
        self.y = event.y

    def kuaijiejian(self,event):
        if event.char =="r":
            self.fgcolor = "#ff0000"
        elif event.char =="g":
            self.fgcolor = "#00ff00"
        elif event.char =="y":
            self.fgcolor = "#ffff00"

if __name__ == '__main__':
    root = Tk()
    root.geometry(str(win_width)+"x"+str(win_height)+"+200+300")
    root.title("Darling的画图软件")
    app = Application(master=root)
    root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/61397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于liunx 宝塔运行php项目

文章目录前言一、申请liunx服务器安装宝塔环境二、安装php看你自己安装需要的版本三.php文件创建四.数据库创建五.访问项目就可以了前言 自己研究学习&#xff0c;大佬勿喷 一、申请liunx服务器安装宝塔环境 我是线上安装的都一样看个人习惯爱好吧 等待安装完成提示地址和账…

Java基础—重新抛出异常

重新抛出异常 在catch块内处理完后&#xff0c;可以重新抛出异常&#xff0c;异常可以是原来的&#xff0c;也可以是新建的&#xff0c;如下所示&#xff1a; try{ //可能触发异常的代码 }catch(NumberFormatException e){ System.out.println("not valid numbe…

电子印章结构以及规范讲解

前言 为了确保电子印章的完整性、不可伪造性&#xff0c;以及合法用户才能使用&#xff0c;需要定义一个安全的电子印章数据格式&#xff0c;通过数字签名&#xff0c;将印章图像数据与签章者等印章属性进行安全绑定&#xff0c;形成安全电子印章 电子印章&#xff1a;一种由…

MVVM与Vue响应式的实现

Vue的响应式实现原理 MVVM M&#xff1a;模型 》data中的数据 V&#xff1a;视图 》模板 VM&#xff1a;视图模型 》Vue实例对象 ViewModel是一个中间的桥梁将视图View与模型Model连接起来&#xff0c;ViewModel内部通过数据绑定&#xff0c;实现数据变化&#xff0c;视图发…

链接装载(一)虚拟地址与物理地址

文章目录一、基本概念二、一个基本问题三、程序的执行四、从堆中分配的数据的逻辑地址一、基本概念 当我们写出一个程序&#xff0c;即便是最基本的 Hello World&#xff0c;都需要经过 预处理、编译、汇编、链接才能生成最终的可执行文件。 预处理&#xff1a; 预处理过程主…

spring ioc的循环依赖问题

spring ioc的循环依赖问题什么是循环依赖spring中循环依赖的场景通过构造函数注入时的循环依赖通过setter或Autowired注入时的循环依赖循环依赖的处理机制原型bean循环依赖单例bean通过构造函数注入循环依赖单例bean通过setter或者Autowired注入的循环依赖三级缓存对象的创建分…

Metasploit 操作及内网 Pivot图文教程

目录 一、metasploit 简介 二、 基本使用 三、 使用 encoders 四、pivot 技术 一、metasploit 简介 Metasploit 是一款开源的安全漏洞检测工具&#xff0c;集成了丰富的渗透测试工具&#xff0c;深受安 全工作者喜爱。官方网站&#xff1a;www.metasploit.com 本案例将以图…

OS-调度

调度 多个程序在并发的情况下执行&#xff0c;最大化CPU利用率&#xff0c;同时要保证一定的公平性 调度的时机 五种情况&#xff1a; Running -> Waiting&#xff1a;例如等待I/ORunning -> Ready: interupt&#xff0c;计时器到时间了Running -> TerminatedWait…

我把Idea给改了,看看有没有你常用的功能,没有,你告诉我,我来改

改造的目标 时隔2个多月的研发&#xff0c;11月25日&#xff0c;终于把Idea插件BG-BOOM的1.1.0版本搞上线了&#xff0c;本次更新勇哥也是百忙之中挤时间&#xff0c;加班加点开发为粉丝&#xff0c;目的也主要是帮助大家提升开发效率&#xff0c;有更多摸鱼和内卷时间&#x…

[附源码]Python计算机毕业设计SSM晋中学院教室管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

QT中怎么设置定时器/周期任务/定时触发任务

Qt中定时器的使用有两种方法&#xff0c;一种是使用QObject类提供的定时器&#xff0c;还有一种就是使用QTimer类。 其精确度一般依赖于操作系统和硬件&#xff0c;但一般支持20ms。下面将分别介绍两种方法来使用定时器。 QObject类提供的定时器 QObject中的定时器的使用&am…

Makefile 详解

文章目录1.什么是Makefile2.Makefile文件命名规则3.编写Makefile4.Makefile 的工作原理5.Makefile中的变量6.模式匹配7.函数1.什么是Makefile 一个工程中的源文件不计其数&#xff0c;按期类型、功能、模块分别放在若干个文件中&#xff0c;MakeFile文件定义了一系列的规则来制…

HIN应用调研总结

文章目录1. 代码安全iDev: enhancing social coding security by cross-platform user identification between GitHub and stack overflow【A】2. API推荐Group preference based API recommendation via heterogeneous information network【A】3.Andorid恶意软件检测Out-of-…

SSM甜品店系统计算机毕业论文java毕业设计选题源代码

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之SSM甜品店系统-IT实战营_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzygogogo.com/i…

中英双语多语言外贸企业网站源码系统 - HanCMS - 安装部署教程

随着跨境独立站的流行&#xff0c;中英双语的公司官网越来越受到重视。 此项目是基于开源CMS开发出的中英文双语外贸企业网站内容管理系统&#xff0c;命名HanCMS HanCMS 汉CMS中英双语多语种外贸网站系统&#xff0c;是一个轻量级的网站系统&#xff0c;访问速度极快&#xff…

[附源码]计算机毕业设计小太阳幼儿园学生管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

威伦触摸屏TK6060IP简单例子

详情见以下链接 https://download.csdn.net/download/weixin_39926429/87242438

[附源码]Python计算机毕业设计SSM教务管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

基于连续小波变换的厄尔尼诺海平面周期变化数据集分析

基于连续小波变换的厄尔尼诺海平面周期变化数据集分析1. 厄尔尼诺海平面周期变化数据集介绍2. 基于连续小波变换的信号分析2.1 原始信号读取可视化2.2 傅里叶变换结果可视化2.3 小波变换结果可视化参考资料后记1. 厄尔尼诺海平面周期变化数据集介绍 这些数据是通过国际热带海洋…

文件上传的multipart/form-data属性,你理解了吗

form表单经常用于前端发送请求&#xff0c;比如&#xff1a;用户填写信息、选择数据、上传文件&#xff0c;对于不同的场景&#xff0c;上传数据的格式也会有些区别。 action action 表示该请求的 url 地址&#xff0c;定义在form上&#xff0c;请求的URI&#xff0c;可以写完…