用python做一个简单的画板

news2024/12/28 18:51:19

一,画板的介绍

画板(Paint Board)是一个提供用户绘图、涂鸦和创作的平台。现代数字画板通常是由软件程序实现的,具有多种功能。以下是画板的一些主要特征和功能:

1. 基本绘图工具

  • 画笔和铅笔:用户可以选择不同的笔刷或笔触类型,调整粗细和透明度来进行绘图。
  • 橡皮擦:用于删除不需要的部分。

2. 颜色选择

  • 颜色调色板:提供多种颜色供用户选择,用户还可以自定义颜色。
  • 渐变和填充:一些画板支持渐变效果和区域填充,让绘图更为丰富。

3. 形状工具

  • 用户可以绘制几何图形,如矩形、圆形、线条和多边形等。

4. 图层管理

  • 支持图层的概念,允许用户在不同的层上绘图,便于编辑和修改,不同图层之间相互独立。

5. 撤销和重做

  • 提供撤销和重做功能,让用户可以轻松修正错误,支持多步撤销。

6. 区域选择和填充

  • 一些画板允许用户选择特定区域进行删除或填充颜色,增加创作灵活性。

7. 导入和导出

  • 用户可以导入图片进行编辑,也能把创作的作品导出为多种格式(如PNG、JPEG等)。

8. 界面友好

  • 设计简洁直观,适合各年龄段用户,提供易于使用的工具和菜单。

9. 额外功能

  • 一些高级画板软件还有滤镜、效果、文本工具和图形编辑功能。

10. 可用于多种平台

  • 画板可以按需在桌面(Windows、macOS)、在线(浏览器应用)、手机(iOS、Android)等多种平台上使用。

应用场景

  • 艺术创作:帮助艺术家进行草图、插画和数字绘画。
  • 设计:用于界面设计、图标设计和做原型。
  • 教育:教师和学生使用画板进行图形化表达和创作。
  • 娱乐:简单的涂鸦游戏或创作活动。

总结

现代画板提供了丰富的功能,能够满足不同用户的创作需求,从简单的涂鸦到复杂的艺术作品,都是一个很好的创作工具。无论是专业艺术家还是业余爱好者,都可以在画板中找到乐趣和表达的可能性。

二,第一步实现画板

我们可以使用 Python 的 Tkinter 库来创建一个简单的画板应用程序。下面的示例代码展示了如何构建一个基本的画板,用户可以通过鼠标在画布上绘画。

import tkinter as tk  

class PaintApp:  
    def __init__(self, root):  
        self.root = root  
        self.root.title("简单画板")  

        # 创建画布  
        self.canvas = tk.Canvas(root, bg="white", width=800, height=600)  
        self.canvas.pack()  

        # 初始化绘图相关的变量  
        self.last_x = None  
        self.last_y = None  

        # 绑定鼠标事件  
        self.canvas.bind("<Motion>", self.paint)  
        self.canvas.bind("<Button-1>", self.set_last_pos)  
        self.canvas.bind("<ButtonRelease-1>", self.reset)  

    def set_last_pos(self, event):  
        # 设置最后的坐标  
        self.last_x = event.x  
        self.last_y = event.y  

    def paint(self, event):  
        # 在画布上绘制线条  
        if self.last_x and self.last_y:  
            x, y = event.x, event.y  
            self.canvas.create_line(self.last_x, self.last_y, x, y, fill="black", width=2)  
            self.last_x = x  
            self.last_y = y  

    def reset(self, event):  
        # 重置最后的坐标  
        self.last_x = None  
        self.last_y = None  

if __name__ == "__main__":  
    root = tk.Tk()  
    app = PaintApp(root)  
    root.mainloop()

 运行结果:

代码解释

  1. 创建主窗口:使用 tk.Tk() 创建主窗口,并设置标题。
  2. 创建画布:使用 tk.Canvas 创建一个白色背景的画布,设置宽度和高度。
  3. 绘图逻辑
    • 通过绑定 <Motion> 事件,跟踪鼠标移动,并在画布上绘制线条。
    • 使用 set_last_pos 方法记录鼠标按下的位置,reset 方法在鼠标释放时重置位置。
    • 当鼠标移动时,paint 方法绘制线条。
  4. 启动应用:在主程序中创建 Tkinter 主循环。

