iT邦幫忙

0

C#,在FORM畫完圖後,將視窗縮小再放大,圖就消失

c#
symis 2013-12-22 15:30:3112633 瀏覽

請問C#,在FORM畫完圖後,將視窗縮小再放大,圖就消失,請問要如何解?
謝謝!
檔案在此:
http://www.2shared.com/file/FGYVhmhb/\_online.html
我爬過文,試過一些方法都失敗,有個方法成功了,卻只能畫一次 @@

fillano iT邦超人 1 級 ‧ 2013-12-23 12:19:11 檢舉
我猜你需要在Paint事件重新畫圖。(.Net不熟,所以用猜的XD)
symis iT邦新手 3 級 ‧ 2013-12-23 23:49:58 檢舉
謝謝!
fillano iT邦超人 1 級 ‧ 2013-12-25 13:24:35 檢舉
看了幾篇文章,這篇講的還算清楚:
http://johnniebooks.blogspot.tw/2009/09/c-delgateevent.html

不好意思,.Net與C#不熟,所以只能找別人寫的文章XD

1 個回答

4
fillano
iT邦超人 1 級 ‧ 2013-12-23 23:52:42
最佳解答

看到你還到fb問這個問題,所以認真作答好了XD

  1. 在fb有人提到,需要在Form1_Paint處理重繪,這是最重要的地方
  2. 用PictureBox來做會比較簡單,因為他有Image屬性,所以在Form裡面加了pictureBox1這個PictureBox
  3. 繪製的動作是在一個Bitmap上,繪製完成後assign給pictureBox1.Image,就會顯示,這樣所有的顯示方法就是一致的。

大致上就做了上述修改(把繪圖的程式抽成方法,本來是為了預備試不出來用的,跟你原來作法其實一樣):

<pre class="c" name="code">
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 EX_010
{
     public partial class Form1 : Form
    {
        Pen p;
        Bitmap b;

        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            b = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        }
        private void line(Graphics g, Pen p, int x1, int y1, int x2, int y2)
        {
            g.DrawLine(p, x1, y1, x2, y2); // NEW 畫線座標
        }
        private void XA1_Click(object sender, EventArgs e)
        {
            int x1 = int.Parse(X1.Text); // X1 畫線座標
            int y1 = int.Parse(Y1.Text); // Y1 畫線座標
            int x2 = int.Parse(X2.Text); // X2 畫線座標
            int y2 = int.Parse(Y2.Text); // X2 畫線座標
            line(Graphics.FromImage(b), p, x1, y1, x2, y2);
            pictureBox1.Image = b;
        }
        private void circle(Graphics g, Pen p, int x, int y, int r)
        {
            g.DrawEllipse(p, x - r, y - r, r * 2, r * 2); //NEW 畫圓座標
        }
        private void YA1_Click(object sender, EventArgs e)
        {
            int x = int.Parse(CA.Text);  // X 畫圓座標
            int y = int.Parse(CB.Text);  // Y 畫圓座標
            int Radius = int.Parse(RC.Text); //r 座標
            circle(Graphics.FromImage(b), p, x, y, Radius);
            pictureBox1.Image = b;
        }
        private void clear(Graphics g)
        {
            g.Clear(Color.White);
        }
        private void RS_Click(object sender, EventArgs e)
        {
            clear(Graphics.FromImage(b));
            pictureBox1.Image = b;
        }

        private void button_Click(object sender, EventArgs e)
        {
            Application.Exit(); //結束程式
        }

        private void radioA_CheckedChanged(object sender, EventArgs e)
        {
            p = new Pen(Color.Red,2);  //紅色
        }

        private void radioB_CheckedChanged(object sender, EventArgs e)
        {
            p = new Pen(Color.Yellow, 2); //黃色
        }

        private void radioC_CheckedChanged(object sender, EventArgs e)
        {
            p = new Pen(Color.Green, 2);  //綠色
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
                pictureBox1.Image = b;
        }
    }
}
看更多先前的回應...收起先前的回應...
fillano iT邦超人 1 級 ‧ 2013-12-24 00:14:15 檢舉

