在 C# 中减慢动画速度

发布于 2024-11-14 08:04:07 字数 3400 浏览 3 评论 0原文

我有一个类项目,它使用 Windows 窗体创建一个控制第二个窗体的 GUI。第二种形式是带有位图的DrawingForm。使用背景工作者,我在位图上绘制随机、连续的贝塞尔曲线。这是一个简单的程序,因此能够快速绘制它们,每秒数百个。我想添加一个滑块,它可以让我控制线条绘制的速度。换句话说,我不想将每条曲线设置为在计时器上绘制,这会导致它看起来每秒停止和启动数百次。我已经筋疲力尽地搜索谷歌,任何关于如何做到这一点的提示都会很棒。谢谢!

编辑:这是一个代码片段。该代码在我的绘图表单类中。它的构造函数是从我的主 GUI/用户控件类调用的。

    // this is the code executed by the background thread
    // it can run continously without hanging the user interface thread
    // except that it draws to a bitmap (with the bMapDC) instead of to the form
    private void backgroundWorkerDrawing_DoWork(object sender, DoWorkEventArgs e)
    {

        for (int i = 0; i < 100000000; i++)
        {
            if (scribbleOn == true)
            {
                curveColor = changeColor(curveColor);
                Pen pen = new Pen(curveColor, penThickness);

                if (i == 0) // initial curve should start in center, the rest of the points will be random
                {
                    lastX = GUI.rand.Next(0, bMapWidth); //used to store the x coordinate where the curve ends
                    lastY = GUI.rand.Next(0, bMapHeight); //used to store the y coordinate where the curve ends

                    bMapDC.DrawBezier(pen, initialX, initialY, GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight),
                    GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight), lastX, lastY);
                }

                if (i > 0) // used for all curves after the first one. 
                {
                    int tempX = GUI.rand.Next(0, bMapWidth); //used to store the x coordinate where the curve ends
                    int tempY = GUI.rand.Next(0, bMapHeight); //used to store the y coordinate where the curve ends

                    bMapDC.DrawBezier(pen, lastX, lastY, GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight),
                    GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight), tempX, tempY);

                    lastX = tempX; // sets the last x coordinate of the last curve for next loop
                    lastY = tempY;  // sets the last y coordinate of the last curve for next loop
                }
                pen.Dispose(); // free up resources from the pen object
            }   
            else i = 0;
        }
    }

    // timer event handler causes the form to be repreatedly invalidated
    // This causes the paint event handler to keep going off,
    // which causes the bMap that is continously being drawn to
    // by the background thread to be continously redisplayed in the form.
    // We will see other ways to do this that may be better.
    private void timerInvalidate_Tick(object sender, EventArgs e)
    {
        Invalidate();
    }

    private void DrawingForm_Shown(object sender, EventArgs e)
    {
        lock (bMap)
        {
            bMapHeight = bMap.Height;  // set the vars that keep track of the size of the bMap
            bMapWidth = bMap.Width;

            initialX = bMapWidth / 2; // start the curve at the center of the bMap
            initialY = bMapHeight / 2;
            bMapDC = Graphics.FromImage(bMap);  // setup the DC (device context) to allow drawing to the bMap)
            backgroundWorkerDrawing.RunWorkerAsync();   // start the background thread
            timerInvalidate.Enabled = true;  // start the timer that will cause periodic Invalidates
        }
    }

I have a class project that uses Windows Forms to create a GUI that controls a second form. The second form is a DrawingForm with a bitmap. Using a backgroundworker, I am drawing random, continuous Bezier curves all over the bitmap. It is a simple program, so it is able to draw them quickly, hundreds per second. I would like to add a slider bar that would allow me to control how fast the lines paint. In other words, I dont want to set up each curve to be drawn on a timer, which would cause it to appear to stop and start hundreds of times a second. I have exhausted myself searching google, any tips on how to do this would be awesome. Thanks!

Edit: Here is a code snippet. This code is in my class for my drawing form. Its constructor is called from my main GUI/user control class.

    // this is the code executed by the background thread
    // it can run continously without hanging the user interface thread
    // except that it draws to a bitmap (with the bMapDC) instead of to the form
    private void backgroundWorkerDrawing_DoWork(object sender, DoWorkEventArgs e)
    {

        for (int i = 0; i < 100000000; i++)
        {
            if (scribbleOn == true)
            {
                curveColor = changeColor(curveColor);
                Pen pen = new Pen(curveColor, penThickness);

                if (i == 0) // initial curve should start in center, the rest of the points will be random
                {
                    lastX = GUI.rand.Next(0, bMapWidth); //used to store the x coordinate where the curve ends
                    lastY = GUI.rand.Next(0, bMapHeight); //used to store the y coordinate where the curve ends

                    bMapDC.DrawBezier(pen, initialX, initialY, GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight),
                    GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight), lastX, lastY);
                }

                if (i > 0) // used for all curves after the first one. 
                {
                    int tempX = GUI.rand.Next(0, bMapWidth); //used to store the x coordinate where the curve ends
                    int tempY = GUI.rand.Next(0, bMapHeight); //used to store the y coordinate where the curve ends

                    bMapDC.DrawBezier(pen, lastX, lastY, GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight),
                    GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight), tempX, tempY);

                    lastX = tempX; // sets the last x coordinate of the last curve for next loop
                    lastY = tempY;  // sets the last y coordinate of the last curve for next loop
                }
                pen.Dispose(); // free up resources from the pen object
            }   
            else i = 0;
        }
    }

    // timer event handler causes the form to be repreatedly invalidated
    // This causes the paint event handler to keep going off,
    // which causes the bMap that is continously being drawn to
    // by the background thread to be continously redisplayed in the form.
    // We will see other ways to do this that may be better.
    private void timerInvalidate_Tick(object sender, EventArgs e)
    {
        Invalidate();
    }

    private void DrawingForm_Shown(object sender, EventArgs e)
    {
        lock (bMap)
        {
            bMapHeight = bMap.Height;  // set the vars that keep track of the size of the bMap
            bMapWidth = bMap.Width;

            initialX = bMapWidth / 2; // start the curve at the center of the bMap
            initialY = bMapHeight / 2;
            bMapDC = Graphics.FromImage(bMap);  // setup the DC (device context) to allow drawing to the bMap)
            backgroundWorkerDrawing.RunWorkerAsync();   // start the background thread
            timerInvalidate.Enabled = true;  // start the timer that will cause periodic Invalidates
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光清浅 2024-11-21 08:04:07

你可以创建线程并使用 sleep

private Thread SimulaciaArts;
public Animation(){
public SpleepValue { get; set;}

SimulaciaArts = new Thread(new ThreadStart(simuluj));
}

public void simuluj(){

//anything
Thread.Sleep(SleepValue);

}

,在 gui 中你必须使用 delegate

 delegate void Invoker();
 private void setSpeed()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Invoker(setSpeed));
                return;
            }
 Simulation.SleepValue=Speed;
}

希望它很好。

You can make thread and use sleep

private Thread SimulaciaArts;
public Animation(){
public SpleepValue { get; set;}

SimulaciaArts = new Thread(new ThreadStart(simuluj));
}

public void simuluj(){

//anything
Thread.Sleep(SleepValue);

}

and in gui you must use delegate

 delegate void Invoker();
 private void setSpeed()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Invoker(setSpeed));
                return;
            }
 Simulation.SleepValue=Speed;
}

Hope it is good.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文