三,优化画板

接下来是一个更完整的 Tkinter 画板代码,包含删除(清空画布)、撤销(恢复上一步操作)、橡皮擦(擦除绘图)和涂颜色的功能。

import tkinter as tk  
from tkinter import colorchooser  

class PaintApp:  
    def __init__(self, root):  
        self.root = root  
        self.root.title("功能完善的画板")  

        # 创建画布  
        self.canvas = tk.Canvas(root, bg="white", width=800, height=600)  
        self.canvas.pack()  

        # 初始化绘图相关的变量  
        self.last_x = None  
        self.last_y = None  
        self.color = "black"  
        self.stroke_width = 2  
        self.lines = []  

        # 绑定鼠标事件  
        self.canvas.bind("<Motion>", self.paint)  
        self.canvas.bind("<Button-1>", self.set_last_pos)  
        self.canvas.bind("<ButtonRelease-1>", self.reset)  

        # 创建工具栏  
        self.toolbar = tk.Frame(root)  
        self.toolbar.pack(fill=tk.X)  

        # 选择颜色按钮  
        self.color_button = tk.Button(self.toolbar, text="选择颜色", command=self.choose_color)  
        self.color_button.pack(side=tk.LEFT)  

        # 橡皮擦按钮  
        self.eraser_button = tk.Button(self.toolbar, text="橡皮擦", command=self.use_eraser)  
        self.eraser_button.pack(side=tk.LEFT)  

        # 撤销按钮  
        self.undo_button = tk.Button(self.toolbar, text="撤销", command=self.undo)  
        self.undo_button.pack(side=tk.LEFT)  

        # 清空画布按钮  
        self.clear_button = tk.Button(self.toolbar, text="清空画布", command=self.clear_canvas)  
        self.clear_button.pack(side=tk.LEFT)  

    def set_last_pos(self, event):  
        # 设置最后的坐标  
        self.last_x = event.x  
        self.last_y = event.y  

    def paint(self, event):  
        # 在画布上绘制线条  
        if self.last_x and self.last_y:  
            x, y = event.x, event.y  
            line = self.canvas.create_line(self.last_x, self.last_y, x, y, fill=self.color, width=self.stroke_width)  
            self.lines.append(line)  
            self.last_x = x  
            self.last_y = y  

    def reset(self, event):  
        # 重置最后的坐标  
        self.last_x = None  
        self.last_y = None  

    def choose_color(self):  
        # 选择颜色的函数  
        color = colorchooser.askcolor()[1]  
        if color:  
            self.color = color  

    def use_eraser(self):  
        # 切换到橡皮擦模式  
        self.color = "white"  

    def undo(self):  
        # 撤销最后一步操作  
        if self.lines:  
            line = self.lines.pop()  
            self.canvas.delete(line)  

    def clear_canvas(self):  
        # 清空画布  
        self.canvas.delete("all")  
        self.lines.clear()  

if __name__ == "__main__":  
    root = tk.Tk()  
    app = PaintApp(root)  
    root.mainloop()

功能解释

  1. 选择颜色:使用 colorchooser 让用户选择颜色,创建一个新的颜色变量来存储所选颜色。
  2. 橡皮擦:将当前绘图颜色设置为白色,以模拟橡皮擦的效果。
  3. 撤销:通过 self.lines 列表保存每一条线,撤销时从列表中删除最后一条线。
  4. 清空画布:使用 self.canvas.delete("all") 清空画布,并清空存储的线条列表。

 四,添加选择区域的功能

下面是更新后的画板应用程序,这个版本添加了选择区域的功能,使用户可以选择区域并对其进行涂色或删除操作。工具栏也已经移动到窗口的顶部。

import tkinter as tk  
from tkinter import colorchooser  

