C# Windows Forms实现绘制画板

news2024/9/20 12:35:42

目录

C# Windows Forms上绘制画板:

详细解释:

TempData临时数据,用来保存画笔相关的信息,如:颜色,大小,坐标等

类声明和成员变量

 构造函数

文件菜单项点击事件 

 保存菜单项点击事件

 画笔大小选择

 颜色选择

清空画布 

 鼠标事件处理

 完整代码:

总结

详细解释:

TempData临时数据,用来保存画笔相关的信息,如:颜色,大小,坐标等

public static class TempData
{
    /// <summary>
    /// 用来保存上一次坐标点
    /// </summary>
    public static Point PrevPoint { get; set; }

    /// <summary>
    /// 画笔的颜色
    /// </summary>
    public static Color PenColor { get; set; } = Color.Black;

    /// <summary>
    /// 画笔的粗细
    /// </summary>
    public static int PenWidth { get; set; } = 2;

    
}

类声明和成员变量

  • Form1 类继承自 Form,表示一个Windows表单。
  • paintStart 是一个布尔变量,用于跟踪鼠标是否按下,从而开始绘图。
  • g 是一个 Graphics 对象,用于在窗体控件上绘制图像。
  • bmp 是一个 Bitmap 对象,用作绘图的画布。
    public partial class Form1 : Form
    {
        bool paintStart = false; // 标识是否开始绘画
        Graphics g = null; // 用于绘制图形的Graphics对象
        Bitmap bmp = null; // 用于存储绘制内容的Bitmap对象

 构造函数

  • InitializeComponent 方法用于初始化窗体上的控件。
  • g 被初始化为 panel2 的 Graphics 对象。
  • bmp 被初始化为一个与 panel2 控件大小相同的 Bitmap 对象。
    public Form1()
    {
        InitializeComponent();
        g = panel2.CreateGraphics();
        bmp = new Bitmap(panel2.Width, panel2.Height);
    }

文件菜单项点击事件 

  • 打开一个文件对话框,让用户选择一个JPG图片文件。
  • 如果用户选择了文件并点击了OK,当前的 Bitmap 对象 bmp 被替换为用户选择的图片。
  • 使用 Graphics 对象 g 将新的 Bitmap 绘制到 panel2 上。
    private void 文件FToolStripMenuItem_Click(object sender, EventArgs e)
    {
        OpenFileDialog dlg = new OpenFileDialog();
        dlg.Filter = "图片(*.jpg)|*.JPG";
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            bmp = new Bitmap(dlg.FileName);
            g.DrawImage(bmp, new Point(0, 0));
        }
    }

 保存菜单项点击事件

  • 打开一个保存文件对话框,让用户选择保存路径和文件名。
  • 如果用户选择了路径并点击了OK,尝试将当前的 Bitmap 对象 bmp 保存为JPG图片。
  • 如果保存过程中发生异常(例如文件被其他程序占用),显示一个错误消息。
    private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
    {
        SaveFileDialog saveFileDialog = new SaveFileDialog();
        saveFileDialog.Filter = "图片(*.jpg)|*.JPG";
        if (saveFileDialog.ShowDialog() == DialogResult.OK)
        {
            try
            {
                bmp.Save(saveFileDialog.FileName);
            }
            catch (Exception)
            {
                MessageBox.Show("保存的文件名称,已经被独占打开!重新输入新文件名!");
            }
        }
    }

 画笔大小选择

  • 这些方法设置画笔的大小,TempData.PenWidth 存储当前选择的画笔宽度。
    private void 小号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        TempData.PenWidth = 2;
    }
    
    private void 中号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        TempData.PenWidth = 6;
    }
    
    private void 大号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        TempData.PenWidth = 10;
    }

 颜色选择

  • 打开一个颜色对话框,让用户选择画笔的颜色。
  • 如果用户选择了颜色并点击了OK,将选择的颜色存储在 TempData.PenColor 中。清空画布
    private void 颜色ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        ColorDialog colorDialog = new ColorDialog();
        if (colorDialog.ShowDialog() == DialogResult.OK)
        {
            TempData.PenColor = colorDialog.Color;
        }
    }

