如何在 UserControl Paint 事件中对点进行动画处理?

2024-01-05

在绘画事件中,因为我希望能够控制点大小颜色和更多属性。

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;

public partial class LoadingLabel : UserControl
{
    public LoadingLabel()
    {
        InitializeComponent();
    }

    private void LoadingLabel_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.FillEllipse(Brushes.Red, 1, 1, 20, 20);
        Thread.Sleep(1);
        e.Graphics.FillEllipse(Brushes.Red, 1, 1, 0, 0);
        Thread.Sleep(1);
    }
}

我首先尝试制作一个简单的点,该点在一段时间后消失,然后再次显示,但它不起作用,我看到一个红色的静止点(点)。

稍后当它起作用时,我想制作 3 个点的动画,就像加载动画一样。

这是我尝试过的:

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;

public partial class LoadingLabel : UserControl
{
    private bool animate = false;

    public LoadingLabel()
    {
        InitializeComponent();
        timer1.Enabled = true;
    }

    private void LoadingLabel_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        if (animate == false)
        {
            e.Graphics.FillEllipse(Brushes.Red, 1, 1, 20, 20);
        }
        else
        {
            e.Graphics.FillEllipse(Brushes.Red, 5, 1, 20, 20);
        }
    }

    int count = 0;
    private void timer1_Tick(object sender, EventArgs e)
    {
        count++;

        if(count == 10 && animate == false)
        {
            animate = true;
        }

        if(count == 20 && animate)
        {
            animate = false;
            count = 0;
        }
        this.Invalidate();
    }
}

结果是第一个点绘制,然后是第二个点绘制,但第一个点消失了:

看起来该点向右移动,然后又回到左侧。

但我想要3点的加载效果。并且不移动点。

这适用于 3 点,但对于 3 点来说看起来太复杂了。如果我想要 100 分呢?

也许我应该在绘画事件中使用循环?

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;

public partial class LoadingLabel : UserControl
{
    private int numofpoints = 0;

    public LoadingLabel()
    {
        InitializeComponent();
        timer1.Enabled = true;
    }

    private void LoadingLabel_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        if(numofpoints == 0)
        {
            e.Graphics.FillEllipse(Brushes.Red, 1, 1, 20, 20);
        }
        if(numofpoints == 1)
        {
            e.Graphics.FillEllipse(Brushes.Red, 5, 1, 20, 20);
        }
        if(numofpoints == 2)
        {
            e.Graphics.FillEllipse(Brushes.Red, 10, 1, 20, 20);
        }
    }

    int count = 0;
    private void timer1_Tick(object sender, EventArgs e)
    {
        count++;

        if(count == 10)
        {
            numofpoints = 0;
        }

        if(count == 20)
        {
            numofpoints = 1;
        }

        if(count == 30)
        {
            numofpoints = 2;
            count = 0;
        }
        this.Invalidate();
    }
}

我尝试过的另一个更新:

 using System.ComponentModel;
 using System.Drawing;
 using System.Drawing.Drawing2D;
    
 public partial class LoadingLabel : UserControl
 {
     private List<PointF> points = new List<PointF>();

     public LoadingLabel()
     {
         InitializeComponent();
         points.Add(new PointF(0, 0));
         timer1.Enabled = true;
     }

     private void LoadingLabel_Paint(object sender, PaintEventArgs e)
     {
         e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            
         for (int i = 0; i < points.Count; i++)
         {
             e.Graphics.FillEllipse(Brushes.Red, points[i].X, points[i].Y, 20, 20);
         }
     }

     int count = 0;
     private void timer1_Tick(object sender, EventArgs e)
     {
         count++;

         if (count < 3)
         {
             points.Add(new PointF(count * 20, 0));
             //points = new List<PointF>();
         }
         //this.Invalidate();
     }
 }

如果我在勾选事件中创建实例,它将不会绘制任何内容。如果我使用无效线,它会使点像闪烁一样。 我想要的是创建一个加载效果动画。

现在代码的结果仍然是 3 点,我想像链接中那样对它们进行动画处理。

像这样的事情:


因为,根据您发布的图像,您想要为一系列点设置动画,其中只有active一改变颜色,您的用户控件可以定义允许指定点的数量、点的颜色和点的颜色的属性active Dot.

计时器可用于更改当前活动的点,因此绘制过程知道何时更改其中一个点的颜色。