class PaintApp:  
    def __init__(self, root):  
        self.root = root  
        self.root.title("功能完善的画板")  

        # 创建画布  
        self.canvas = tk.Canvas(root, bg="white", width=800, height=600)  
        self.canvas.pack()  

        # 初始化绘图相关的变量  
        self.last_x = None  
        self.last_y = None  
        self.color = "black"  
        self.stroke_width = 2  
        self.lines = []  
        self.rect_id = None  
        self.start_x = None  
        self.start_y = None  
        
        # 绑定鼠标事件  
        self.canvas.bind("<Motion>", self.paint)  
        self.canvas.bind("<Button-1>", self.set_last_pos)  
        self.canvas.bind("<ButtonRelease-1>", self.reset)  
        self.canvas.bind("<Button-3>", self.start_select) # 右键开始选择区域  
        self.canvas.bind("<B3-Motion>", self.draw_rectangle) # 右键拖动选择区域  
        self.canvas.bind("<ButtonRelease-3>", self.end_select) # 右键释放结束选择  

        # 创建工具栏  
        self.toolbar = tk.Frame(root)  
        self.toolbar.pack(fill=tk.X)  

        # 选择颜色按钮  
        self.color_button = tk.Button(self.toolbar, text="选择颜色", command=self.choose_color)  
        self.color_button.pack(side=tk.LEFT)  

        # 橡皮擦按钮  
        self.eraser_button = tk.Button(self.toolbar, text="橡皮擦", command=self.use_eraser)  
        self.eraser_button.pack(side=tk.LEFT)  

        # 撤销按钮  
        self.undo_button = tk.Button(self.toolbar, text="撤销", command=self.undo)  
        self.undo_button.pack(side=tk.LEFT)  

        # 清空画布按钮  
        self.clear_button = tk.Button(self.toolbar, text="清空画布", command=self.clear_canvas)  
        self.clear_button.pack(side=tk.LEFT)  

        # 区域删除按钮  
        self.delete_area_button = tk.Button(self.toolbar, text="区域删除", command=self.delete_selected_area)  
        self.delete_area_button.pack(side=tk.LEFT)  

        # 区域填充按钮  
        self.fill_area_button = tk.Button(self.toolbar, text="区域填充", command=self.fill_selected_area)  
        self.fill_area_button.pack(side=tk.LEFT)  

    def set_last_pos(self, event):  
        # 设置最后的坐标  
        self.last_x = event.x  
        self.last_y = event.y  

    def paint(self, event):  
        # 在画布上绘制线条  
        if self.last_x and self.last_y:  
            x, y = event.x, event.y  
            line = self.canvas.create_line(self.last_x, self.last_y, x, y, fill=self.color, width=self.stroke_width)  
            self.lines.append(line)  
            self.last_x = x  
            self.last_y = y  

    def reset(self, event):  
        # 重置最后的坐标  
        self.last_x = None  
        self.last_y = None  

    def choose_color(self):  
        # 选择颜色的函数  
        color = colorchooser.askcolor()[1]  
        if color:  
            self.color = color  

    def use_eraser(self):  
        # 切换到橡皮擦模式  
        self.color = "white"  

    def undo(self):  
        # 撤销最后一步操作  
        if self.lines:  
            line = self.lines.pop()  
            self.canvas.delete(line)  

    def clear_canvas(self):  
        # 清空画布  
        self.canvas.delete("all")  
        self.lines.clear()  

    def start_select(self, event):  
        # 开始选择区域  
        self.start_x = event.x  
        self.start_y = event.y  
        self.rect_id = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='blue', dash=(2, 2))  

    def draw_rectangle(self, event):  
        # 绘制选择区域  
        self.canvas.coords(self.rect_id, self.start_x, self.start_y, event.x, event.y)  

    def end_select(self, event):  
        # 结束选择区域  
        pass  

    def delete_selected_area(self):  
        # 删除选择区域内的内容  
        if self.rect_id:  
            x1, y1, x2, y2 = self.canvas.coords(self.rect_id)  
            self.canvas.delete(self.rect_id)  
            self.rect_id = None  
            self.clear_area(x1, y1, x2, y2)  

    def clear_area(self, x1, y1, x2, y2):  
        # 清除选择区域内的内容  
        overlapping_items = self.canvas.find_overlapping(x1, y1, x2, y2)  
        for item in overlapping_items:  
            self.canvas.delete(item)  

    def fill_selected_area(self):  
        # 在选择区域内涂色  
        if self.rect_id:  
            x1, y1, x2, y2 = self.canvas.coords(self.rect_id)  
            self.canvas.delete(self.rect_id)  
            self.rect_id = None  
            self.canvas.create_rectangle(x1, y1, x2, y2, fill=self.color, outline='')  

