【问题标题】:Graphics flickering when using Panel paint event [duplicate]使用面板绘制事件时图形闪烁 [重复]
【发布时间】:2015-01-04 11:11:23
【问题描述】:

我创建了一个可以根据实时正常工作的模拟时钟。

我不希望您为我或任何其他人解决它 - 我的代码已经在运行,但它在严重闪烁,并且我的知识有限,我无法确定我需要更改什么才能停止闪烁。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ClockAndStuff
{

    public partial class TheName : Form
    {

        public TheName()
        {
            InitializeComponent();
            timer1.Start();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Graphics surfaceBckg;
            Graphics surfaceMin;
            Graphics surfaceH;
            Graphics surfaceSec;

            Pen penMin = new Pen(Color.Pink,2);
            Pen penH = new Pen(Color.Red,3);
            Pen penSec = new Pen(Color.DeepPink,1);
            Pen black = new Pen(Color.Black, 4F);

            surfaceBckg = panel1.CreateGraphics();
            surfaceBckg.TranslateTransform(250, 250);
            surfaceBckg.DrawEllipse(black,-220,-220,440,440);

            surfaceMin = panel1.CreateGraphics();
            surfaceMin.TranslateTransform(250, 250);
            surfaceMin.RotateTransform(6 * DateTime.Now.Minute);

            surfaceH = panel1.CreateGraphics();
            surfaceH.TranslateTransform(250, 250);
            surfaceH.RotateTransform(30 * DateTime.Now.Hour);

            surfaceSec = panel1.CreateGraphics();
            surfaceSec.TranslateTransform(250, 250);
            surfaceSec.RotateTransform(6 * DateTime.Now.Second);

            surfaceMin.DrawLine(penMin, 0, 0, 0, -200);
            surfaceH.DrawLine(penH, 0, 0, 0, -120);
            surfaceSec.DrawLine(penSec, 0, 0, 1, -180);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            panel1.Refresh();
        } 
    }
}

根据我的任务是正确的,但我不禁认为必须有更好的方法来做到这一点。

我对 C# 还不是很了解,所以如果你能给我代码示例作为答案,那么我将能够理解它的可能性更大......

【问题讨论】:

  • timer_tick 多久被调用一次?
  • 您可以找到许多解决方案,例如thisthisthis
  • @Grundy 我已经看到了所有这些链接,但我根本无法确定如何使用它们来解决我的问题,这就是我再次询问 with 的原因我的问题的细节
  • 如果您无法弄清楚副本的解决方案与您的解决方案之间的区别:删除 all.CreateGraphics() 的调用并改用e.Graphics。阅读副本以获得解释。
  • 你没有遵循重复的解决方案并且你没有指出什么你不明白。我的评论包括一个非常简单的一句话解决方案。如果您仍然不知道该怎么做,我不知道如何更好地解释它。

标签: c# winforms graphics


【解决方案1】:

我建议创建一个启用适当双缓冲的自定义控件:

public class Canvas : Control
{
    public Canvas()
    {
        this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
        this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
        this.SetStyle( ControlStyles.UserPaint, true );
        this.SetStyle( ControlStyles.ResizeRedraw, true );
    }
}

将您的绘制代码与Paint 事件挂钩,并使用Invalidate 触发重绘。永远不要使用CreateGraphics,绘制提供给事件的图形对象。这将使您完全无闪烁绘图!

private void canvas1_Paint( object sender, PaintEventArgs e )
{
    // do your painting here, using the Graphics object passed to
    // you in the PaintEventArgs

    Pen penMin = new Pen( Color.Pink, 2 );
    Pen penH = new Pen( Color.Red, 3 );
    Pen penSec = new Pen( Color.DeepPink, 1 );
    Pen black = new Pen( Color.Black, 4f );

    e.Graphics.TranslateTransform( 250, 250 );
    e.Graphics.DrawEllipse( black, -220, -220, 440, 440 );

    e.Graphics.ResetTransform();
    e.Graphics.TranslateTransform( 250, 250 );
    e.Graphics.RotateTransform( 6 * DateTime.Now.Minute );
    e.Graphics.DrawLine( penMin, 0, 0, 0, -200 );

    e.Graphics.ResetTransform();
    e.Graphics.TranslateTransform( 250, 250 );
    e.Graphics.RotateTransform( 30 * DateTime.Now.Hour );
    e.Graphics.DrawLine( penH, 0, 0, 0, -120 );

    e.Graphics.ResetTransform();
    e.Graphics.TranslateTransform( 250, 250 );
    e.Graphics.RotateTransform( 6 * DateTime.Now.Second );        
    e.Graphics.DrawLine( penSec, 0, 0, 1, -180 );
}

【讨论】:

  • “从不使用 CreateGraphics”是什么意思?我的意思是,它显然告诉我不要使用它,但我真的不知道还能做什么。但我想有限的知识是我的问题..
  • 当我改变它时,它只是没有画手臂。例如:e.Graphics.TranslateTransform(250, 250);e.Graphics.RotateTransform(6 * DateTime.Now.Second);e.Graphics.DrawLine(penSec, 0, 0, 1, -180);
  • 那是因为当您在原始代码中创建一个新的图形对象时,您会丢失之前的转换。但是现在,当您使用相同的图形对象时,您的变换将添加到(从技术上讲,乘以)之前的变换,最终在其他地方结束。您可以使用ResetTransform 重新开始!
  • 如果 - 在原始代码中 - 每个时钟臂位于不同的表面上,以便我可以在不同的时间间隔内分别旋转每个时钟臂,这种方法是否适用?
  • 这会给你带来全新的透明度和类似问题,所以我建议不要这样做。只需在绘制每个部分之前调用ResetTransform,您的原始代码就可以正常工作。
【解决方案2】:

闪烁来自计时器滴答声,它非常快,您可以在 timer1_tick 方法中创建一个检查,以确保一秒实际上已经过了一秒,然后更新绘图。

您还可以使用计时器,告诉它何时开始以及您希望它多久更新一次。这样你就可以实时跟踪你自己的电脑了

【讨论】:

  • 哇!所以我试过了,它几乎完全停止了——只是每隔一段时间它就会闪烁几次,然后又恢复正常。没想到这么简单:)
  • 因为它是一个学校项目,我不会告诉你怎么做,但我可以给你一个地方看,但是你已经在使用的计时器上有一个间隔属性:)
  • 闪烁只是,定时器间隔较大。请查看解决方案以了解如何使其停止。这只是一个创可贴,不是治愈方法。
  • 我使用一个整数来存储当前时间(秒)来解决它,将它与每个刻度的当前时间进行比较,看看是否已经过了一秒。猜猜它不像 pro 那样,但它似乎正在工作:)
猜你喜欢
  • 2013-05-28
  • 1970-01-01
  • 2012-08-01
  • 2014-08-12
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多