当前位置:编程学习 > C#/ASP.NET >>

winform panel绘图问题。


 private void InitDraw()
        {
            //int x = 10, y = 15, dx = 840, dy = 560;
            Bitmap bitmap = new Bitmap(this.panel2.ClientSize.Width, this.panel2.ClientSize.Height);
            Graphics g = Graphics.FromImage(bitmap);//将绘制内容画到bitmap中。
            g.Clear(Color.White);
            Pen blackPen = new Pen(Color.Black);//定义一只画笔
            SolidBrush redBrush = new SolidBrush(Color.Red);//单色画刷,填充形状

            //先画矩形
            g.DrawRectangle(blackPen, 10, 15, 840, 560);//以坐标(10,15)为起点画一个宽840,高575的矩形
        
            //画分割线,
            for (int i = 0; i < 4; i++)
                g.DrawLine(blackPen, 10, 140 * i + 15, 850, 140 * i + 15);//(x,dy/4*i+y,dx+x,dy/4*i+y);

            for (int j = 0; j < 4; j++)
            {//鼠标单击画线。
                //判断鼠标在那个通道上,
                if (m_x > 10 && m_y > 140 * j + 15 && m_y < 140 * (j + 1) + 15 && m_x < 850)
                {
                    g.DrawLine(blackPen, m_x, 140 * j + 15, m_x, 140 * (j + 1) + 15);
                    g.FillEllipse(redBrush, 15, 140 * j + 20, 10, 10);
                }
            }

            for (int k = 0; k < 26;k++ )
            {//画底部坐标
                if (k % 5 == 0) 
                    g.DrawLine(blackPen, 10 + 33 * k, 568, 10 + 33 * k, 575);
                else
                    g.DrawLine(blackPen, 10 + 33 * k, 572, 10 + 33 * k, 575);
            }

            //自定义虚线
            blackPen.DashPattern = new float[] { 2, 3 };//2表示虚线长度为2px,3表示虚线间隔为3px
            for (int i = 0; i < 4; i++)
            {
                g.DrawLine(blackPen, 10, 140 * i + 85, 850, 140 * i + 85);//(x,dy/4*i+(dy/8+y),dx+x,dy/4*i+(dy/8+y))
            }
            
            g.Dispose();
            blackPen.Dispose();
            redBrush.Dispose();
            Graphics gg = this.panel2.CreateGraphics(); //在tabPage1上绘图
            gg.DrawImage(bitmap,0,0);//将bitmap图片显示
            bitmap.Dispose();
            gg.Dispose();
        }
        //画采集曲线
        private void InitDraw_cur() 
        {
            //画采集的曲线
            //当前处于哪几个曲线,调文件画曲线
            //画采集波形,如果某道有数据就画,没有数据就不画
            int i = 0;
            byte j ;
            for (j = 1; j < 5; j++)
            {
                if (Trace[j] == true)//首先读通道数组,如果本道有数据,则画曲线
                {
                    short MaxAd = 1;
                    for (i = 0; i < TPR.SampLen; i++)
                    {
                        if (MaxAd < Math.Abs(Tdata[j, i]))
                            MaxAd = Math.Abs(Tdata[j, i]);
                        //bufw.Write(Fda[i]);//浮点数
                    }
                    //画曲线
                    int Cu = j - 1;
                    Graphics g = this.panel2.CreateGraphics();
                    Pen redPen = new Pen(Color.Red);
                    double dx = 0, dy0 = 0, dy1 = 0;
                    dx = (double)840 / TPR.SampLen;
                    for (i = 0; i < TPR.SampLen - 1; i++)
                    {
                        dy0 = (double)Tdata[j, i] / MaxAd;
                        dy1 = (double)Tdata[j, i + 1] / MaxAd;
                        g.DrawLine(redPen, 10 + (int)(dx * i), (int)(85 - dy0 * 40) + Cu * 140, 10 + (int)(dx * (i + 1)), (int)(85 - dy1 * 40) + Cu * 140);//46=98/2;中间分割线starX,starY,endX,endY
                    }
                    g.Dispose();
                    redPen.Dispose();
                }
            }   
        }

private void panel2_Paint(object sender, PaintEventArgs e)
        {
            if (FormSty == "采集界面")
            {
                InitDraw();
                InitDraw_cur();
            }
            else if (FormSty == "单道界面")
            {
                InitDraw_sign();
                InitDraw_singCur();
            }
            else if (FormSty == "分析界面")
            {
                InitWave();
                InitWave_cur();
            }
        }

       
        private void panel2_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)//单击鼠标左键
            {
                if (FormSty == "采集界面")
                {
                    m_x = e.X;//获取鼠标点击时x轴坐标
                    m_y = e.Y;//y坐标

                    InitDraw();
                    InitDraw_cur();
                }
                if (FormSty == "单道界面")
                {
                    m_x = e.X;//获取鼠标点击时x轴坐标
                    m_y = e.Y;//y坐标

                    InitDraw_sign();
                    InitDraw_singCur();
                }  
            }
        }

        private void panel2_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if(FormSty=="单道界面")
            {
                FormSty = "采集界面";
                InitDraw();
                InitDraw_cur();
                this.单道显示ToolStripMenuItem.Checked = false;
                this.多道显示ToolStripMenuItem.Checked = true;
            }
            else if (FormSty == "采集界面")
            {
                FormSty = "单道界面";
                InitDraw_sign();
                InitDraw_singCur();
                this.单道显示ToolStripMenuItem.Checked = true;
                this.多道显示ToolStripMenuItem.Checked = false;
            }
        }

        private void panel2_MouseMove(object sender, MouseEventArgs e)
        {
            panel2_MouseDown(sender, e);
        }