if __name__ == "__main__":  
    root = tk.Tk()  
    app = PaintApp(root)  
    root.mainloop()

 

功能说明

  1. 选择区域:用户可以使用鼠标的右键点击并拖动来选择一个矩形区域,该区域用虚线框表示。
  2. 区域删除:点击“区域删除”按钮后,将删除所选区域内的所有绘制内容。
  3. 区域填充:点击“区域填充”按钮后,将用当前选择的颜色填充所选区域。
  4. 工具栏:包含颜色选择、橡皮擦、撤销、清空画布、区域删除和区域填充等功能。

五,最完整的画板

完整版可以把页面保存下来,还可以打开图片,可以各种画图

import tkinter as tk  
from tkinter import colorchooser, filedialog  
from PIL import Image, ImageDraw, ImageTk  

class PaintApp:  
    def __init__(self, root):  
        self.root = root  
        self.root.title("绘图应用")  
        self.canvas = tk.Canvas(root, bg="white", width=800, height=600)  
        self.canvas.pack(expand=tk.YES, fill=tk.BOTH)  

        self.toolbar = tk.Frame(root)  
        self.toolbar.pack(side=tk.TOP, fill=tk.X)  

        self.color = "black"  
        self.stroke_width = 2  
        self.lines = []  
        self.last_x = None  
        self.last_y = None  
        self.rect_id = None  
        self.image = Image.new("RGB", (800, 600), "white")  
        self.draw = ImageDraw.Draw(self.image)  

        # 工具栏按钮  
        self.color_button = tk.Button(self.toolbar, text="选择颜色", command=self.choose_color)  
        self.color_button.pack(side=tk.LEFT)  

        self.eraser_button = tk.Button(self.toolbar, text="橡皮擦", command=self.use_eraser)  
        self.eraser_button.pack(side=tk.LEFT)  

        self.undo_button = tk.Button(self.toolbar, text="撤销", command=self.undo)  
        self.undo_button.pack(side=tk.LEFT)  

        self.clear_button = tk.Button(self.toolbar, text="清空", command=self.clear_canvas)  
        self.clear_button.pack(side=tk.LEFT)  

        self.delete_area_button = tk.Button(self.toolbar, text="区域删除", command=self.delete_selected_area)  
        self.delete_area_button.pack(side=tk.LEFT)  

        self.fill_area_button = tk.Button(self.toolbar, text="区域填充", command=self.fill_selected_area)  
        self.fill_area_button.pack(side=tk.LEFT)  

        self.save_button = tk.Button(self.toolbar, text="保存", command=self.save_image)  
        self.save_button.pack(side=tk.LEFT)  

        self.new_button = tk.Button(self.toolbar, text="新建", command=self.new_canvas)  
        self.new_button.pack(side=tk.LEFT)  

        self.open_button = tk.Button(self.toolbar, text="打开", command=self.open_image)  
        self.open_button.pack(side=tk.LEFT)  

        # 事件绑定  
        self.canvas.bind("<Button-1>", self.set_last_pos)  
        self.canvas.bind("<B1-Motion>", self.paint)  
        self.canvas.bind("<ButtonRelease-1>", self.reset)  
        self.canvas.bind("<Button-3>", self.start_select)  
        self.canvas.bind("<B3-Motion>", self.draw_rectangle)  
        self.canvas.bind("<ButtonRelease-3>", self.end_select)  

        self.start_x = self.start_y = None  

    def set_last_pos(self, event):  
        self.last_x = event.x  
        self.last_y = event.y  

    def paint(self, event):  
        if self.last_x is not None and self.last_y is not None:  
            x, y = event.x, event.y  
            line = self.canvas.create_line(self.last_x, self.last_y, x, y, fill=self.color, width=self.stroke_width)  
            self.lines.append(line)  
            self.draw.line((self.last_x, self.last_y, x, y), fill=self.color, width=self.stroke_width)  
            self.last_x = x  
            self.last_y = y  

    def reset(self, event):  
        self.last_x = None  
        self.last_y = None  

    def choose_color(self):  
        color = colorchooser.askcolor()[1]  
        if color:  
            self.color = color  

    def use_eraser(self):  
        self.color = "white"  

    def undo(self):  
        if self.lines:  
            line = self.lines.pop()  
            self.canvas.delete(line)  

    def clear_canvas(self):  
        self.canvas.delete("all")  
        self.lines.clear()  
        self.image = Image.new("RGB", (800, 600), "white")  
        self.draw = ImageDraw.Draw(self.image)  

    def start_select(self, event):  
        self.start_x = event.x  
        self.start_y = event.y  
        if self.rect_id is not None:  
            self.canvas.delete(self.rect_id)  
        self.rect_id = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='blue', dash=(2, 2))  

    def draw_rectangle(self, event):  
        self.canvas.coords(self.rect_id, self.start_x, self.start_y, event.x, event.y)  

    def end_select(self, event):  
        pass  

    def delete_selected_area(self):  
        if self.rect_id:  
            x1, y1, x2, y2 = self.canvas.coords(self.rect_id)  
            self.canvas.delete(self.rect_id)  
            self.rect_id = None  
            self.clear_area(x1, y1, x2, y2)  

    def clear_area(self, x1, y1, x2, y2):  
        overlapping_items = self.canvas.find_overlapping(x1, y1, x2, y2)  
        for item in overlapping_items:  
            self.canvas.delete(item)  

    def fill_selected_area(self):  
        if self.rect_id:  
            x1, y1, x2, y2 = self.canvas.coords(self.rect_id)  
            self.canvas.delete(self.rect_id)  
            self.rect_id = None  
            self.canvas.create_rectangle(x1, y1, x2, y2, fill=self.color, outline='')  
            self.draw.rectangle([x1, y1, x2, y2], fill=self.color)  

    def save_image(self):  
        # 创建一个与画布相同大小的图像  
        x = self.canvas.winfo_width()  
        y = self.canvas.winfo_height()  
        self.image = Image.new("RGB", (x, y), "white")  
        self.draw = ImageDraw.Draw(self.image)  

        # 将画布上的所有图形绘制到Pillow图像上  
        self.canvas.update()  
        self.canvas.postscript(file="temp_canvas.eps")  # 导出为EPS文件  
        img = Image.open("temp_canvas.eps")  # 用Pillow读取EPS文件  
        
        # 获取保存路径  
        file_path = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png"), ("JPEG files", "*.jpg"), ("All files", "*.*")])  
        if file_path:  
            img.save(file_path)  # 保存为用户选择的路径  
            
        # 清理临时文件  
        import os  
        if os.path.exists("temp_canvas.eps"):  
            os.remove("temp_canvas.eps")  

    def new_canvas(self):  
        self.clear_canvas()  

    def open_image(self):  
        file_path = filedialog.askopenfilename(filetypes=[("PNG files", "*.png"), ("JPEG files", "*.jpg"), ("All files", "*.*")])  
        if file_path:  
            self.clear_canvas()  
            img = Image.open(file_path)  
            self.image = img.convert("RGB")  
            self.draw = ImageDraw.Draw(self.image)  
            self.tk_image = self.image_to_tk(self.image)  
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.tk_image)  

    def image_to_tk(self, image):  
        # Convert PIL image to PhotoImage  
        image.thumbnail((800, 600))  # Resize image to fit canvas  
        return ImageTk.PhotoImage(image)  

