【发布时间】:2014-05-21 13:07:38
【问题描述】:
我正在使用 C# windows 窗体进行一个项目,在该项目中我使用图片框来显示多个转速计。
每个图片框由一个背景图像和一个图像组成。背景图像是静态的,但图像(显示实际指示器)每秒会旋转和更新几次。
背景图片:http://i.stack.imgur.com/FBsKI.jpg
正面图片:http://i.stack.imgur.com/T0nJU.jpg
只要我有一个或两个转速计同时运行,它就可以很好地工作,但是当我添加更多时,它开始滞后很多。
这是我用于更新图片框的代码:
private void timer4_Tick(object sender, EventArgs e)
{
Bitmap image = RotateImage(indicatorImg, i++, false, true, Color.Transparent);
pictureBox4.Image = image;
}
我正在使用的 RotateImage 函数(感谢 RenniePet https://stackoverflow.com/a/16027561/3660713):
public static Bitmap RotateImage(Image inputImage, float angleDegrees, bool upsizeOk,
bool clipOk, Color backgroundColor)
{
lock (lockObject)
{
// Test for zero rotation and return a clone of the input image
if (angleDegrees == 0f)
return (Bitmap)inputImage.Clone();
// Set up old and new image dimensions, assuming upsizing not wanted and clipping OK
int oldWidth = inputImage.Width;
int oldHeight = inputImage.Height;
int newWidth = oldWidth;
int newHeight = oldHeight;
float scaleFactor = 1f;
// If upsizing wanted or clipping not OK calculate the size of the resulting bitmap
if (upsizeOk || !clipOk)
{
double angleRadians = angleDegrees * Math.PI / 180d;
double cos = Math.Abs(Math.Cos(angleRadians));
double sin = Math.Abs(Math.Sin(angleRadians));
newWidth = (int)Math.Round(oldWidth * cos + oldHeight * sin);
newHeight = (int)Math.Round(oldWidth * sin + oldHeight * cos);
}
// If upsizing not wanted and clipping not OK need a scaling factor
if (!upsizeOk && !clipOk)
{
scaleFactor = Math.Min((float)oldWidth / newWidth, (float)oldHeight / newHeight);
newWidth = oldWidth;
newHeight = oldHeight;
}
// Create the new bitmap object. If background color is transparent it must be 32-bit,
// otherwise 24-bit is good enough.
Bitmap newBitmap = new Bitmap(newWidth, newHeight, backgroundColor == Color.Transparent ?
PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb);
newBitmap.SetResolution(inputImage.HorizontalResolution, inputImage.VerticalResolution);
// Create the Graphics object that does the work
using (Graphics graphicsObject = Graphics.FromImage(newBitmap))
{
graphicsObject.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphicsObject.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
graphicsObject.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
// Fill in the specified background color if necessary
if (backgroundColor != Color.Transparent)
graphicsObject.Clear(backgroundColor);
// Set up the built-in transformation matrix to do the rotation and maybe scaling
graphicsObject.TranslateTransform(newWidth / 2f, newHeight / 2f);
if (scaleFactor != 1f)
graphicsObject.ScaleTransform(scaleFactor, scaleFactor);
graphicsObject.RotateTransform(angleDegrees);
graphicsObject.TranslateTransform(-oldWidth / 2f, -oldHeight / 2f);
// Draw the result
graphicsObject.DrawImage(inputImage, 0, 0);
}
return newBitmap;
}
}
关于如何提高性能的任何想法?有没有更好的方法来做到这一点?
【问题讨论】:
-
你可以用不同的方式实现它(没有计时器),见here。除此之外,位图位图是最快的方法。您可以预渲染帧,然后在绘制图像时使用它们。它可以以缓存的方式完成:如果帧丢失 - 它被渲染然后重用,否则它保持
null并且不使用内存。 -
您可能需要使用当前相关的 .Net UI 技术检查My Answer 来回答一个非常相似的问题。
-
仅供参考,我已经修改了我之前评论中链接的示例,以包括通过计时器随机移动的 20 个仪表,并且 UI 响应是即时的。使用诸如 winforms 之类的古老技术是您永远无法实现的。 Full source code on GitHub
-
谢谢你们。我会检查您的解决方案并发布我的发现!
标签: c# winforms visual-studio