我想知道其实正常picturebox的绘图使用是将程序放在什么部分的?
我都是放在timer上面通过定时重绘的方式来处理的,
我想有没有一种方式是可以不用timer的?
个人感觉用timer重绘比较卡,很不爽啊,我觉得应该是本身有其它自动触发重绘功能的,但是不知道是什么诶,求指教啦!!!
大神快来解救下我咧,,,谢谢啦哈哈

解决方案 »

  1.   

    需要重绘时调用它的Invalidate,绘图代码放到OnPaint中,你还可以考虑用内存图的方法,new一个Bitmap,然后再上面画,然后设置picturbox的Image为这个bitmap,这样可以减少不必要的OnPaint处理,还需要在需要重绘时,重新绘制一下bitmap即可
      

  2.   

    用timer肯定是不对的,你用timer的想法是你想主动控制图片框绘图,而win程序的本质是回调,是操作系统通知你可以绘图了。把"怎么绘图"和"绘什么图"两个功能分开,
    “绘什么图”在程序里控制,比如定义一个bitmap,在bitmap上绘,如果是矢量图,就定义一个集合,把顶点信息等保存进去,绘图如果需要马上显示出来,就调用Invalidate"怎么绘图"就在OnPaint事件里,读取数据显示出来。这样即使窗口挡住后又可见了,都是会自动重绘的,要手工重绘就调用Invalidate
      

  3.   

    draw()
    {  
                    int Length01;
                    OpenFilePath01 = OpenFilePath01.Replace("jmms", "den");
                    
                    FileStream str01 = new FileStream(OpenFilePath01, FileMode.Open);
                    BinaryReader bread01 = new BinaryReader(str01);
                    Length01 = Convert.ToInt32(str01.Length);
                    byte[] rdata01 = new byte[Length01];
                    for (int i = 0; i < Length01; i++)
                    {
                        rdata01[i] = bread01.ReadByte();                }
                    str01.Close();                string YY;
                    YY = System.Text.Encoding.ASCII.GetString(rdata01);  //将转成的Y点放入字符串中
                    textBox1.Text = YY;
                    string[] Prdata = Regex.Split(YY, @"\s+");  //以分割空格的方式将Y点放入数组中                           pictureBox1.Width = (int)((Prdata.Length / 2) * BiLi + 10);                if (flag == true)
                    {
                        PicHeight = (int)(PicHeight * BiLi);
                        BiLi1 = BiLi1 * BiLi;
                        flag = !flag;
                        scroll = !scroll;
                    }
                    pictureBox1.Height = PicHeight;             
                    
                    //初始化画板                Bitmap image = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
                    //获取背景层
                    Bitmap BeiJing = (Bitmap)pictureBox1.BackgroundImage;                //初始化画布
                    Bitmap HuaBu = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);                //初始化图形
                    Graphics g = Graphics.FromImage(image);
                    Graphics gb = Graphics.FromImage(HuaBu);              
                    PointF[] pL0 = new PointF[Prdata.Length - 1];  //出现多余的斜线是因为这里的长度大于数组的长度
                    PointF[] pY = new PointF[Prdata.Length - 1];
                    PointF ptY;
                    //Prdata.Length-2才是最后一个点
                    for (ii = 0; ii < Prdata.Length - 1; ii++)
                    {
                        pL0[ii] = new PointF(ii / 2, PicHeight / 2);
                        fx = (float)(ii / 2) * BiLi1;
                        fy = float.Parse(Prdata[ii]) * 100 * BiLi1;
                        ptY = new PointF(fx, (PicHeight / 2) - fy);
                        pY[ii] = ptY;
                    }
                    Pen penL = new Pen(Color.Green);
                    Pen penY = new Pen(Color.Red);                g.DrawLines(penY, pY);
                    g.DrawLines(penL, pL0);
                    g.Dispose();
                    gb.DrawImage(BeiJing, 0, 0); //先绘制背景层
                    gb.DrawImage(image, 0, 0);  //绘制画层
                    pictureBox1.BackgroundImage = BeiJing; //设置背景层
                    pictureBox1.CreateGraphics().DrawImage(HuaBu, 0, 0);
    }
    这是我画图的代码,然后你说的“怎么绘图“是下面这些吧?//初始化画板                Bitmap image = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
                    //获取背景层
                    Bitmap BeiJing = (Bitmap)pictureBox1.BackgroundImage;                //初始化画布
                    Bitmap HuaBu = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);                //初始化图形
                    Graphics g = Graphics.FromImage(image);
                    Graphics gb = Graphics.FromImage(HuaBu);
    然后其它的就直接放入OnPaint里面?
                  
      

  4.   

    我想问一下,我现在把画图的写入了OnPaint中了,但是我在拖动滚动条的时候后面的曲线还是不会自动显示出来,是怎么回事呢??要怎么解决呢???
      

  5.   

    我想问一下,我现在把画图的写入了OnPaint中了,但是我在拖动滚动条的时候后面的曲线还是不会自动显示出来,是怎么回事呢??要怎么解决呢???
      

  6.   

    你的代码太长,而且是读取专门的文件显示,和你的问题关系不大,我这儿又不能重用你的代码,拖动滚动条不知道你说的是那个控件的滚动条?
    我写了个简单的例子,窗体的autoscroll不知道是不是你说的滚动条,可以设置为true,拖一个图片框和按钮。熟悉vb就用vb写了,没几行代码,应该看得懂。
    Public Class Form1    Dim image As Bitmap    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load        image = New Bitmap(PictureBox1.ClientSize.Width, PictureBox1.ClientSize.Height)    End Sub    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click        Using g = Graphics.FromImage(image)            g.DrawEllipse(Pens.Red, 10, 10, 200, 200)        End Using        PictureBox1.Invalidate()    End Sub    Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint        e.Graphics.DrawImage(image, 0, 0)    End SubEnd Class
      

  7.   

    谢谢你啊,可是我按你这种方式的话会不停地创建新的窗口出来诶,为什么会这样咧?
    然后我看网上都是在picturebox_paint中画图,然后再OnPaint中再画一遍,但是我发现OnPaint用了跟没用一样诶
      

  8.   

    呃。。不是,说错了,OnPaint用了之后是要是我滚动条拖动过快的画,会直接不显示了,要再拖动一点点滚动条什么的才会显示出来,而我拖动滚动条慢一点的画就能正常显示,这样的话要怎么办噢?
      

  9.   

    还是看不明白你到底是想问什么问题,滚动快了没显示,那就看看是不是onpaint里语句太多了,不需要的语句都移出来,onpaint里就放几条DrawImage语句就行了。
      

  10.   


    我那个代码会不断创建新窗口?都没有new 窗体的语句,怎么会创建新窗口?你是怎么操作的?picturebox_paint和OnPaint是一回事,paint是事件,OnPaint是受保护方法,继承picturebox才可以重写OnPaint,不知道你的“网上都是在picturebox_paint中画图,然后再OnPaint中再画一遍”是什么概念。
      

  11.   


    我在paint里面放的是
                    //初始化画板                image = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
                    //获取背景层
                   BeiJing = (Bitmap)pictureBox1.BackgroundImage;                //初始化画布
                    HuaBu = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);                //初始化图形
                    Graphics g = Graphics.FromImage(image);
                    Graphics gb = Graphics.FromImage(HuaBu);
     后面的就是画线啊什么的
    然后OnPaint中放入
    e.Graphics.DrawImage(image,0,0);
    e.Graphics.DrawImage(HuaBu, 0, 0);
      

  12.   

    重写用c#写了一个,点一次按钮话一个椭圆,不管怎么遮挡都自动重绘,你看看你的思路是不是这样?我想你应该在Paint里做复杂的画图操作了。
    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;namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {        
        Bitmap image;
        Random rand= new Random();        public Form1()
            {
                InitializeComponent();
            }        private void Form1_Load(object sender, EventArgs e)
            {
                image = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
            }        private void button1_Click(object sender, EventArgs e)
            {
                using (Graphics g = Graphics.FromImage(image)) 
                {
                      g.DrawEllipse(Pens.Red, rand.Next(200), rand.Next(200), rand.Next(200), rand.Next(200));
                }            pictureBox1.Invalidate();
            }        private void pictureBox1_Paint(object sender, PaintEventArgs e)
            {
                e.Graphics.DrawImage(image, 0, 0);
            }
        }
    }
      

  13.   

    我在paint里面放的是
    ==========paint是什么?是一个只执行一次的方法吗?还是不停的执行?只执行一次的话,应该不会出现滚动就没有 的事情呀
      

  14.   


    不能在按钮中加pictureBox1.Invalidate()吧,这样会把图刷掉的,然后我在Paint里面读取了较大的数据量进行画图操作,是因为数据量过大而无法自动重绘吗?
      

  15.   

    就是会把图刷掉的,这是windows的核心思想,你不能绘一次就不管了,奢望操作系统给你保存你已经绘的图。所以你需要自己保存自己绘的图,paint方法里只是简单的把你保存的图显示出来。你的绘图方法不能直接在paint里不断的执行,而是对你保存的图操作。
      

  16.   

    不知道你的实际需求是什么,看你的代码,大概意思是读取一个数据文件,然后在一个bmp文件上根据这些数据画线,这个bmp还很大,要滚动才能显示完,不是那种数据自动更新的实时系统,滚动操作比较多。如果是这样的话,就是在内存先new一个bmp,画好背景,根据情况触发读取数据的操作,并且在内存的bmp上画线,而paint方法里只是根据滚动条的位置显示这个bmp的不同部分。
      

  17.   

    想出来什么办法?如果只是偶尔有缩放操作,可以全部重新读数据绘图,如果频繁的操作,那就要把这些曲线参数放在集合里,缩放操作在集合的数据里操作,paint里遍历集合重绘。