想了一下,如果是要畫到Form上,那可以從Form1上取得Graphics物件,然後透過它的DrawImage方法把Bitmap畫上去。

symis iT邦新手 3 級 ‧ 2013-12-24 00:41:23 檢舉

謝謝! 但改好後,只能畫一次(線或圓),就不能再畫了,也不能清除,和本文所述一樣!
(奇怪,怎麼貼上程式碼,說我內容太長),但你上面卻可貼?)

symis iT邦新手 3 級 ‧ 2013-12-24 00:43:05 檢舉

我是把pictureBox1.Image 改成:this.BackgroundImage

fillano iT邦超人 1 級 ‧ 2013-12-24 05:21:40 檢舉

是喔,我的可以XD

fillano iT邦超人 1 級 ‧ 2013-12-24 05:38:40 檢舉

不要用BackgroundImage啦,他會自動tile,而且似乎要在重繪時才有作用。(lifecycle是怎樣我不太確定)你可以改成這兩行:

<pre class="c" name="code">
Graphics g1 = CreateGraphics();
g1.DrawImage(b, 0, 0);
symis iT邦新手 3 級 ‧ 2013-12-24 11:53:47 檢舉

原來你還是有用pictureBox,題目是直接在FORM上畫。
我把所有this.BackgroundImage都改成你的二行程式,可以正常畫圖,也可以清除,但,還是回到老問題...將視窗縮小再放大,圖就消失!

fillano iT邦超人 1 級 ‧ 2013-12-24 12:05:32 檢舉

你有處理Form1_Paint嗎?另外,我把PictureBox拿掉,改用上述兩行程式,可以正常運作阿。畫在form上面並沒有問題,只是沒貼圖給你而已。

fillano iT邦超人 1 級 ‧ 2013-12-24 12:09:34 檢舉
<pre class="c" name="code">
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            //有處理嗎?
        }
fillano iT邦超人 1 級 ‧ 2013-12-24 12:15:16 檢舉

另外,不知道你有沒有仔細看我改的程式。繪圖的部分是作用在哪個元件?所以之後要怎樣做才能維持繪圖內容的顯示?後續的動作,差別只是把繪圖內容更新到哪個元件上而已,用不用PictureBox並不是關鍵。即使使用PictureBox,重繪沒處理,一樣會被清空的。

symis iT邦新手 3 級 ‧ 2013-12-24 12:29:54 檢舉

有啊,Form1_Paint內就只有你那二行程式啊!
我重PO最後的程式好了...
http://www.2shared.com/file/P\_ISXAMR/\_online.html
很抱歉,我對繪圖原理不熟,讓您費心了

fillano iT邦超人 1 級 ‧ 2013-12-24 13:57:06 檢舉

除了clear會有問題之外,看起來OK耶?這樣有點怪,不過我要晚上回去才能測試...

fillano iT邦超人 1 級 ‧ 2013-12-24 19:25:16 檢舉

...你要用VisualStudio的屬性視窗加入Paint事件啦,Form1是一個partial class,有些事情不是在這裡發生的,你沒用VisualStudio來加入事件handler,事情不會自己發生。

打開設計檢視,用滑鼠右鍵點選Form1,然號選擇「屬性」,接下來點一下「閃電」icon切換到事件,然後點兩下Paint加入事件處理handler。

fillano iT邦超人 1 級 ‧ 2013-12-24 19:56:57 檢舉

有興趣研究的話,可以看一下Form1.Designer.cs...看看是否有把事件加進去:

<pre class="c" name="code">
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);

這是VisualStudio幫你做的事情...實際上,事件處理的方法是這樣bind上去的,並不是自己定義就會動。

symis iT邦新手 3 級 ‧ 2013-12-24 23:06:47 檢舉

可以了,感恩!
上面那一行指令太深了,看不懂,以前好像聽老師提過,是叫指派嗎?

我要發表回答

立即登入回答