清空画布 

  • 显示一个确认对话框,询问用户是否确定要清空画布。
  • 如果用户点击“Yes”,清空 panel2 的内容,重新创建一个空白的 Bitmap 对象,并将其绘制到 panel2 上。
    private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        DialogResult dr = MessageBox.Show("你确定要清空吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        if (dr == DialogResult.Yes)
        {
            g.Clear(Color.White);
            bmp = new Bitmap(panel2.Width, panel2.Height);
            g.DrawImage(bmp, new Point(0, 0));
        }
    }

 鼠标事件处理

  • MouseDown: 当用户在 panel2 上按下鼠标左键时,设置 paintStart 为 true 并记录当前鼠标位置。
  • MouseMove: 当用户在 panel2 上移动鼠标时,如果 paintStart 为 true,则根据选择的工具(画笔或橡皮擦)绘制线条或擦除区域。
  • MouseUp: 当用户在 panel2 上释放鼠标左键时,设置 paintStart 为 false,停止绘图。
    private void panel2_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            paintStart = true;
            TempData.PrevPoint = new Point(e.X, e.Y);
        }
    }
    
    private void panel2_MouseMove(object sender, MouseEventArgs e)
    {
        Graphics g2 = Graphics.FromImage(bmp);
        Pen pen = new Pen(TempData.PenColor, TempData.PenWidth);
        Point pt2 = new Point(e.X, e.Y);
        if (rbPen.Checked && paintStart)
        {
            g2.DrawLine(pen, TempData.PrevPoint, pt2);
            TempData.PrevPoint = pt2;
            g.DrawImage(bmp, 0, 0);
        }
        else if (rbEraser.Checked && paintStart)
        {
            g2.FillRectangle(new SolidBrush(panel2.BackColor), e.X, e.Y, TempData.PenWidth + 50, TempData.PenWidth + 50);
            g.DrawImage(bmp, 0, 0);
        }
    }
    
    private void panel2_MouseUp(object sender, MouseEventArgs e)
    {
        paintStart = false;
    }

 完整代码:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace _2.画板
{
    public partial class Form1 : Form
    {
        // 标识,表示是否开始绘画
        bool paintStart = false;
        // 画板1(用panel2创建的,主要用来显示图)
        Graphics g = null;
        // 保存的图片  BitMap位图(.bmp), Image图片(.jpg,.jpeg,.png)
        Bitmap bmp = null;

        public Form1()
        {
            InitializeComponent();
            // 创建画板实例
            g = panel2.CreateGraphics();
            // 创建图片实例,设置宽高
            bmp = new Bitmap(panel2.Width, panel2.Height);
        }

        private void 文件FToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "图片(*.jpg)|*.JPG"; // 图片(*.jpg)|*.JPG|所有文件(*.*)|*.*
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                bmp = new Bitmap(dlg.FileName);
                g.DrawImage(bmp, new Point(0, 0));//重新绘制画板
            }
        }

        private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "图片(*.jpg)|*.JPG";
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    bmp.Save(saveFileDialog.FileName);
                }
                catch (Exception)
                {
                    MessageBox.Show("保存的文件名称,已经被独占打开!重新输入新文件名!");
                }
            }
        }

        private void 小号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TempData.PenWidth = 2;
        }

        private void 中号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TempData.PenWidth = 6;
        }

        private void 大号画笔ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TempData.PenWidth = 10;
        }

        private void 颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                TempData.PenColor = colorDialog.Color;
            }
        }

        private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("你确定要清空吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == DialogResult.Yes)
            {
                g.Clear(Color.White); // 清空画板1
                bmp = new Bitmap(panel2.Width, panel2.Height); // 重新创建bmp实例,清空图片内容
                g.DrawImage(bmp, new Point(0, 0)); //用清空后的图片重新绘制画板1
            }
        }

        private void panel2_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                paintStart = true;

                // MouseEventArgs类型的实例中,拥有坐标系统
                // EventArgs
                TempData.PrevPoint = new Point(e.X, e.Y);
            }
        }

        private void panel2_MouseMove(object sender, MouseEventArgs e)
        {
            // 用空白图片bmp当成画板的底板,重新生成一个画板2,画板2上画的图其实是画在bmp。
            // 为什么要创建两个画板:画板1为了画图并显示。画板2为了保存绘制的图片,橡皮擦。
            // 两个画板上的图保持一致。
            Graphics g2 = Graphics.FromImage(bmp);

            Pen pen = new Pen(TempData.PenColor, TempData.PenWidth);
            Point pt2 = new Point(e.X, e.Y);
            if (rbPen.Checked && paintStart)
            {
                g2.DrawLine(pen, TempData.PrevPoint, pt2);
                TempData.PrevPoint = pt2;
                g.DrawImage(bmp, 0, 0); // 把bmp上的图,重新再绘制到画板1上展示出来。
            }
            else if (rbEraser.Checked && paintStart)
            {
                g2.FillRectangle(new SolidBrush(panel2.BackColor), e.X, e.Y, TempData.PenWidth + 50, TempData.PenWidth + 50);
                g.DrawImage(bmp, 0, 0);  // 为了同步g和g2两个画板。
            }
        }

        private void panel2_MouseUp(object sender, MouseEventArgs e)
        {
            paintStart = false;
        }
    }
}

