C#中关于PANEL控件的Graphics绘图

我想请问一下,我在C#的中生成了0、1的随机数,并用PANEL控件将他绘制出来,但是,我的PANEL控件不能完全将生成的图像表示出来,就是这样的。拉动滚动条出不行,请问一... 我想请问一下,我在C#的中生成了0、1的随机数,并用PANEL控件将他绘制出来,但是,我的PANEL控件不能完全将生成的图像表示出来,

就是这样的。拉动滚动条出不行,请问一下有什么方法可以解决?我的代码如下:
namespace Chapter23
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Graphics grap = pChart.CreateGraphics();
grap.Clear(Color.White);
Pen blue = new Pen(Color.Blue);
Pen red = new Pen(Color.Red);
int[] nums = new int[10000];
Random random = new Random(); //随机数值
for (int i = 0; i < 100; i++)
{
nums[i] = random.Next(0, 2);

}
for (int i = 0; i < 100; i++)
{
if (nums[i] == 1)
{
SolidBrush r1 = new SolidBrush(Color.Red);//定义单色画刷
Rectangle rect = new Rectangle(20 * i, 0, 10, 50);
grap.FillRectangle(r1, rect);//填充这个矩形
}
else
{
SolidBrush b1 = new SolidBrush(Color.Blue);//定义单色画刷
Rectangle rect = new Rectangle(20 * i, 0, 10, 50);
grap.FillRectangle(b1, rect);//填充这个矩形
}
System.Threading.Thread.Sleep(50);
}
}请问该怎么改?可以给我写出代码吗?
private void pChart_Paint(object sender, PaintEventArgs e)
{
ControlPaint.DrawBorder3D(e.Graphics, e.ClipRectangle, Border3DStyle.Etched, Border3DSide.All);
this.pChart.HorizontalScroll.Visible = true;
this.pChart.AutoScroll = true;
}
这是我的PAINT事件
展开
 我来答
kostr
推荐于2017-12-16 · TA获得超过102个赞
知道小有建树答主
回答量:84
采纳率:0%
帮助的人:94.7万
展开全部

LZ关键问题是没有注意到图形在某位“位置”绘制后,如果该位置发生的移动,或其他图形遮挡了后会出现什么,如下图:

用其他什么东西,例如QQ遮挡 了一下原图形就没有了...因为在此之后没有人重新绘制了该图形,基于类似原因,即便你使用了Scoll,也无法看到后面的图形


你的程序我改造了一下,可以根据需求绘制图形,去掉Panel自带的HorizontalScroll,新增了一个hScrollBar(HorizontalScroll没有尝试成功,所以替换了,LZ可以多尝试下)

 private struct ImageContainerType
        {
            public Rectangle theImage;     // 图形容器--矩形
            public SolidBrush theBrush;    // 绘制该图形所用的画笔
        };
        // 绘制的图形的"容器"--这里用来存放绘制的矩形
        
        List<ImageContainerType> imageList;

        // 用于控制绘图位置的全局变量
        int indexDraw = 0;

        private void button1_Click(object sender, EventArgs e)
        {
            /*
                调整思路
             * 方案A:静态绘图
             * 1、将所有绘制的图形保存到imageList容器中
             * 2、在需要时再执行绘制,例如拖动Scoll时触发
             * 缺点:如果绘制的图形较多,将消耗大量内存
             * 优点:只需要执行一次图形创建过程,以后随时可以使用,节省CPU或GPU资源
             *      且算法简单
             * 
             * 方案B:动态绘图
             * 1、先绘制当前所需要的图形(在可见区间内)
             * 2、在需要时如Scoll,重新(在可见区间内)绘制所需要的图形
             */
            int[] nums = new int[10000];

            // 初始化图形容器
            imageList = new List<ImageContainerType>(100);
            ImageContainerType tempImage;

            Random random = new Random(); //随机数值
            for (int i = 0; i < 100; i++)
            {
                nums[i] = random.Next(0, 2);

            }
            for (int i = 0; i < 100; i++)
            {
                if (nums[i] == 1)
                {
                    SolidBrush r1 = new SolidBrush(Color.Red);//定义单色画刷    
                    Rectangle rect = new Rectangle(20 * i, 0, 10, 50);
                    //grap.FillRectangle(r1, rect);//填充这个矩形 
                    // 将当前图形存入容器
                    tempImage = new ImageContainerType();
                    tempImage.theBrush = new SolidBrush(Color.Red);
                    tempImage.theImage = new Rectangle(20 * i, 0, 10, 50);
                    imageList.Add(tempImage);
                }
                else
                {
                    SolidBrush b1 = new SolidBrush(Color.Blue);//定义单色画刷
                    Rectangle rect = new Rectangle(20 * i, 0, 10, 50);
                    //grap.FillRectangle(b1, rect);//填充这个矩形
                    tempImage = new ImageContainerType();
                    tempImage.theBrush = new SolidBrush(Color.Blue);
                    tempImage.theImage = new Rectangle(20 * i, 0, 10, 50);
                    imageList.Add(tempImage);
                }             
            }

            // [关键]设置Scorll的新值
            this.hScrollBar1.Maximum = 100;

            // 绘制全部图形
            DrawImage(0, imageList.Count - 1);

            MessageBox.Show("绘制完成");
        }
        /// <summary>
        /// 实际的图形绘制方法
        /// </summary>
        /// <param name="start">所需绘制图形的起始编号</param>
        /// <param name="end">所需绘制图形的结束编号,如果end在start则绘制所有剩下图形</param>
        void DrawImage(int start, int end)
        { 
            // 1、判定绘图容器是否存在
            if (imageList == null || imageList.Count <= 0)
            {
                MessageBox.Show("还没有生成图形");
                return;
            }

            // 2、绘图区间判定
            if (start >= imageList.Count || end >= imageList.Count)
            {
                MessageBox.Show("不在有效绘图区间");
                return;
            }

            // 3、
            if (start <= end)
            { 
                // 绘制从起始位置,到结束位置所有图形
                end = imageList.Count - 1;
            }

            // 4、绘制图形
            Graphics grap = pChart.CreateGraphics();
            grap.Clear(Color.White);
            Pen blue = new Pen(Color.Blue);
            Pen red = new Pen(Color.Red);
            for(int index=start;index<= end;index++)
            {
                grap.FillRectangle(imageList[index].theBrush, imageList[index].theImage);
            }            
        }

        /// <summary>
        /// 在Scroll实际中重绘Panel内容
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            // 每次重绘"当前位置"直至结尾的所有图形
            DrawImage(e.NewValue, imageList.Count - 1);
        }

