CGY-OS 正式开源!【软件编写篇】

news2024/9/20 8:56:35

上一篇文章:CGY-OS 正式开源!_cgy091107的博客-CSDN博客

一、软件编写基础要求

        在编写CGY-OS的应用程序之前,您需要:

                1. 安装python3.10,配置好CGY-OS。

                2.掌握python3的基本语法、lambda表达式、各种简单的数据结构。

                3.对python的tkinter库有基本的了解,并使用它编写过简单的应用程序。

                4.仔细阅读过上一篇文章。(这很重要!否则后文的传参将让您头疼)

        如果您认为您满足此要求,请继续向下翻看。

二、配置CGY-OS

        以后再说。u

三、编写第一个“ULoop”程序:numAdder

        3.1 “ULoop”和“Loop”:

                由于CGY-OS 的GUI控件中,大多(如Button、Entry)都有command参数,所以在处理一些简单的任务(如按下按钮执行一个函数)时,无需一个一直在后台执行的进程处理这些任务,所以我们不需要在应用程序里编写一个类似于cos的oneloop的函数(关于cos.oneloop,参见上一篇文章),这种程序,被称为“ULoop”。

                反之,在处理一些复杂的、不能中断的任务(如计时器、游戏)时,我们在程序里必须设置一个在后台一直执行的函数(def run():),这种程序被称为“Loop”。

        3.2 编写程序

                其实在上一篇文章的2.1中,已经带领大家编写过了一个“ULoop"程序。所以,框架在此不再解释。

                在cos\apps新建文件,命名为“numAdder.py”,输入基础框架,并在cos\apps\__init__.py第一行末尾追加“numAdder”(详见见上一篇文章的2.1)。

from apilib import *
from classes import *
import cos


# 导入包

def cosmain():  # 主函数
    screen = cos.window  # 绑定显示器
    root = Tk(screen, 10, 105, 350, 450, "Basic")  # 创建窗口
    api_hook(root, 'Basic')  # 绑定窗口

                在cos应用程序编写中,最稳妥的方式是先添加控件,再调整root的大小(root的大小基本总是不合适的)。我们现在来添加一个文本框:

def cosmain():  
    screen = cos.window 
    root = Tk(screen, 10, 105, 350, 450, "Basic") 
    entry = Entry(screen, root, 5, 5, 70) #这里
    entry.pack() #这里
    api_hook(root, 'Basic')

                运行一下(如果您无法运行,请检查cos\apps\__init__.py的第一行的import语句是否包含numAdder、您的文件名称和App_starter中的输入,如果您问我如何在App_starter的文本框内输入,那么请仔细查看上一篇文章,如果还是输入不了,请换Windows+python3.10+高配置并重试几遍),结果如图:

                很好!接下来 我们在添加一个“+”(使用Label)和另一个文本框。

def cosmain():
    screen = cos.window
    root = Tk(screen, 10, 105, 350, 450, "Basic") 
    entry = Entry(screen, root, 5, 5, 70)
    entry.pack()
    Label(screen, root, "+", 83, 5, bg=None).pack() #从这里
    entry2 = Entry(screen, root, 100, 5, 70)
    entry2.pack()                                   #到这里
    api_hook(root, 'Basic')

                对于像“+”这样既不获取其值,又不对其加以改变的控件,我们可以不使用变量,直接调用其pack方法(学过tkinter的都懂)。运行结果如图:

                 在创建一个calc函数(函数体为空)和一个按钮、一个状态栏(就是label),并将calc绑定到按钮和文本框中。

def cosmain():
    def calc(): #这里
        pass

    screen = cos.window
    root = Tk(screen, 10, 105, 350, 450, "Basic")
    entry = Entry(screen, root, 5, 5, 70, command=calc)#这里
    entry.pack()
    Label(screen, root, "+", 83, 5, bg=None).pack()
    entry2 = Entry(screen, root, 100, 5, 70, command=calc)#这里
    entry2.pack()
    Button(screen, root, "Calc", 175, 5, 45, command=calc).pack()#从这里
    label = Label(screen, root, "Welcome!", 5, 35, bg=None)
    label.pack()                                                 #到这里
    api_hook(root, 'Basic')

                接下来可以更改窗口了。

from apilib import *
from classes import *
import cos