这样画出来之后,会很闪,本人新手,请大侠分析下代码。 --------------------编程问答-------------------- 设置 Form 的 DoubleBuffer=true;

打开缓冲 --------------------编程问答-------------------- 这样没用的。 --------------------编程问答-------------------- 重载Panel控件,设置双缓冲。 
构造函数里写
this.DoubleBuffered = true --------------------编程问答-------------------- Panel.Backgroundimage=.....
设置背景而不是在其上绘图 --------------------编程问答-------------------- 本人新手,不妥之处请拍。
具体代码如下:首先自定义一个PANEL,代替你代码中的PANEL2,当然,接下来在主界面中需要添加之,添加的方法你肯定知道了。。委托,各种事件注册。。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace 你的命名空间
{
    public class DrawPanel : Control
    {
        public DrawPanel()
        {
            this.DoubleBuffered = true;
            this.SetStyle
            (
               ControlStyles.OptimizedDoubleBuffer |
               ControlStyles.ResizeRedraw, true
            );
            this.Paint += new PaintEventHandler(DrawPanel_Paint);
        }
}
在主界面中的构造函数中可以加入:
 
 //-----------------------DoubleBuffered------------------//
            this.SetStyle(
            ControlStyles.OptimizedDoubleBuffer |
            ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

你先尝试下。



--------------------编程问答--------------------
引用 4 楼 dylike 的回复:
Panel.Backgroundimage=.....
设置背景而不是在其上绘图


学习,之后我的恶心的代码可以改善下。。全部是在panel上的。 --------------------编程问答-------------------- 一个最简单的方法就是把panel换成pictureBox这个控件就不会闪了


/// <summary>
        /// 重绘事件
        /// </summary>
        /// <param name="e"></param>
        void drawPanel_Paint(object sender, PaintEventArgs e)
        {
            Bitmap bp = new Bitmap(this.picBoxMain.Width, this.picBoxMain.Height);
            //newGraphics = this.panelMain.CreateGraphics();
            newGraphics = Graphics.FromImage(bp);
            try
            {
                SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true); //禁止擦除背景.
                SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
                // 消锯齿(可选项)
                newGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                //高质量
                newGraphics.SmoothingMode = SmoothingMode.HighQuality;
                for (int i = 0; i < LineManager.ListLine.Count; i++)
                {
                    Line line = LineManager.ListLine[i];
                    Pen p = new Pen(line.LineColor, line.LineSize);
                    newGraphics.DrawLine(p, line.StartPoint, line.EndPoint);
                }
                // 将缓冲位图绘制到输出
                e.Graphics.DrawImage(bp, Point.Empty);
            }
            catch (Exception ex)
            {
                Console.WriteLine("MainForm-->drawPanel_Paint:" + ex.Message);
            }
            finally
            {
                newGraphics.Dispose();
            }
        }
--------------------编程问答-------------------- 双缓冲不是SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true); //禁止擦除背景.
                SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
这么几句话设置就完了吧?

this.panel2.CreateGraphics();这样得到Graphics,和e.Graphice。有很大的区别。
--------------------编程问答--------------------
引用 8 楼 libaiyikiss 的回复:
双缓冲不是SetStyle(ControlStyles.UserPaint, true);
  SetStyle(ControlStyles.AllPaintingInWmPaint, true); //禁止擦除背景.
  SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
这么几句话设置就完了吧?

this.panel2.Create……

大哥你没看我的回复吗? --------------------编程问答-------------------- 把panel换成pictureBox这个控件就不会闪了 --------------------编程问答--------------------
引用 10 楼 qq123592624 的回复:
把panel换成pictureBox这个控件就不会闪了



.你看我代码了?  换成pic一样的效果。 
在Panel_Paint里面用e.Graphics得到Graphics绘出来不会闪,
我在自己方法里面只能用this.panel.creartGraphics.得到Graphics。画出来会闪。

Bitmap bitmap = new Bitmap(this.panel2.ClientSize.Width, this.panel2.ClientSize.Height);
            Graphics g = Graphics.FromImage(bitmap);这样画出来效果也是不闪的,但加上了曲线就会闪, --------------------编程问答-------------------- --------------------编程问答-------------------- 画了这么多都不会闪 --------------------编程问答--------------------
引用 11 楼 libaiyikiss 的回复:
引用 10 楼 qq123592624 的回复:
把panel换成pictureBox这个控件就不会闪了



.你看我代码了? 换成pic一样的效果。 
在Panel_Paint里面用e.Graphics得到Graphics绘出来不会闪,
我在自己方法里面只能用this.panel.creartGraphics.得到Graphics。画出来会闪。

Bitmap bitmap ……

这样画没有用到双缓冲的效果,所以会闪 --------------------编程问答-------------------- 要用双缓冲才行,要不多次绘制会闪烁。 先把你要画的东西绘制在一个Bitmap上面,然后把这个Bitmap 贴上就就行了。 --------------------编程问答--------------------
引用 15 楼 shadan05 的回复:
要用双缓冲才行,要不多次绘制会闪烁。 先把你要画的东西绘制在一个Bitmap上面,然后把这个Bitmap 贴上就就行了。


就是需要多次绘制,不同的功能绘制不同的效果,都是画在同一个panel上面。
求方案。 --------------------编程问答-------------------- studying --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- http://www.diybl.com/course/4_webprogram/asp.net/netjs/2008520/117339.html
http://www.cnblogs.com/yuanermen/archive/2008/10/09/1307369.html
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,