得到的效果是:

你可以看到,Scoll正确发挥了作用,但貌似图形不正确阿....前面的没有了?

原因在于现有的重绘访法是

// 每次重绘"当前位置"直至结尾的所有图形
DrawImage(e.NewValue, imageList.Count - 1);

而在imageList容器中存放的图形其坐标已经固定了,因此绘制结果也就可以预期了——这距离使用Scoll拖动图形距离不远了:>


其实关键就是图形和界面之间相对位置的处理了——界面是静止的,那么只有让图动起来,看我的改造:

注意上面两个图形的坐标,0-99和9~99,然后看相应的图形。的确界面没动,但图形动了,看起来就像是Panel向右滑动了10个单位一样。修改Scoll事件中的绘图方法就可以达到所需要的效果了

        /// <summary>
        /// 在Scroll实际中重绘Panel内容
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            int theValue = e.NewValue;
            int theNewImageX_Index = 0;


            // 要想实现“动态效果”的关键是重新计算图形与“静止”的界面
            // 之间的相对位置,即“界面不动”图形动(我不动那就麻烦你动一下了:>)
            // 这将消耗一定的CPU资源
            // --尝试将图形的位置根据当前"位置"进行移动
            // --将当前图形设定为"相对于界面"的第一个图形,后面的图形依次+1
            for (int index = theValue; index < imageList.Count; index++)
            {
                ImageContainerType temp = new ImageContainerType();
                temp.theImage = new Rectangle(20 * theNewImageX_Index, 0, 10, 50);
                temp.theBrush = imageList[index].theBrush;
                imageList[index] = temp;

                theNewImageX_Index++;
            }

            // 然后重新绘制图形
            DrawImage(theValue, imageList.Count - 1);
        }

 这里最关键的就是重新计算图形的坐标

new Rectangle(20 * theNewImageX_Index, 0, 10, 50);
追问
请问一下,你的QQ为多少?我想细问一下。
追答
发邮件给我吧
百度网友30a3645
2013-07-27 · TA获得超过531个赞
知道小有建树答主
回答量:446
采纳率:0%
帮助的人:176万
展开全部
private void panel1_Paint(object sender, PaintEventArgs e) { DrawMe(e.Graphics); }private void DrawMe(Graphics g){g.FillRectangle(blueBrush, x, y, width, height);...这里绘制 主意:绘制结束后不要使用 g.Dispone() 因为这个g来自控件绘制本身 不能销毁 }
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式