首页 新闻 会员 周边

如何解决winfrom里三个圆的闪屏问题

0
悬赏园豆:50 [已解决问题] 解决于 2016-04-16 13:53

要实现的效果:鼠标点击winform上任意两点构成直线,点击第一个按钮,出现一个圆沿直线做往返运动,点击第二个按钮,同时出现三条直线,每条直线上有三个圆沿直线做往返运动。这个效果已实现,三个圆之间无闪屏

问题:解决三个圆之间的闪屏

界面:两个button,三个timer

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace PictureSport
{
public partial class Test_DongYuan : Form
{
public Test_DongYuan()
{
//this.DoubleBuffered = true;

InitializeComponent();
}

 

public Graphics g;//封装一个gdi+绘图图面
private Bitmap bmp;

public Point p1;//默认第一条线点的起始坐标
public Point p2;//默认第一条线点的结束坐标

public Point p3;
public Point p4;
public Point p5;
public Point p6;

private int n = 0; //运动点离起点的距离
private bool bDirect = true;//true为从起点向终点运行,false从终点向起点运行
Point pt = new Point(0, 0); //当前点

public int i = 1;//记录循环次数

public int m;//总距离

 

private void Test_DongYuan_Load(object sender, EventArgs e)
{


//1、在内存中建立一块“虚拟画布”

bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
//2、获取这块内存画布的Graphics引用

g = Graphics.FromImage(bmp); ;//获取画布
timer1.Enabled = false;//一开始不画圆
timer2.Enabled = false;
timer3.Enabled = false;
}

private void Test_DongYuan_MouseClick(object sender, MouseEventArgs e)
{
if (i == 1)
{
p1 = new Point();
p1.X = e.Location.X;
p1.Y = e.Location.Y;
i++;

}
else
{

if (i == 2)
{
p2 = new Point();
p2.X = e.Location.X;
p2.Y = e.Location.Y;

g.DrawLine(Pens.Black, p1, p2);
g.DrawImage(bmp, new Point(0, 0));
this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
g.Dispose();

}

}

}


private void timer1_Tick(object sender, EventArgs e)
{

button1_Click(sender, e);

}
private void timer2_Tick(object sender, EventArgs e)
{
//第一条直线上的直线

p3.X = p1.X;
p3.Y = p1.Y - 50;
p4.X = p2.X;
p4.Y = p2.Y - 50;

//第一条直线下的直线
p5.X = p1.X;
p5.Y = p1.Y + 50;
p6.X = p2.X;
p6.Y = p2.Y + 50;


bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
g = Graphics.FromImage(bmp); ;//获取画布
g.DrawLine(Pens.Black, p1, p2);
g.DrawLine(Pens.Black, p3, p4);
g.DrawLine(Pens.Black, p5, p6);
DongYuan(p3, p4);
g.DrawImage(bmp, new Point(0, 0));

this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
g.Dispose();

}

private void timer3_Tick(object sender, EventArgs e)
{

//第一条直线上的直线

p3.X = p1.X;
p3.Y = p1.Y - 50;
p4.X = p2.X;
p4.Y = p2.Y - 50;

//第一条直线下的直线
p5.X = p1.X;
p5.Y = p1.Y + 50;
p6.X = p2.X;
p6.Y = p2.Y + 50;

 

bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
g = Graphics.FromImage(bmp); ;//获取画布
g.DrawLine(Pens.Black, p1, p2);
g.DrawLine(Pens.Black, p3, p4);
g.DrawLine(Pens.Black, p5, p6);
DongYuan(p5, p6);
g.DrawImage(bmp, new Point(0, 0));
this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
g.Dispose();

}

/// <summary>
/// 动圆
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{


DongYuan(p1,p2);
timer1.Enabled = true;

}
/// <summary>
/// 动圆方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void DongYuan(Point p_first,Point p_last)
{


//Math.Pow() Pow返回指定数字的指定次幂 pow(X,y)就是计算X的Y次方
m = (int)Math.Pow(Math.Pow((p_last.X - p_first.X), 2) + Math.Pow((p_last.Y - p_first.Y), 2), 0.5);//总距离
if (n == m)//运动点离起点的距离=总距离
bDirect = false;//false从终点向起点运行
if (n == 0)//运动点离起点的距离=0
bDirect = true;//true为从起点向终点运行
if (bDirect)//从起点向终点运行
n++;//运动点离起点的距离不断自加
else
n--;//运动点离起点的距离不断自-

//Pen p11 = new Pen(Color.Black);
Pen p_double = new Pen(Color.Red);
Graphics g = this.CreateGraphics();

if (pt.X != 0 && pt.Y != 0) //清除上次的运动点
{
//减去圆半径
g.DrawEllipse(new Pen(this.BackColor), pt.X - 15, pt.Y - 15, 30, 30); //清除上次的运动点
}

g.DrawLine(Pens.Black,p_first, p_last);//画起点到终点的线
g.DrawImage(bmp, new Point(0, 0));
this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景

//总距离不为0
if (m != 0)
{
pt.X = ((p_last.X - p_first.X) * n) / m + p_first.X;
pt.Y = ((p_last.Y - p_first.Y)) * n / m + p_first.Y;
g.DrawEllipse(p_double, pt.X - 15, pt.Y - 15, 30, 30); //画运动的点
g.Dispose();//释放资源

}

}


/// <summary>
/// 分批
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
timer2.Enabled = true;
timer3.Enabled = true;
//第一条直线上的直线

p3.X = p1.X;
p3.Y = p1.Y - 50;
p4.X = p2.X;
p4.Y = p2.Y - 50;

//第一条直线下的直线
p5.X = p1.X;
p5.Y = p1.Y + 50;
p6.X = p2.X;
p6.Y = p2.Y + 50;

bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
g = Graphics.FromImage(bmp); ;//获取画布
g.DrawLine(Pens.Black,p1,p2);
g.DrawLine(Pens.Black, p3, p4);
g.DrawLine(Pens.Black, p5, p6);
g.DrawImage(bmp, new Point(0, 0));
this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
button1_Click(sender, e);


}


}
}