if __name__ == "__main__":  
    root = tk.Tk()  
    app = PaintApp(root)  
    root.mainloop()

 

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

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

相关文章

Java——数组的定义与使用

各位看官&#xff1a;如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论&#xff0c;感谢您的支持&#xff01;&#xff01;&#xff01; 一&#xff1a;数组的概念以及定义,初始化 1.1&#xff1a;数组概念以及定义 数组概念&#xff1a;可以看成…

红黑树:c++实现

1. 红⿊树的概念 红⿊树是⼀棵⼆叉搜索树&#xff0c;他的每个结点增加⼀个存储位来表⽰结点的颜⾊&#xff0c;可以是红⾊或者⿊⾊。 通过对任何⼀条从根到叶⼦的路径上各个结点的颜⾊进⾏约束&#xff0c;红⿊树确保没有⼀条路径会⽐其他路 径⻓出2倍&#xff0c;因⽽是接近平…

用LaTeX写一篇帅帅的算法学习题解

前言 先来看看用 LaTeX \text{LaTeX} LaTeX 写出来的题解是啥样&#xff0c;内容是瞎写的。 前提知识与环境 默认已经掌握了 LaTeX \text{LaTeX} LaTeX 的一些用法&#xff0c;特别是公式如何写&#xff0c;如果你对这块还是很了解&#xff0c;可以先学着使用 Typora \…