总结

这个程序实现了一个基本的绘图工具,允许用户加载图片、保存图片、选择画笔大小和颜色,并在 panel2 控件上进行绘图。它通过处理鼠标事件来实现绘图功能,并通过 Graphics 对象在 Bitmap 上绘制,然后将 Bitmap 显示在 panel2 上。

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

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

相关文章

浙大数据结构:03-树2 List Leaves

这道题我借用了一点上一题的代码思路&#xff0c;这题考察的主要是层序遍历&#xff0c;即用队列来实现&#xff0c;当然此处我依然采用数组模拟队列来实现。 机翻 1、条件准备 map的键存下标&#xff0c;后面值分别存左右子树的下标&#xff0c;没有子树就存-1. head数组只…

python脚本源码如何使用PyOxidizer编译Windows可执行文件

使用 PyOxidizer 将上述代码编译为 Windows 可执行文件&#xff0c;可以按照以下步骤进行&#xff1a; 一、准备工作 确保已经安装了 PyOxidizer 和 Rust 开发环境&#xff0c;如前文所述。 二、创建 PyOxidizer 配置文件 创建一个名为pyoxidizer.toml的配置文件&#xff0c;内…

go急速入门API开发

go急速入门 1、安装Go和对应编辑器2、编写helloWord3、项目目录开发4、编写一个http服务器5、 使用Gin框架基本使用使用部分中间件自定义中间件 6、部署 1、安装Go和对应编辑器 go官网&#xff0c;下载自己电脑对应版本即可。安装完成之后打开cmd输入go即可弹出对应提示。 对…

ffmpeg(各个系统版本安装- Windows11-Mac-Linux)

各个系统上的安装不建议使用编译安装&#xff0c;大佬的话可以 编译安装会各种环境问题&#xff0c;直接使用别人安装好的就行 1.Windows11上安装ffmpeg 1.官网下载ffmpeg 进入Download FFmpeg网址&#xff0c;点击下载windows版ffmpeg&#xff0c;使用别人编译好的版本即可 …

文法的例题

答案&#xff1a;B 知识点&#xff1a; 文法 一个形式文法是一个有序四元组G{V,T,S,P}&#xff0c;其中&#xff1a; V&#xff1a;非终结符。不是语言组成部分&#xff0c;不是最终结果&#xff0c;可理解为占位符 T&#xff1a;终结符。是语言的组成部分&#xff0c;是最…

自用NAS系列1-设备

拾光坞 拾光坞多账号绑定青龙面板SMBWebdav小雅alist下载到NASDocker安装迅雷功能利用qBittorrentEEJackett打造一站式下载工具安装jackett插件 外网访问内网拾光客户端拾光穿透公网ipv6路由器配置ipv6拾光坞公网验证拾光坞域名验证 拾光坞 多账号绑定 手机注册拾光坞账号&am…

Web Bluetooth 与点对点连接

前言 需求需要实现手持终端设备与 web 网页的点对点数据传输&#xff0c;不希望有服务器参与&#xff0c;想到了 web 的 USB 与 Bluetooth API&#xff0c;对 Web Bluetooth API 进行了研究。 蓝牙 GATT 基础知识 GATT&#xff08;通用属性配置文件&#xff0c;蓝牙低功耗&a…

K8S 发布应用

前言 昨儿个用 unbuntu20.04 又装了一次K8S 用的 kubeadm containerd Cilium (CNI) 又重新撸了一遍 这里只记录 应用发布的笔记 正文 #创建deployment kubectl create deployment nginx --imagenginx #我这边大约30秒后显示为 ready kubectl get deployments kubectl desc…

