我试图将可移动的针(指针)放在仪表(仪表)的固定图形上。通过在缓冲图形上使用矩阵旋转来移动针。我可以得到固定的图形和针头显示。但是当我渲染到屏幕时,最后放置的图像会删除先前的图形。我正在使用计时器来获取针动画和轨迹栏输入以产生运动。针做了我正在寻找的确切运动。
我无法让固定的背景和针头同时出现。
有什么想法吗?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Dial01
{
public partial class dial01Form : Form
{
// Establishes timer for graphics animation
private Timer timer01 = new Timer();
/* Establishes a graphic buffer to write to
* prior display on screen */
private Graphics myGraphics;
private BufferedGraphics myBufferedGraphics1;
// Establishes manager for embedded resources (Images)
private System.Resources.ResourceManager myRM = new
System.Resources.ResourceManager("Resources.resx",
System.Reflection.Assembly.GetExecutingAssembly());
int y = 0; // Rotation value
Graphics g,g1; // Graphics objects
public dial01Form()
{
// Establishes size of Dial01Form
this.Width = 500;
this.Height = 500;
// Gets reference to the current BufferedGraphicsContext
BufferedGraphicsContext myContext1 = BufferedGraphicsManager.Current;
// Specifically sets maximum buffer size
myContext1.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
// Sets the buffer size
myBufferedGraphics1 = myContext1.Allocate(this.CreateGraphics(),
new Rectangle(0, 0, this.Width, this.Height));
// Actvates timer and sets interval
timer01.Enabled = true;
timer01.Tick += onTimer;
timer01.Interval = 20;
timer01.Start();
// Initializes form components
InitializeComponent();
}
private void onTimer(object sender, System.EventArgs e)
{
myGraphics = this.CreateGraphics();
// Initializes graphics buffer variable
g1 = myBufferedGraphics1.Graphics;
// Clears graphic buffer with a color
g1.Clear(SystemColors.Control);
// Initializes an image variable for Dial Outline
Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250;
// Draw Dial Outline to graphics buffer
myGraphics.DrawImage(dial01Outline, (ClientSize.Width / 2) - 100,
(ClientSize.Height / 2) - 100);
// Goto drawPointer method passing trackBar1 value
drawPointer(trackBar1.Value);
// Render buffered graphics to screen
// myBufferedGraphics.Render(Graphics.FromHwnd(this.Handle));
myBufferedGraphics1.Render();
}
public int drawPointer(int trkBarValue)
{
int x = trkBarValue;
y = 0;
if (225 + x <= 360) { y = 222 + x; }
else if (225 + x > 360) { y = x - 135; }
// These two labels are for testing purposes
label1.Text = ("Trk Bar Val = " + x).ToString();
label2.Text = ("Ptr value = " + y).ToString();
y = y + 180;
// Matrix rotation to pointer
Matrix myMatrix = new Matrix();
myMatrix.Rotate(y, MatrixOrder.Append);
myMatrix.Translate(this.ClientSize.Width / 2,
this.ClientSize.Height / 2, MatrixOrder.Append);
g1.Transform = myMatrix;
// Pointer polygon
PointF point1 = new PointF(0.0F, 0.0F);
PointF point2 = new PointF(0.0F, 50.0F);
PointF point3 = new PointF(3.0F, 55.0F);
PointF point4 = new PointF(7.0F, 50.0F);
PointF point5 = new PointF(7.0F, 0.0F);
PointF[] polyPoints =
{
point1,
point2,
point3,
point4,
point5
};
g1.FillPolygon(Brushes.Black, polyPoints);
return y;
}
private void dial01Form_Load(object sender, EventArgs e)
{
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
}
}
}
答案 0 :(得分:1)
您采用的一般图形方法不适用于winforms应用。
图形在winforms中的工作方式,只要窗体被覆盖/未覆盖/调整大小/等,Windows就会让它重新绘制自己。您在CreateGraphics
完成的任何操作都将被覆盖。这就是你不应该致电CreateGraphics
的原因。
相反,您应该通过Paint
事件拦截重新绘制过程,并在那里进行所有自定义绘制。您仍然可以在计时器上重新绘制,只需在计时器内调用Invalidate()
,这会导致表单尽快重新绘制。
这是&#34;正确方式的一般形状&#34;这样做:
public partial class dial01Form : Form
{
private Timer timer01 = new Timer();
int y = 0; // Rotation value
public dial01Form()
{
// Establishes size of Dial01Form
this.Width = 500;
this.Height = 500;
// Actvates timer and sets interval
timer01.Enabled = true;
timer01.Tick += onTimer;
timer01.Interval = 20;
timer01.Start();
// handle the paint event
this.Paint += OnPaint;
// Initializes form components
InitializeComponent();
}
private void OnPaint(object sender, PaintEventArgs e)
{
// all painting here, targeting e.Graphics
e.Graphics.Clear(SystemColors.Control);
Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250;
e.Graphics.DrawImage(dial01Outline, (ClientSize.Width / 2) - 100,
(ClientSize.Height / 2) - 100);
drawPointer(e.Graphics, trackBar1.Value);
}
private void onTimer(object sender, System.EventArgs e)
{
this.Invalidate();
}
public int drawPointer(Graphics g1, int trkBarValue)
{
// elided: same code as before, but using the g1 parameter instead of a field
}
}
我认为你不应该遇到闪烁问题 - 默认情况下启用双缓冲。确保您的表单DoubleBuffered
属性设置为True。