DEEP TEMPORAL GRAPH CLUSTERING.md

ICLR23 推荐指数&#xff1a; #paper/⭐ 原因的话&#xff0c;可以找找前人的一篇文章(可以看&#xff0c;但是当你阅读前人文章会发现。) 动机/优点 很明确&#xff0c;时序图只需要考虑时间相近的点&#xff0c;因此开销特别小。但是邻接矩阵&#xff0c;就要考虑所有点的关…

Dockerfile最佳实践:如何创建高效的容器

在微服务和云计算时代&#xff0c;Docker就已经成为应用开发和部署不可或缺的工具。如今虽处大模型时代&#xff0c;但这些基础技术仍然是我们需要掌握的。 容器化允许开发者将应用程序及其依赖打包到一个单一的、可移植的单元中&#xff0c;确保了可预测性、可扩展性和快速部…

反射机制(Reflection)

1. 反射 Java的反射机制(reflection)是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff1b;这种动态获取信息以及动态调用对象方法的功能称为java语言的反…

创建一个c#程序,实现字符串类型转整数类型

首先&#xff0c;创建一个c#程序 在代码编辑器中编写代码&#xff0c;点击Run按钮或者按下F5键来运行程序。 下面&#xff0c;编写将字符串类型转换为整数类型的代码。 sing System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…

安装samples/1_Utilities/deviceQuery等文件

本文章摘抄来自https://zhuanlan.zhihu.com/p/666647168 从cuda11.6开始cuda toolkit就不自带cuda-samples了&#xff0c;而deviceQuery又是cuda-sample的一个子库&#xff0c;所以需要自己手动装一下。 我的系统是ubuntu20.04&#xff0c;已经安装了CUDA Toolkit 12.2。 第…