4.7 Sensors -- useScroll

4.7 Sensors – useScroll https://vueuse.org/core/useScroll/ 作用 响应式的监听滚动位置和状态。 官方示例 <script setup lang"ts"> import { useScroll } from vueuse/coreconst el ref<HTMLElement | null>(null) const { x, y, isScrolling…

【Python系列】只更新非空的字段

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

数字电路专题:verilog 阻塞赋值和非阻塞赋值

verilog 阻塞赋值 和 非阻塞赋值 “”阻塞赋值&#xff0c; ”<”非阻塞赋值。阻塞赋值为执行完一条赋值语句&#xff0c;再执行下一条&#xff0c;可理解为顺序执行&#xff0c;而且赋值是立即执行&#xff1b; 非阻塞赋值可理解为并行执行&#xff0c;不考虑顺序&#x…

【python计算机视觉编程——7.图像搜索】

python计算机视觉编程——7.图像搜索 7.图像搜索7.1 基于内容的图像检索&#xff08;CBIR&#xff09;从文本挖掘中获取灵感——矢量空间模型&#xff08;BOW表示模型&#xff09;7.2 视觉单词**思想****特征提取**&#xff1a; 创建词汇7.3 图像索引7.3.1 建立数据库7.3.2 添加…

构建并训练卷积神经网络(CNN)对CIFAR-10数据集进行分类

深度学习实践&#xff1a;构建并训练卷积神经网络&#xff08;CNN&#xff09;对CIFAR-10数据集进行分类 引言 在计算机视觉领域中&#xff0c;CIFAR-10数据集是一个经典的基准数据集&#xff0c;广泛用于图像分类任务。本文将介绍如何使用PyTorch框架构建一个简单的卷积神经…

微信小程序uniappvue3版本-控制tabbar某一个的显示与隐藏

1. 首先在pages.json中配置tabbar信息 2. 在代码根目录下添加 tabBar 代码文件 直接把微信小程序文档里面的四个文件复制到自己项目中就可以了 3. 根据自己的需求更改index.js文件 首先我这里需要判断什么时候隐藏某一个元素&#xff0c;需要引入接口 然后在切换tabbar时&#…

git:认识git和基本操作(1)

目录 一、版本控制器 1.安装git 2.创建git本地仓库 3.配置git 二、git操作&#xff08;1&#xff09; 1.工作区、暂存区、版本库 2.添加文件 3.查看.git 4.修改文件 一、版本控制器 所谓的版本控制器&#xff0c;就是能让你了解到每一个文件的修改历史。相应的&#x…

Maven的安装

一、安装 压缩包解压完的目录如下所示&#xff08;此处为绿色免安装版&#xff09;&#xff1a; &#xff08;其余三个文件是针对Maven版本&#xff0c;第三方软件等简要介绍&#xff09; 二、环境变量 前提&#xff1a; jdk最低版本为JAVA7&#xff08;即jdk17&#xff09…

R语言统计分析——重复测量方差分析

参考资料&#xff1a;R语言实战【第2版】 所谓重复测量方差分析&#xff0c;即受试者被测量不止一次。本例使用数据集市co2数据集&#xff1a;因变量是二氧化碳吸收量&#xff08;uptake&#xff09;&#xff0c;自变量是植物类型&#xff08;Type&#xff09;和七种水平的二氧…

Gitness 基础安装

文章目录 Docker 安装注册账户创建项目导入已有仓库配置 Github Token同步源代码仓库 官方链接 Gitness was the next step in the evolution of Drone, from continuous integration to source code hosting, bringing code management and pipelines closer together. Gitnes…

自动化表格处理的革命:智能文档系统技术解析

在当今数据驱动的商业环境中&#xff0c;表格数据的自动化处理成为了企业提高效率、降低成本的关键。企业智能文档系统在智能表格识别方面展现出卓越的性能&#xff0c;通过精准识别和处理各种通用表格&#xff0c;显著提升了企业文档管理的智能化水平。本文将深入探讨该系统在…

STM32的使用方法一

注:我采用的是STM32F103RC芯片、相应的电路图和STM32CubeIDE软件这是在STM32CubeIDE软件定义芯片后&#xff0c;所给的必要的代码逻辑&#xff0c;加上了注释 #include "main.h"/* Private variables ---------------------------------------------------------*//…