def cosmain():
    def calc():
        pass

    screen = cos.window
    root = Tk(screen, 10, 105, 230, 55, "numAdder") #这里
    entry = Entry(screen, root, 5, 5, 70, command=calc)
    entry.pack()
    Label(screen, root, "+", 83, 5, bg=None).pack()
    entry2 = Entry(screen, root, 100, 5, 70, command=calc)
    entry2.pack()
    Button(screen, root, "Calc", 175, 5, 45, command=calc).pack()
    label = Label(screen, root, "Welcome!", 5, 35, bg=None)
    label.pack()
    api_hook(root, 'numAdder') #这里

                至此,UI界面编写完成。运行结果:

                接下来编写运算函数,先获取两数的值并相加、显示:

    def calc():
        num1 = int(entry.get())
        num2 = int(entry2.get())
        ans = num1 + num2
        label.config(text=f"{num1}+{num2}={ans}", fg=blue) #使用蓝色显示答案

                再运行一下:

                很好,没有问题,但是当我们输入非数字时…… 

                 

                cos崩溃了。 我们必须避免这种问题,解决方案当然是try...except...语句。

    def calc():
        try:
            num1 = int(entry.get())
            num2 = int(entry2.get())
        except ValueError:
            label.config(text="Must be a number.", fg=red)
        else:
            ans = num1 + num2
            label.config(text=f"{num1}+{num2}={ans}", fg=blue)  # 使用蓝色显示答案

                 再试一次,就没有问题了!

         3.3 Label.maxlenth 体验 & 程序优化

                当我们输入的数过长时,label的显示会出现问题:

                 接下来让我们解决这种问题。

                 方法1:长度限制:因为Entry没有maxlenth之类的参数(当然以后会有),所以我们只能在程序中限制:

    def calc():
        try:
            num1 = int(entry.get())
            num2 = int(entry2.get())
        except ValueError:
            label.config(text="Must be a number.", fg=red)
        else:
            if len(entry.get()) > 10 or len(entry2.get()) > 10:
                label.config(text="Number's length mustn't bigger than 10.", fg=red)
            else:
                ans = num1 + num2
                label.config(text=f"{num1}+{num2}={ans}", fg=blue)  # 使用蓝色显示答案

                运行结果:

                好吧,这样也超了,所以我们才需要第二种方案:

                方法2:更改cosmain中的这一行代码,然后查看结果:


def cosmain():
    def calc():
        try:
            num1 = int(entry.get())
            num2 = int(entry2.get())
        except ValueError:
            label.config(text="Must be a number.", fg=red)
        else:
            if len(entry.get()) > 10 or len(entry2.get()) > 10:
                label.config(text="Number's length mustn't bigger than 10.", fg=red)
            else:
                ans = num1 + num2
                label.config(text=f"{num1}+{num2}={ans}", fg=blue)  # 使用蓝色显示答案

    screen = cos.window
    root = Tk(screen, 10, 105, 230, 80, "numAdder")##这里!(80原来是55)
    entry = Entry(screen, root, 5, 5, 70, command=calc)
    entry.pack()
    Label(screen, root, "+", 83, 5, bg=None).pack()
    entry2 = Entry(screen, root, 100, 5, 70, command=calc)
    entry2.pack()
    Button(screen, root, "Calc", 175, 5, 45, command=calc).pack()
######################################################这里!!!
    label = Label(screen, root, "Welcome!", 5, 35, bg=None, maxlength=20) #这里!
    label.pack()
    api_hook(root, 'numAdder')

                 再次运行呢?

                 我们看到它自动换行了。这是Label的高级功能。

         3.4 恭喜!

                恭喜!!!您已经成功的做出了一个安全的、完整的、实用的CGY-OS应用程序了!

                附上源代码:

from apilib import *
from classes import *
import cos


def cosmain():
    def calc():
        try:
            num1 = int(entry.get())
            num2 = int(entry2.get())
        except ValueError:
            label.config(text="Must be a number.", fg=red)
        else:
            if len(entry.get()) > 10 or len(entry2.get()) > 10:
                label.config(text="Number's length mustn't bigger than 10.", fg=red)
            else:
                ans = num1 + num2
                label.config(text=f"{num1}+{num2}={ans}", fg=blue)

    screen = cos.window
    root = Tk(screen, 10, 105, 230, 80, "numAdder")
    entry = Entry(screen, root, 5, 5, 70, command=calc)
    entry.pack()
    Label(screen, root, "+", 83, 5, bg=None).pack()
    entry2 = Entry(screen, root, 100, 5, 70, command=calc)
    entry2.pack()
    Button(screen, root, "Calc", 175, 5, 45, command=calc).pack()
    label = Label(screen, root, "Welcome!", 5, 35, bg=None, maxlength=20)
    label.pack()
    api_hook(root, 'numAdder')

四、编写第一个"Loop"应用程序

        4.1 概述

                在本程序中,我们要通过canvas控件创建一个动画,动画中,我们每隔0.1秒刷新一次(具体画什么后面自知)。

        4.2 编写程序框架

                新建文件animation.py(animation为“动画”的英文),输入应用程序框架,并在cos\apps\__init__.py第一行结尾追加,运行无误后进行下一步。

                为了在后台运行我们的进程,我们在cosmain中添加一个run函数,并用root.add_unapply_hook来添加它(之所以用add_unapply_hook,是为了在root隐藏时可以继续运行run函数,虽然本示例用不到它,但是这是一个好的习惯)。

def cosmain():
    def run():
        pass

    screen = cos.window
    root = Tk(screen, 10, 105, 350, 450, "Basic")
    root.add_unapply_hook(run)
    api_hook(root, 'Basic')

       重点:run函数要写成oneloop的形式,也就是说它的函数体不是循环,而是循环内的所有代码。

        4.3 计时器

                计时器类来自cpu.py的Time类,它被apilib间接导入到应用程序中。

                我们使用一个程序(直接该animation.py源代码)来说明这个类,这个程序显示一个Label,它从0开始,每一秒增加1.

from apilib import *
from classes import *
import cos


def cosmain():
    def run():
        nonlocal i  # nonlocal:问你的python老师去
        if (not timer.is_sleeping()  # 如果上一次计时结束
                or timer.sec == 0):  # 或者刚刚开始
            timer.sleep(1)  # 计时1秒
            i += 1
            label.config(text=f"{i}")  # 更新

    screen = cos.window
    root = Tk(screen, 10, 105, 55, 30, "Time")
    timer = Time()
    i = 0
    label = Label(screen, root, f"{i}", 5, 5, bg=None)
    label.pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Time')

                运行结果:

         4.4 编写程序

                我们先把4.3的文件删掉,换成4.2的框架。

                我们的GUI编写非常简单,只需要添加一个canvas并改变窗口就可以了。