当指定的点数发生变化时,UserControl 会自动调整大小。
此外,当首次创建 UserControl 时,它会设置其MinimumSize,因此点始终可见。

您可以在此基础上进行扩展template,添加更多功能。


请注意 UserControl 构造函数中的这些行:

components = new Container();
dotsTimer = new Timer(components) { ... };

这指示定时器组件将自身添加到父容器的组件中,因此当父容器被释放时,定时器也被释放并且其事件处理程序被删除。

Setting DoubleBuffered = true;避免绘制点时闪烁。


致电Start()启动动画的方法和Stop()方法来阻止它。

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;

public partial class LoadingLabel : UserControl {

    private int m_NumberOfDots = 5;
    private Color m_DotColor = Color.Cyan;
    private Color m_DotActiveColor = Color.Blue;
    private float dotSize = 20.0f;
    private float dotSpacing = 20.0f;
    private int currentDot = 0;
    private Timer dotsTimer = null;

    public LoadingLabel()
    {
        InitializeComponent();
        components = new Container();
        dotsTimer = new Timer(components) { Interval = 200 };
        dotsTimer.Tick += DotsTimer_Tick;

        DoubleBuffered = true;
        Padding = new Padding(5);
    }

    [DefaultValue(5)]
    public int NumberOfDots {
        get => m_NumberOfDots;
        set {
            value = Math.Max(3, Math.Min(value, 7));
            if (m_NumberOfDots != value) {
                m_NumberOfDots = value;

                bool running = dotsTimer.Enabled;
                Stop();
                SetMinSize();
                if (running) Start();
            }
        }
    }

    [DefaultValue(typeof(Color), "Cyan")]
    public Color DotColor { 
        get => m_DotColor;
        set {
            m_DotColor = value;
            Invalidate();
        } 
    }

    [DefaultValue(typeof(Color), "Blue")]
    public Color DotActiveColor { 
        get => m_DotActiveColor;
        set {
            m_DotActiveColor = value;
            Invalidate();
        } 
    }

    protected override void OnPaint(PaintEventArgs e) {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        for (int dot = 0; dot < m_NumberOfDots; dot++) {
            var color = dot == currentDot ? DotActiveColor : DotColor;
            var pos = Padding.Left + (dotSize + dotSpacing) * dot;
            using (var brush = new SolidBrush(color)) {
                e.Graphics.FillEllipse(brush, pos, Padding.Top, dotSize, dotSize);
            }
        }
        base.OnPaint(e);
    }

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        SetMinSize();
    }

    protected override void OnHandleDestroyed(EventArgs e) {
        Stop();
        base.OnHandleDestroyed(e);
    }

    private void DotsTimer_Tick(object sender, EventArgs e) {
        currentDot += 1;
        currentDot %= m_NumberOfDots;
        Invalidate();
    }

    public void Start() => dotsTimer.Start();

    public void Stop() {
        dotsTimer.Stop();
        currentDot = 0;
        Invalidate();
    }

    private void SetMinSize() {
        var width = Padding.Left + Padding.Right + 
            (dotSize * m_NumberOfDots) + (dotSpacing * (m_NumberOfDots - 1)) + 1;
        var height = Padding.Top + Padding.Bottom + dotSize + 1;
        MinimumSize = new Size((int)width, (int)height);
        Size = MinimumSize;
    }
}

它是这样工作的:


一经请求,这是 PasteBin https://pastebin.com/4XNTwn5W用于选择颜色的自定义组合框控件的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 UserControl Paint 事件中对点进行动画处理? 的相关文章

  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 读取文件特定行号的有效方法。 (奖励:Python 手册印刷错误)

    我有一个 100 GB 的文本文件 它是来自数据库的 BCP 转储 当我尝试导入它时BULK INSERT 我在第 219506324 行上收到一个神秘错误 在解决此问题之前 我想看看这一行 但可惜的是我最喜欢的方法 import line
  • 为什么“斜接”关节比其他关节慢?

    我在 Flash Player 中绘制线条时遇到图形问题 如果我使用任何其他线条 则以不同粗细绘制在彼此顶部的两条线条无法正确对齐JointStyle than MITER 有关效果图片以及问题的图形部分 请参阅我的帖子在 doctype
  • 如何从 .resx 文件条目获取注释

    资源文件中的字符串有名称 值和注释 The ResXResourceReader类让我可以访问名称和值 有办法看评论吗 你应该能够得到Comment via ResXDataNode class http msdn microsoft co
  • 存储来自其他程序的事件

    我想将其他应用程序的事件存储在我自己的应用程序中 事件示例 打开 最小化 Word 或打开文件时 这样的事可能吗 运行程序 http msdn microsoft com en us library ms813609 aspx and 打开
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • .Net 4.0 应用程序在 64 位上比 32 位慢(分析和可能的解决方案)(应用程序正在使用 NetAdvantage)

    我们已经用 VB NET 4 0 VS2010 编写了 NET 应用程序 并使用设置为调试和发布配置的 AnyCPU 设置的所有项目进行编译 我们注意到 当此应用程序在 64 位环境中运行 在 Windows Server 2003 R2
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 将 log4net 与 Autofac 结合使用

    我正在尝试将 log4net 与 Autofac 一起使用 我粘贴了这段代码http autofac readthedocs org en latest examples log4net html http autofac readthed
  • 如何对 Web Api 操作进行后调用?

    我创建了一个 Web API 操作 如下所示 HttpPost public void Load string siteName string providerName UserDetails userDetails implementat
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也
  • 如何在按钮单击时模拟按键 - Unity

    我对 Unity 中的脚本编写非常陌生 我正在尝试创建一个按钮 一旦单击它就需要模拟按下 F 键 要拾取一个项目 这是我当前的代码 在编写此代码之前我浏览了所有统一论坛 但找不到任何有效的东西 Code using System Colle
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 线程和 fork()。我该如何处理呢? [复制]

    这个问题在这里已经有答案了 可能的重复 多线程程序中的fork https stackoverflow com questions 1235516 fork in multi threaded program 如果我有一个使用 fork 的
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0
  • 检查Windows控制台中是否按下了键[重复]

    这个问题在这里已经有答案了 可能的重复 C 控制台键盘事件 https stackoverflow com questions 2067893 c console keyboard events 我希望 Windows 控制台程序在按下某个
  • 当另一个线程可能设置共享布尔标志(最多一次)时,是否可以读取共享布尔标志而不锁定它?

    我希望我的线程能够更优雅地关闭 因此我尝试实现一个简单的信号机制 我不认为我想要一个完全事件驱动的线程 所以我有一个工作人员有一种方法可以使用关键部分优雅地停止它Monitor 相当于C lock我相信 绘图线程 h class Drawi
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当
  • 在客户端系统中安装后桌面应用程序无法打开

    我目前正在使用 Visual Studio 2017 和 4 6 1 net 框架 我为桌面应用程序创建了安装文件 安装程序在我的系统中完美安装并运行 问题是安装程序在其他计算机上成功安装 但应用程序无法打开 edit 在客户端系统中下载了