随风起舞的主页 随风起舞 | 初学一级 | 园豆:19
提问于:2016-04-14 19:49
< >
分享
最佳答案
0

留个邮箱或QQ,我把代码发你?

收获园豆:50
Firen | 大侠五级 |园豆:5385 | 2016-04-15 13:34

邮箱:2220552727@qq.com

随风起舞 | 园豆:19 (初学一级) | 2016-04-15 13:44

@随风起舞: 发你邮件了,没做往返功能,只是为了演示不闪烁。

Firen | 园豆:5385 (大侠五级) | 2016-04-15 14:25

@Firen: 已经收到了案例,完美解决问题了。

随风起舞 | 园豆:19 (初学一级) | 2016-04-16 13:50
其他回答(2)
0

我现在有点怕用gdi+做动画了,你还是用wpf做吧,保证不闪

上帝之城 | 园豆:2549 (老鸟四级) | 2016-04-14 20:09

不会用wpf

支持(0) 反对(0) 随风起舞 | 园豆:19 (初学一级) | 2016-04-14 20:10

@随风起舞: 事实上,用gdi+画这个根本没压力,是你方法没用对

支持(0) 反对(0) 上帝之城 | 园豆:2549 (老鸟四级) | 2016-04-14 20:12

@上帝之城: 如果你会的话,求教

支持(0) 反对(0) 随风起舞 | 园豆:19 (初学一级) | 2016-04-14 20:13

@随风起舞: 用gdi+,就要学习局部绘图技术,你每次都完整的绘制了一帧,不卡才怪。

支持(0) 反对(0) 上帝之城 | 园豆:2549 (老鸟四级) | 2016-04-14 20:17

@上帝之城: 那应该怎么修改代码?

支持(0) 反对(0) 随风起舞 | 园豆:19 (初学一级) | 2016-04-14 20:18
0

你需要使用双缓冲,才能解决闪屏问题

刘宏玺 | 园豆:14020 (专家六级) | 2016-04-15 21:24

双缓冲用过了好几种,都没有效果

支持(0) 反对(0) 随风起舞 | 园豆:19 (初学一级) | 2016-04-15 21:35

@随风起舞: 你的代码里确实用到了双缓冲,要不你把整个项目发给我,有空我帮你调调?

支持(0) 反对(0) 刘宏玺 | 园豆:14020 (专家六级) | 2016-04-15 21:50

@刘宏玺: 好的

支持(0) 反对(0) 随风起舞 | 园豆:19 (初学一级) | 2016-04-15 22:07

@刘宏玺: 我发份压缩包到你的邮箱吧,有空麻烦帮我看一下

支持(0) 反对(0) 随风起舞 | 园豆:19 (初学一级) | 2016-04-15 22:18
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册