from apilib import *
from classes import *
import cos


def cosmain():
    def run():
        pass

    screen = cos.window
    root = Tk(screen, 10, 105, 200, 200, "Animation")
    canvas = Canvas(screen, root, 0, 0, 200, 200)
    canvas.pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Animation')

 

                我们再来添加一个画方块的函数box,并添加一个测试用的按钮来调用它

from apilib import *
from classes import *
import cos
import random


def cosmain():
    def box(i):
        pen = canvas.rect(100 - i * 5, 100 - i * 5, i * 10, i * 10,
                          (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
        pens.append(pen)

    def run():
        pass

    pens = []
    screen = cos.window
    root = Tk(screen, 10, 105, 200, 200, "Animation")
    canvas = Canvas(screen, root, 0, 0, 200, 200)
    canvas.pack()
    Button(screen, root, "test", 5, 5, 45, lambda: box(15)).pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Animation')

                点击按钮,屏幕上出现了一个颜色随机的正方形。

                接下来,我们删除button,参考4.3中的内容,使run函数每隔0.5秒执行一次(i先传参15):

def cosmain():
    def box(i):
        pen = canvas.rect(100 - i * 5, 100 - i * 5, i * 10, i * 10,
                          (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
        pens.append(pen)

    def run():
        if not timer.is_sleeping() or timer.sec==0:
            timer.sleep(0.5)
            box(15)

    pens = []
    screen = cos.window
    root = Tk(screen, 10, 105, 200, 200, "Animation")
    timer = Time()
    canvas = Canvas(screen, root, 0, 0, 200, 200)
    canvas.pack()
    # Button(screen, root, "test", 5, 5, 45, lambda: box(15)).pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Animation')

                我们在增加一个i变量,从20开始,每0.5秒减少1,直到为0为止。

from apilib import *
from classes import *
import cos
import random


def cosmain():
    def box(i):
        pen = canvas.rect(100 - i * 5, 100 - i * 5, i * 10, i * 10,
                          (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
        pens.append(pen)

    def run():
        nonlocal i
        if not timer.is_sleeping() or timer.sec == 0:
            timer.sleep(0.5)
            if i != 0: 
                box(i)
                i -= 1

    pens = []
    i = 20
    screen = cos.window
    root = Tk(screen, 10, 105, 200, 200, "Animation")
    timer = Time()
    canvas = Canvas(screen, root, 0, 0, 200, 200)
    canvas.pack()
    # Button(screen, root, "test", 5, 5, 45, lambda: box(15)).pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Animation')

        运行结果:

         接下来,我们增加一个功能:在i=0(结束绘图)是将所有正方形从外到内删除,直到画布为空白。

def cosmain():
    def box(i):
        pen = canvas.rect(100 - i * 5, 100 - i * 5, i * 10, i * 10,
                          (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
        pens.append(pen)

    def run():
        nonlocal i, flag
        if not timer.is_sleeping() or timer.sec == 0:
            timer.sleep(0.5)
            if not flag:  # 没有停止过
                if i != 0:
                    box(i)
                    i -= 1
                else:
                    flag = True
            else:
                if len(pens) != 0:  # 如果还有绘图句柄:
                    canvas.remove_pen(pens[0])
                    pens.pop(0)  # 删除第一个元素

    pens = []
    i = 20
    flag = False  # 是否停止
    screen = cos.window
    root = Tk(screen, 10, 105, 200, 200, "Animation")
    timer = Time()
    canvas = Canvas(screen, root, 0, 0, 200, 200)
    canvas.pack()
    # Button(screen, root, "test", 5, 5, 45, lambda: box(15)).pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Animation')

                 我们来实现最后一个功能:动画循环播放(说白了只用增加3行代码):

from apilib import *
from classes import *
import cos
import random


def cosmain():
    def box(i):
        pen = canvas.rect(100 - i * 5, 100 - i * 5, i * 10, i * 10,
                          (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
        pens.append(pen)

    def run():
        nonlocal i, flag
        if not timer.is_sleeping() or timer.sec == 0:
            timer.sleep(0.5)
            if not flag:  # 没有停止过
                if i != 0:
                    box(i)
                    i -= 1
                else:
                    flag = True
            else:
                if len(pens) != 0:  # 如果还有绘图句柄:
                    canvas.remove_pen(pens[0])
                    pens.pop(0)  # 删除第一个元素
                else:  # 从这里
                    flag = False
                    i = 20  # 到这里

    pens = []
    i = 20
    flag = False  # 是否停止
    screen = cos.window
    root = Tk(screen, 10, 105, 200, 200, "Animation")
    timer = Time()
    canvas = Canvas(screen, root, 0, 0, 200, 200)
    canvas.pack()
    # Button(screen, root, "test", 5, 5, 45, lambda: box(15)).pack()
    root.add_unapply_hook(run)
    api_hook(root, 'Animation')

                 最后,将timer.sleep中的数据减小一点“timer.sleep(0.5)”—>"timer.sleep(0.05)",观看效果——完美!

        4.5 恭喜

                恭喜又完成了一件大作!相信您在此时一定收获颇多。CGY-OS的程序就是这么简单,只要可以熟练使用库就好了。

                下一节,我们将制作一个GUI设计很有挑战性的程序:计算器。

五、计算器

        5.1 原理、ui

                让我们先打开python控制台,输入以下代码:

eval("57+38-10*(5-4)")

                输出:85

                所以eval表达式可以计算一个Python语句(表达式)的值。通过这个,我们可以通过追加表达式的方法实现计算的功能,此思路和大部分计算器的编写思路是一样的。

                顺便说一句,因为cos内核过于简单,UI功能有限,所以我们的ui长这样(漂亮吧!):

        5.2 Python实现

                这次改规矩了,先写函数,再写UI。

import cos
from apilib import *
from classes import *


def cosmain():
    def update(x): #将x追加到evaler后面
        nonlocal evaler
        if evaler != '0':
            evaler += x
        else:
            evaler = x
        
    def backspace(): #退格
        nonlocal evaler
        if evaler != '0' and evaler != '':
            evaler = evaler[:-1]
        if evaler == '':
            evaler = '0'
        

    def c():#清零
        nonlocal evaler
        evaler = '0'
        

    def calc(): #计算
        nonlocal evaler

        try:
            int(eval(evaler)) #使用eval计算和试错
        except(SyntaxError, Exception):
            pass #先不管他
        finally:
            evaler = '0' #怎么着都得重置

    screen = cos.window
    evaler = "0" #数学表达式
    root = Tk(screen, 10, 105, 270, 65, "calc")
    api_hook(root, 'calc')

                注释很清楚,写过计算器的应该都能看懂。

                再加一个Label:

def cosmain():
    def update(x):
        nonlocal evaler
        if evaler != '0':
            evaler += x
        else:
            evaler = x
        if len(evaler) < len("Error:Invalid expression."):
            label.config(text=evaler, fg=black)#成功增加
        else:
            label.config(text="Error:Line too long.", fg=red)#失败(太长了)

    def backspace():
        nonlocal evaler
        if evaler != '0' and evaler != '':
            evaler = evaler[:-1]
        if evaler == '':
            evaler = '0'
        label.config(text=evaler, fg=black)#成功

    def c():
        nonlocal evaler
        evaler = '0'
        label.config(text=evaler, fg=black)#成功

    def calc():
        nonlocal evaler

        try:
            label.config(text=f"={int(eval(evaler))}", fg=green) #成功
        except(SyntaxError, Exception):
            label.config("Error:Invalid expression.", fg=red) #语法错误
        finally:
            evaler = '0'

    screen = cos.window
    evaler = "0"
    root = Tk(screen, 10, 105, 270, 65, "calc")
    Canvas(screen, root, 5, 5, 260, 15).pack()#为了使背景为白色,增加一个白色的canvas(正方形)
    label = Label(screen, root, evaler, 5, 5)
    label.pack()
    api_hook(root, 'calc')

                最后一堆按钮:

    Button(screen, root, "C", 5, 25, 10, lambda: c()).pack()
    Button(screen, root, "1", 20, 25, 10, lambda: update('1')).pack()
    Button(screen, root, "2", 35, 25, 10, lambda: update('2')).pack()
    Button(screen, root, "3", 50, 25, 10, lambda: update('3')).pack()
    Button(screen, root, "4", 65, 25, 10, lambda: update('4')).pack()
    Button(screen, root, "5", 80, 25, 10, lambda: update('5')).pack()
    Button(screen, root, "6", 95, 25, 10, lambda: update('6')).pack()
    Button(screen, root, "7", 110, 25, 10, lambda: update('7')).pack()
    Button(screen, root, "8", 125, 25, 10, lambda: update('8')).pack()
    Button(screen, root, "9", 140, 25, 10, lambda: update('9')).pack()
    Button(screen, root, "0", 155, 25, 10, lambda: update('0')).pack()
    Button(screen, root, "BackSpace", 170, 25, 95, lambda: backspace()).pack()
    Button(screen, root, "+", 5, 45, 10, lambda: update('+')).pack()
    Button(screen, root, "-", 20, 45, 10, lambda: update('-')).pack()
    Button(screen, root, "*", 35, 45, 10, lambda: update('*')).pack()
    Button(screen, root, "/", 50, 45, 10, lambda: update('/')).pack()
    Button(screen, root, "%", 65, 45, 10, lambda: update('%')).pack()
    Button(screen, root, "//", 80, 45, 20, lambda: update('//')).pack()
    Button(screen, root, "(", 105, 45, 10, lambda: update('(')).pack()
    Button(screen, root, ")", 120, 45, 10, lambda: update(')')).pack()
    Button(screen, root, "Calc it!", 135, 45, 85, lambda: calc()).pack()

        5.3 恭喜!

                计算器这个程序虽然简单,但意义非凡,它代表着CGY-OS在不断地向实用的操作系统买进!

                本节写的简单了一些,以后也只会越来越简单。

                全部源码:

import cos
from apilib import *
from classes import *


def cosmain():
    def update(x):
        nonlocal evaler
        if evaler != '0':
            evaler += x
        else:
            evaler = x
        if len(evaler) < len("Error:Invalid expression."):
            label.config(text=evaler, fg=black)
        else:
            label.config(text="Error:Line too long.", fg=red)

    def backspace():
        nonlocal evaler
        if evaler != '0' and evaler != '':
            evaler = evaler[:-1]
        if evaler == '':
            evaler = '0'
        label.config(text=evaler, fg=black)

    def c():
        nonlocal evaler
        evaler = '0'
        label.config(text=evaler, fg=black)

    def calc():
        nonlocal evaler

        try:
            label.config(text=f"={int(eval(evaler))}", fg=green)
        except(SyntaxError, Exception):
            label.config("Error:Invalid expression.", fg=red)
        finally:
            evaler = '0'

    screen = cos.window
    evaler = "0"
    root = Tk(screen, 10, 105, 270, 65, "calc")
    Canvas(screen, root, 5, 5, 260, 15).pack()
    label = Label(screen, root, evaler, 5, 5)
    label.pack()
    Button(screen, root, "C", 5, 25, 10, lambda: c()).pack()
    Button(screen, root, "1", 20, 25, 10, lambda: update('1')).pack()
    Button(screen, root, "2", 35, 25, 10, lambda: update('2')).pack()
    Button(screen, root, "3", 50, 25, 10, lambda: update('3')).pack()
    Button(screen, root, "4", 65, 25, 10, lambda: update('4')).pack()
    Button(screen, root, "5", 80, 25, 10, lambda: update('5')).pack()
    Button(screen, root, "6", 95, 25, 10, lambda: update('6')).pack()
    Button(screen, root, "7", 110, 25, 10, lambda: update('7')).pack()
    Button(screen, root, "8", 125, 25, 10, lambda: update('8')).pack()
    Button(screen, root, "9", 140, 25, 10, lambda: update('9')).pack()
    Button(screen, root, "0", 155, 25, 10, lambda: update('0')).pack()
    Button(screen, root, "BackSpace", 170, 25, 95, lambda: backspace()).pack()
    Button(screen, root, "+", 5, 45, 10, lambda: update('+')).pack()
    Button(screen, root, "-", 20, 45, 10, lambda: update('-')).pack()
    Button(screen, root, "*", 35, 45, 10, lambda: update('*')).pack()
    Button(screen, root, "/", 50, 45, 10, lambda: update('/')).pack()
    Button(screen, root, "%", 65, 45, 10, lambda: update('%')).pack()
    Button(screen, root, "//", 80, 45, 20, lambda: update('//')).pack()
    Button(screen, root, "(", 105, 45, 10, lambda: update('(')).pack()
    Button(screen, root, ")", 120, 45, 10, lambda: update(')')).pack()
    Button(screen, root, "Calc it!", 135, 45, 85, lambda: calc()).pack()
    api_hook(root, 'calc')

六、“超级画板”

        6.1 一个新的类

                为了使这个应用程序可以使用,我专门写了一个新的类:ImageButton,它为Button的子类。

class ImageButton(Button):
    def __init__(self, screen, root, img, x, y, w, h, table, command, bg=lightgray):
        super().__init__(screen, root, "", x, y, w, command, bg)
        self.image = img
        self.table = table
        self.h = h

    def printImg(self):
        for i in range(len(self.image)):
            for j in range(len(self.image[i])):
                if self.table[self.image[i][j]] is not None:
                    Io.io_put_point(self.screen, self.x + self.root.x + j, self.y + self.root.y + i,
                                    self.table[self.image[i][j]])

    def config(self, x=None, y=None, w=None, h=None, command=None, fg=None, bg=None, image=None, table=None):
        if x is not None:
            self.x = x
        if y is not None:
            self.y = y
        if w is not None:
            self.w = w
        if h is not None:
            self.h = h
        if command is not None:
            self.command = command
        if fg is not None:
            self.fg = fg
        if bg is not None:
            self.bg = bg
        if image is not None:
            self.image = image
        if table is not None:
            self.table = table

    def draw(self):
        global s_mode
        mx, my = pygame.mouse.get_pos()
        if self.check_click(mx, my):
            Io.io_put_box(self.screen, self.x - 1 + self.root.x, self.y - 1 + self.root.y, self.w + 1, self.h + 1,
                          black)
            Io.io_put_box(self.screen, self.x + self.root.x, self.y + self.root.y, self.w + 1, self.h + 1, white)
            Io.io_put_box(self.screen, self.x + self.root.x, self.y + self.root.y, self.w, self.h, self.bg)
            self.printImg()
        else:
            Io.io_put_box(self.screen, self.x - 1 + self.root.x, self.y - 1 + self.root.y, self.w + 1, self.h + 1,
                          white)
            Io.io_put_box(self.screen, self.x + self.root.x, self.y + self.root.y, self.w + 1, self.h + 1, black)
            Io.io_put_box(self.screen, self.x + self.root.x, self.y + self.root.y, self.w, self.h, self.bg)
            self.printImg()

        if self.on(mx, my):
            cell.m_state = mouse3
            s_mode = True

        if self.runcmd() and self.check_click(mx, my):
            self.command()

                这里说一下:img是一个二维数组,table是一个字典,用于描述img的颜色。

                有了类就要有图片,前面说了,img是二维数组,所以图片都写在代码里:

image0 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image1 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image2 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
    [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image3 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image4 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

        6.2 代码

                没错,直接上代码,说都懒得说……

                先来UI:

def cosmain():
    def changeColor(color, iten):
        pass

    def clear():
        pass

    def widthUpdate(num):
        pass

    screen = cos.window
    pen_color = black
    width = 5
    root = Tk(screen, 10, 105, 450, 450, "Draw")
    canvas = Canvas(screen, root, 30, 0, 420, 450)
    canvas.pack()
    btn_green = ImageButton(screen, root, image0, 5, 5, 16, 16, {0: "green", 1: "black"},
                            lambda: changeColor(green, btn_green))
    btn_green.pack()
    btn_red = ImageButton(screen, root, image0, 5, 25, 16, 16, {0: "red", 1: "black"},
                          lambda: changeColor(red, btn_red))
    btn_red.pack()
    btn_black = ImageButton(screen, root, image0, 5, 45, 16, 16, {0: "black", 1: "white"},
                            lambda: changeColor(black, btn_black))
    btn_black.pack()
    btn_yellow = ImageButton(screen, root, image0, 5, 65, 16, 16, {0: "yellow", 1: "black"},
                             lambda: changeColor(yellow, btn_yellow))
    btn_yellow.pack()
    btn_blue = ImageButton(screen, root, image0, 5, 85, 16, 16, {0: "blue", 1: "black"},
                           lambda: changeColor(blue, btn_blue))
    btn_blue.pack()
    btn_lightblue = ImageButton(screen, root, image0, 5, 105, 16, 16, {0: "lightblue", 1: "black"},
                                lambda: changeColor(lightblue, btn_lightblue))
    btn_lightblue.pack()
    btn_orange = ImageButton(screen, root, image0, 5, 125, 16, 16, {0: "orange", 1: "black"},
                             lambda: changeColor(orange, btn_orange))
    btn_orange.pack()
    btn_purple = ImageButton(screen, root, image0, 5, 145, 16, 16, {0: "purple", 1: "black"},
                             lambda: changeColor(purple, btn_purple))
    btn_purple.pack()
    btn_pink = ImageButton(screen, root, image0, 5, 165, 16, 16, {0: "pink", 1: "black"},
                           lambda: changeColor(pink, btn_pink))
    btn_pink.pack()
    bth_clear = ImageButton(screen, root, image2, 5, 185, 16, 16, {0: None, 1: "black"}, clear)
    bth_clear.pack()
    bth_up = ImageButton(screen, root, image3, 5, 205, 16, 10, {0: None, 1: 'black'}, command=lambda: widthUpdate(1))
    bth_up.pack()
    label = Label(screen, root, str(width).zfill(2), 5, 220, bg=None)  # zfill为补零的小技巧
    label.pack()
    bth_down = ImageButton(screen, root, image4, 5, 240, 16, 10, {0: None, 1: 'black'}, command=lambda: widthUpdate(-1))
    bth_down.pack()
    buttons = [btn_pink, btn_purple, btn_orange, btn_lightblue, btn_blue, btn_yellow, btn_black, btn_red, btn_green]

    def run():
        pass

    root.add_unapply_hook(run)
    api_hook(root, 'Drawer')

                再上逻辑:

    def changeColor(color, iten):
        nonlocal pen_color
        pen_color = color
        iten.config(image=image1)
        for i in buttons:
            if i is iten: continue
            i.config(image=image0)

    def clear():
        canvas.remove_all()

    def widthUpdate(num):
        nonlocal width
        if 3 <= width + num <= 50:
            width += num
            label.config(text=str(width).zfill(2))
#……
    def run():
        is_on, mx, my = canvas.mouse_is_on()
        if is_on and Io.io_check_mouse()[0]:
            canvas.rect(mx + 15 + 8, my - 15 + 8, width, width, pen_color)

                最后把全部代码一上:

from apilib import *
from classes import *
import cos
import hankaku

image0 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image1 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image2 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
    [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image3 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
image4 = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
    [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]


def cosmain():
    def changeColor(color, iten):
        nonlocal pen_color
        pen_color = color
        iten.config(image=image1)
        for i in buttons:
            if i is iten: continue
            i.config(image=image0)

    def clear():
        canvas.remove_all()

    def widthUpdate(num):
        nonlocal width
        if 3 <= width + num <= 50:
            width += num
            label.config(text=str(width).zfill(2))

    screen = cos.window
    pen_color = black
    width = 5
    root = Tk(screen, 10, 105, 450, 450, "Draw")
    canvas = Canvas(screen, root, 30, 0, 420, 450)
    canvas.pack()
    btn_green = ImageButton(screen, root, image0, 5, 5, 16, 16, {0: "green", 1: "black"},
                            lambda: changeColor(green, btn_green))
    btn_green.pack()
    btn_red = ImageButton(screen, root, image0, 5, 25, 16, 16, {0: "red", 1: "black"},
                          lambda: changeColor(red, btn_red))
    btn_red.pack()
    btn_black = ImageButton(screen, root, image0, 5, 45, 16, 16, {0: "black", 1: "white"},
                            lambda: changeColor(black, btn_black))
    btn_black.pack()
    btn_yellow = ImageButton(screen, root, image0, 5, 65, 16, 16, {0: "yellow", 1: "black"},
                             lambda: changeColor(yellow, btn_yellow))
    btn_yellow.pack()
    btn_blue = ImageButton(screen, root, image0, 5, 85, 16, 16, {0: "blue", 1: "black"},
                           lambda: changeColor(blue, btn_blue))
    btn_blue.pack()
    btn_lightblue = ImageButton(screen, root, image0, 5, 105, 16, 16, {0: "lightblue", 1: "black"},
                                lambda: changeColor(lightblue, btn_lightblue))
    btn_lightblue.pack()
    btn_orange = ImageButton(screen, root, image0, 5, 125, 16, 16, {0: "orange", 1: "black"},
                             lambda: changeColor(orange, btn_orange))
    btn_orange.pack()
    btn_purple = ImageButton(screen, root, image0, 5, 145, 16, 16, {0: "purple", 1: "black"},
                             lambda: changeColor(purple, btn_purple))
    btn_purple.pack()
    btn_pink = ImageButton(screen, root, image0, 5, 165, 16, 16, {0: "pink", 1: "black"},
                           lambda: changeColor(pink, btn_pink))
    btn_pink.pack()
    bth_clear = ImageButton(screen, root, image2, 5, 185, 16, 16, {0: None, 1: "black"}, clear)
    bth_clear.pack()
    bth_up = ImageButton(screen, root, image3, 5, 205, 16, 10, {0: None, 1: 'black'}, command=lambda: widthUpdate(1))
    bth_up.pack()
    label = Label(screen, root, str(width).zfill(2), 5, 220, bg=None)  # zfill为补零的小技巧
    label.pack()
    bth_down = ImageButton(screen, root, image4, 5, 240, 16, 10, {0: None, 1: 'black'}, command=lambda: widthUpdate(-1))
    bth_down.pack()
    buttons = [btn_pink, btn_purple, btn_orange, btn_lightblue, btn_blue, btn_yellow, btn_black, btn_red, btn_green]

    def run():
        is_on, mx, my = canvas.mouse_is_on()
        if is_on and Io.io_check_mouse()[0]:
            canvas.rect(mx + 15 + 8, my - 15 + 8, width, width, pen_color)

    root.add_unapply_hook(run)
    api_hook(root, 'Drawer')

                唉,越来越懒了……

        6.3 BUG

                本程序有一个bug。当我们运行它,并连续点击使画笔粗细变成50时,如果我们把鼠标放的太靠边的话: 

                

                这并不是 draw应用程序的问题,而是COS操作系统的问题,请不要着急,下一版本《有可能》(十分“有”可能)修复~

七、下载地址:

        https://pan.baidu.com/s/1OqZ4R52dvnPCuUP1qaH3CA?pwd=CGY6

        

 https://download.csdn.net/download/cgy091107/88255436 icon-default.png?t=N6B9https://download.csdn.net/download/cgy091107/88255436

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

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

相关文章

基于Python3 的 简单股票 可转债 提醒逻辑

概述 通过本地的定时轮训&#xff0c;结合本地建议数据库。检查股票可转债价格的同事&#xff0c;进行策略化提醒 详细 前言 为什么会有这么个东西出来呢&#xff0c;主要是因为炒股软件虽然有推送&#xff0c;但是设置了价格之后&#xff0c;看到推送也未必那么及时&#…

数据结构(Java实现)-ArrayList与顺序表

什么是List List是一个接口&#xff0c;继承自Collection。 List的使用 List是个接口&#xff0c;并不能直接用来实例化。 如果要使用&#xff0c;必须去实例化List的实现类。在集合框架中&#xff0c;ArrayList和LinkedList都实现了List接口。 线性表 线性表&#xff08;lin…

【安装GPU版本pytorch,torch.cuda.is_available()仍然返回False问题】

TOC 第一步 检查cuda是否安装&#xff0c;CUDA环境变量是否正确设置&#xff0c;比如linux需要设置在PATH&#xff0c;window下环境变量编辑看看&#xff0c;是否有CUDA 第二步&#xff0c;核查python中torch版本 首先查看你环境里的pytorch是否是cuda版本&#xff0c;我这…

深度学习经典检测方法的概述

深度学习经典的检测方法 two-stage&#xff08;两阶段&#xff09;&#xff1a;Faster-rcnn Mask-Rcnn系列 两阶段&#xff08;two-stage&#xff09;是指先通过一个区域提取网络&#xff08;region proposal network&#xff0c;RPN&#xff09;生成候选框&#xff0c;再通过…

4.17 如何基于 UDP 协议实现可靠传输?

目录 QUIC 是如何实现可靠传输的&#xff1f; Packet Header QUIC Frame Header QUIC 是如何解决 TCP 队头阻塞问题的&#xff1f; 什么是TCP对头阻塞问题&#xff1a; HTTP/2 的队头阻塞: 没有队头阻塞的 QUIC QUIC 是如何做流量控制的&#xff1f; QUIC 实现流量控制…

变压器绝缘油酸值测试

变压器绝缘油 酸值测试 试验目的 变压器绝缘油的酸值是表明油品中含有酸性物质&#xff0c;即有机酸和无机酸的总值&#xff0c;一般以中和一克变压器油中酸性物质所需的氢氧化钾mg数来表示。 未使用过的新变压器油中基本不含酸性物质&#xff0c;其酸值相当小&#xff0c;但…

Docker 容器学习笔记

Docker 容器学习笔记 容器的由来 早先&#xff0c;虚拟机通过操作系统实现相互隔离&#xff0c;保证应用程序在运行时相互独立&#xff0c;避免相互干扰。但是操作系统又笨又重&#xff0c;耗费资源严重&#xff1a; 容器技术只隔离应用程序的运行时环境但容器之间共享同一个…

数据结构数组栈的实现

Hello&#xff0c;今天我们来实现一下数组栈&#xff0c;学完这个我们又更进一步了。 一、栈 栈的概念 栈是一种特殊的线性表&#xff0c;它只允许在固定的一端进行插入和删除元素的操作。 进行数据的插入和删除只在栈顶实现&#xff0c;另一端就是栈底。 栈的元素是后进先出。…

vue2 生命周期,工程化开发入门

一、今日目标 1.生命周期 生命周期介绍生命周期的四个阶段生命周期钩子声明周期案例 2.工程化开发入门 工程化开发和脚手架项目运行流程组件化组件注册 二、Vue生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09;什么…

【线程池】ThreadPoolExecutor的使用示例

文章目录 通过ThreadPoolExecutor创建线程池。线程的处理结果如何获取&#xff1f; 通过ThreadPoolExecutor创建线程池。 ThreadPoolExecutor构造方法参数&#xff1a; int corePoolSize //核心线程数量int maximumPoolSize//最大线程数long keepAliveTime//当线程数大于核心…

【谷粒学院】开发篇二:后台管理系统搭建逆向生成代码

后台管理系统介绍 本篇文章主要内容如下&#xff1a; 1.使用人人开源人人开源绞手架搭建后台管理系统的前端和后端框架。 2.使用renren-generator逆向生成微服务&#xff08;gulimall_pms、gulimall_oms、gulimall_sms、gulimall_ums、gulimall_wms&#xff09;的CRUD代码。 …

前端高频面试题 js中堆和栈的区别和浏览器的垃圾回收机制

一、 栈(stack)和 堆(heap) 栈(stack)&#xff1a;是栈内存的简称&#xff0c;栈是自动分配相对固定大小的内存空间&#xff0c;并由系统自动释放&#xff0c;栈数据结构遵循FILO&#xff08;first in last out&#xff09;先进后出的原则&#xff0c;较为经典的就是乒乓球盒结…

机器学习---LDA代码

1. 获取投影坐标 import numpy as npdef GetProjectivePoint_2D(point, line):a point[0]b point[1]k line[0]t line[1]if k 0: return [a, t]elif k np.inf: return [0, b]x (ak*b-k*t) / (k*k1)y k*x treturn [x, y] 该函数用于获取一个点到一条直线的投影点…

以物联网为核心的智慧工地云平台:聚集智能技术,实现建筑工地智慧管理

智慧工地云平台源码&#xff0c;智慧工地项目监管平台源码&#xff0c;智慧工地可视化数据大屏源码 智慧工地云平台是将云计算、大数据、物联网、移动技术和智能设备等信息化技术手段&#xff0c;聚集在建筑工地施工管理现场&#xff0c;围绕人员、机械、物料、环境等关键要素&…

网络安全(黑客)——自学日薪2700

以下是练习舞蹈时长两年半的苕皮哥的故事 你想想一个跨专业的都能拿到日薪2700&#xff0c;你上你也行&#xff0c;那么接下来就是我给大家&#xff0c;整理的网络安全学习思路&#xff0c;让大家斩获高薪&#xff01; 前言&#xff1a; 想自学网络安全&#xff08;黑客技术&am…

秦丝九周年 | 秦丝生产ERP,全新一代服装ERP、SCM

秦丝九周年的主题是“数字生意&#xff0c;经九长兴”&#xff0c;通过数字化工具帮助更多商家开启数字生意&#xff0c;改变传统的低效率的工作&#xff0c;提供更加简单高效地把生意做大做强。 在帮助200万商家通过数字化工具管理零售、批发、连锁门店的同时&#xff0c;秦丝…

_数字矩阵

题目&#xff1a;一个3阶的数字矩阵如下&#xff1a; 1 2 3 8 9 4 7 6 5 现在给定数字n(1<n≤20)&#xff0c;输出n阶数字矩阵。 思路&#xff1a; 放出一条好玩的贪吃蛇&#xff0c;按照右下左上的顺序吃蛋糕&#xff0c;一边吃蛋糕&#xff0c;一边拉数字&#xff1b…

[C++ 网络协议] 套接字的多种可选项

目录 1. 套接字的可选项 2. 获取/设置套接字可选项 2.1 getsockopt函数&#xff08;获取套接字可选项&#xff09; 2.2 setsockopt函数&#xff08;设置套接字可选项&#xff09; 3. 常用套接字可选项 3.1 SOL_SOCKET协议层的SO_TYPE可选项 3.2 SOL_SOCKET协议层的SO_SN…

【八股】2023秋招八股复习笔记4(MySQL Redis等)

文章目录 目录1、MySQLmysql索引实现mysql索引优化mysql索引失效的情况mysql 千万数据优化mysql 事务隔离级别 & 实现原理mysql MVCC版本链&#xff08;undo log&#xff09;mysql数据同步机制 & 主从复制 &#xff08;binlog&#xff09;mysql 日志&数据恢复&…

git及GitHub的使用

文章目录 git在本地仓库的使用github使用创建仓库https协议连接(不推荐&#xff0c;现在用起来比较麻烦)ssh连接&#xff08;推荐&#xff09;git分支操作冲突处理忽略文件 git在本地仓库的使用 1.在目标目录下右键打开git bash here 2.创建用户名和邮箱(注&#xff1a; 下载完…