随机推荐

  • onbeforeunload 支持检测

    我想检查当前浏览器是否支持 onbeforeunload 事件 常见的 javascript 方法似乎不起作用 if window onbeforeunload alert yes else alert no 实际上 它只检查某个处理程序是
  • 非命名空间范围错误的显式专业化......迫切需要帮助

    有人可以帮我将以下代码移植到GCC 我在这个网站上发现了很多或相关的问题 但我似乎无法在我的案例中应用建议的解决方法 typedef float MyData attribute vector size 16 template
  • 我什么时候应该使用blockingGet?

    我在工作中经常使用 RxJava 并且看到了一些调用返回 Observable 或 Single 的方法的示例 然后在其上调用blockingGet 以在不同的 我认为这可能是对图书馆和概念的滥用 但我可能是错的 我举一个小例子 publi
  • 用于多处理日志记录的 QueueHandler

    我正在尝试调整我的程序以将不同进程记录到单个日志文件中 我已经寻找解决方案很多天了 但没有成功 我想我仍然不明白队列处理程序是如何工作的 在我看来 这个过程是这样的 create q 将 qHandler 添加到主记录器 所有日志都将重定向
  • Oracle 10g:解析合并重复项的2列

    我有一个包含 3 列的表 DATE A DATE B and ISSUE DATE A and DATE B可以通过 3 种可能的方式填写 要么两者都有一个值 要么只有一个有 如下所示 DATE A DATE B ISSUE 2013030
  • org.hibernate.ejb.criteria.path.Abs​​tractPathImpl.get 处的 NullPointerException [重复]

    这个问题在这里已经有答案了 这工作正常 public Predicate toPredicate Root
  • 如何将现有的heroku应用程序拉到新位置进行开发?

    目前 我在另一台计算机上有最新版本的代码 我想用它来开发 家用计算机和笔记本电脑 供我外出时使用 我在笔记本电脑上为我的应用程序设置了heroku 现在我需要将我的代码关联到桌面上 以便我也可以从那里推送到 heroku 这是我从桌面上得到
  • 使用scala获取包中的所有类名

    我有一个包裹 package one two three 在那个包裹里我有 public trait first public class Second and pubic class Third 我想将所有类和接口 一 二 三 名称获取为
  • 如何将 CSV 文件中的批量数据导入到 DynamoDB 中?

    我正在尝试将 CSV 文件数据导入 AWS DynamoDB 我的 CSV 文件如下所示 first name last name sri ram Rahul Dravid JetPay Underwriter Anil Kumar Gur
  • 如何在非托管c++ dll中查找调用者程序集名称

    我有一个非托管 c dll 我正在从 c net 3 5 调用此非托管 dll 的外部方法 我正在寻找一种方法来找到女巫 c 程序集正在调用我的非托管 c dll 进入我的 c dll 至少是程序集的名称 当然 我不想将任何附加参数传递给方
  • 显示虚拟环境

    当我在 virtualenv 中并且它处于活动状态时 环境名称将显示在正常命令行提示符之前的括号中 看起来像 foo env User Development foo env foo where foo env是环境的名称 我想知道是否有办
  • T-SQL:在 UPDATE 语句中使用 CASE 根据条件更新某些列

    我想知道这是否可能 如果条件为真 我想更新列 x 否则将更新列 y UPDATE table SET CASE CONDITION WHEN TRUE THEN columnx ELSE columny END 25 我到处搜索 尝试了一些
  • 在 .Net 中使用 GraphQL 客户端库实施 AWS Appsync

    我正在尝试实现类似于此 python 示例但在 net 中的应用程序同步订阅https aws amazon com blogs mobile appsync websockets python https aws amazon com b
  • 在 asp.net mvc 中实现“不跟踪”

    如何实现不跟踪来自 asp net mvc3 的浏览器同意 如果用户设置了不跟踪浏览器中启用的设置 所有主要浏览器 例如 IE Firefox 和 Chrome 是否都会发送一些 cookie 同意请求 Do Not Track 仅意味着浏
  • 如何设置根视图控制器

    我设置了一个仅包含应用程序委托类的空应用程序 然后对视图控制器类进行子类化以创建 xib 来布局应用程序并建立连接 但是当我尝试在 iOS 模拟器上运行该应用程序时 出现错误 CoinToss 6212 f803 应用程序预计在应用程序启动
  • std::set of MyElement 与 MyElement::SomeMethod 作为自定义比较器

    我有一个简单的MyElement类 我想使用bool MyElement SomeMethod 作为自定义比较器std set of MyElement items 我已经进行了研究 并且已经知道一些替代解决方案 我在下面列出了这些解决方案
  • 如何检查 DataView.RowFilter 中的空白

    假设我有一个名为 A 的列 并且我想检查 A 是否为空或空白 那么使用 DataView 的 RowFilter 进行检查的正确方法是什么 DataTable dt GetData DataView dv new DataView dt d
  • 前向声明/何时最好包含标头? [复制]

    这个问题在这里已经有答案了 我很清楚何时可以 不能使用前向声明 但我仍然不确定一件事 假设我知道我迟早必须包含一个标头才能取消引用 A 类的对象 我不清楚做类似的事情是否更有效 class A class B A a void DoSome
  • Dialogflow Webhook 响应未发送到 Twilio - Twilio 调试器上出现 14103 Invalid Body 错误

    我正在实现一个通过 Twilio 与 WhatsApp 集成的聊天机器人 该机器人使用 V2 API 我已经在 Google 云上实现了集成 因为它们将被关闭 当我从 WhatsApp 触发机器人时 会触发正确的意图并执行正确的功能 但当我
  • 如何在 UserControl Paint 事件中对点进行动画处理?

    在绘画事件中 因为我希望能够控制点大小颜色和更多属性 using System ComponentModel using System Drawing using System Drawing Drawing2D public partia