【深度学习】使用FasterRCNN模型训练自己的数据集(记录全流程

此处用的FasterRCNN模型使用的是B导的源码&#xff0c;读者可以去B站搜B导的视频进行了解和学习&#xff0c;视频中B导非常细心讲解了如何训练自己的数据集以及预测。 文章目录 前言一、准备数据集二、环境配置2.1 基础环境2.2 其他依赖包安装2.3 预训练权重下载 二、训练数据集…

程序员成长秘籍:是迈向管理巅峰,还是深耕技术架构?

专业在线打字练习平台-巧手打字通&#xff0c;只输出有价值的知识。 一 管理和架构 做技术的同学一般有两条职业发展路径&#xff0c;横向的管理路线和纵向的技术路线。管理路线对应的是管理岗&#xff0c;讲究的是排兵布阵&#xff0c;通过各种资源的优化配置发挥价值。技术路…

(Linux驱动学习 - 10).MISC驱动实验

一.MISC介绍 1.MISC定义 misc 的意思是混合、杂项的&#xff0c;因此 MISC 驱动也叫做杂项驱动&#xff0c;也就是当我们板子上的某 些外设无法进行分类的时候就可以使用 MISC 驱动。 MISC 驱动其实就是最简单的字符设备驱 动&#xff0c;通常嵌套在 platform 总线驱动中&…

智能贴身监测,健康生活建议,圆道妙医智能手表体验

如今热衷于运动和健康生活的爱好者越来越多&#xff0c;相关的赛事等活动也是逐年增多&#xff0c;很多朋友为了能够直观的了解自己的健康状况&#xff0c;都会配备一款智能手表&#xff0c;这样戴在身上就可以随时了解自己的心率、血氧等数据。最近我尝试了一款圆道妙医推出的…

MobaXterm连接Cloudflare Tunnel内网穿透的SSH

背景 如官方文档所示&#xff0c;Cloudflare Tunnel要求我们对SSH客户端进行配置&#xff0c;使本地的cloudflared软件代理SSH才能连接。 存在问题 由于MobaXterm的Session实质为嵌入式PuTTY&#xff0c;不使用OpenSSH样式的配置文件&#xff08;即~/.ssh/config&#xff09…

SpringBoot框架下购物推荐网站的设计模式与实现

3系统分析 3.1可行性分析 通过对本东大每日推购物推荐网站实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本东大每日推购物推荐网站采用JAVA作为开发语言&…

对层级聚类树进行模块分割,定位基因在哪个模块中

拷贝数据到 ImageGP (http://www.ehbio.com/Cloud_Platform/front/#/analysis?pageb%27Ng%3D%3D%27)&#xff0c;并设置参数. ID untrt_N61311 untrt_N052611 untrt_N080611 untrt_N061011 trt_N61311 trt_N052611 trt_N080611 trt_N061011 ENSG000…

【ROS2实操二】服务通信

简介 服务通信也是ROS中一种极其常用的通信模式&#xff0c;服务通信是基于请求响应模式的&#xff0c;是一种应答机制。也即&#xff1a;一个节点A向另一个节点B发送请求&#xff0c;B接收处理请求并产生响应结果返回给A。比如如下场景&#xff1a;机器人巡逻过程中&#xff0…

cuda入门学习

最近接触cuda 编程&#xff0c;记录一下。 1 工作实现一个【0-100&#xff09;的加法 如果用python sum 0 for i in range(200):sumi print(sum)2 cuda 的一些简单的概念 一维情况下大概是这样的 (1个grid * 2个blocks * 4个thread) 3 代码直接上代码 我把100分为20个b…

Jenkins---01

什么是敏捷开发 敏捷开发以用户的需求进化为核心&#xff0c;采用迭代、循序渐进的方法进行软件开发。在敏捷开 发中&#xff0c;软件项目在构建初期被切分成多个子项目&#xff0c;各个子项目的成果都经过测试&#xff0c;具备可视、 可集成和可运行使用的特征。换言之&…

2024年编程资料【9月份部分】

资料列表 「CSDN会员免费电子书1000本」 https://pan.quark.cn/s/5019390a751a 【黑马程序员】年度钻石会员-人工智能AI进阶 https://pan.quark.cn/s/1d14a2a179c2 JavaScript从入门到高级教程 - 带源码课件 https://pan.quark.cn/s/c16ed07eac93 【马哥教育】云原生微服务治理…

测试常用插件: ModHeader - Modify HTTP headers插件进行IP模拟/IP欺骗

由于公司是做海外项目的&#xff0c;所以付款时有要求进行模拟不同IP登录进去时会优先显示该地区的支付方式。 1.安装插件 这里以Microsoft Edge为例&#xff0c;打开扩展 搜索&#xff1a;ModHeader - Modify HTTP headers&#xff0c;进行获取安装即可 安装完成后&#xff…