为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

鸿蒙传说 2018-12-06 12:47:17
要实现的效果:鼠标点击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); } }}
查看完整描述

7 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

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

查看完整回答
反对 回复 2019-01-21
?
绝地无双

TA贡献1946条经验 获得超4个赞

不会用wpf

查看完整回答
反对 回复 2019-01-21
?
守着一只汪

TA贡献1872条经验 获得超3个赞

事实上,用gdi+画这个根本没压力,是你方法没用对

查看完整回答
反对 回复 2019-01-21
?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

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

查看完整回答
反对 回复 2019-01-21
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

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

查看完整回答
反对 回复 2019-01-21
?
临摹微笑

TA贡献1982条经验 获得超2个赞

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

查看完整回答
反对 回复 2019-01-21
?
动漫人物

TA贡献1815条经验 获得超10个赞

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

查看完整回答
反对 回复 2019-01-21
?
HUWWW

TA贡献1874条经验 获得超12个赞

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

查看完整回答
反对 回复 2019-01-21
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

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

查看完整回答
反对 回复 2019-01-21
?
慕少森

TA贡献2019条经验 获得超9个赞

@刘宏玺: 好的

查看完整回答
反对 回复 2019-01-21
?
湖上湖

TA贡献2003条经验 获得超2个赞

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

查看完整回答
反对 回复 2019-01-21
  • 7 回答
  • 0 关注
  • 600 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信