2012年4月11日 星期三

第一張彩色作品-狗狗





第一張彩色作品,感覺好像不是很好耶
沒關係,第一次就太好的話,那就太扯了,應該是「稍微能看」我就要很滿意了

2012年4月3日 星期二

4/3,三張動物素描圖

今天畫三張圖,弄到一點半,(我蠻認真的嘛!XD)
好累喔,呵呵
我才剛開始重新摸回我的繪畫,還畫的不是很好,觸感很不細膩,力道也沒有掌握得很好,目前也只能照著畫,還沒辦法自己構圖。也別提彩色或用電腦畫圖了,過幾天看看有沒有機會吧





2012年4月2日 星期一

美工書本來了






昨天在 PC HOME 24HR 購買的三本書,很快晚上就到貨啦,這三本在圖書館找不到,只能用買的了,還好,不是那麼貴,一本Q版動物,一本Q版人物,一本場景素描。

是的,我又再度開啟了美工繪畫的技能的磨練之途,自從大學畢業之後,好幾年沒有練習了,多練習一個新的技能,希望對工作能更有幫助。

這次除了看了很多介面設計的書籍之外,也看了很多關於素描、透視、表情的書。當然,畫圖這東西不是用看的就好,每天至少要練習,畫個三、五張才行。

當然,程式方面也不會就此荒廢打住,而且我也還有看了一些關於行銷、專案管裡的書籍,這陣子一定要好好充實,加油!

2012年2月5日 星期日

Image與BitmapImage如何用多執行緒來達成預先載入?

如果沒有實做過,會覺得應該不難,沒什麼問題,但是,真的在做的時候,會因為不夠瞭解,而遇到這個陷阱的。




首先,你當然必須在Windows上放上一個Image元件(要用程式建立也行啦),然後,在Window的Class層級宣告以下元件(因為很多函式會共用到,所以不能在函式內宣告。


        private BitmapImage BitMap;
        private FileStream FStream;
        private BackgroundWorker BgWk;


然後再需要載入圖片的時機,產生BackgroundWorker 物件來幫你做多執行緒處理(看是要在某個按鈕被按下,還是在某個Timer事件裡,都好)



            BgWk = new BackgroundWorker( );
            BgWk.DoWork += new DoWorkEventHandler( BgWk_DoWork );
            BgWk.RunWorkerCompleted += new RunWorkerCompletedEventHandler( BgWk_RunWorkerCompleted );
            BgWk.RunWorkerAsync( );





上面需要綁定兩個函式來做BackgroundWorker的事件,一個是DoWork(),是開新的Thread要做的事情,另外一個是RunWorkerCompleted(),則是在Thread忙完之後要做的事情,這裡,非常簡單,很直覺的可以想像,把BitmapImage載入圖片的那一段程式,放到DoWork(),載入完成之後在RunWorkerCompleted()這個函式裡,Image要載入這個圖,兩個函式如下



        private void BgWk_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e )
        {
            ImageControl.BeginInit( );
            ImageControl.Source = BitMap;
            ImageControl.EndInit( );
        }


        private void BgWk_DoWork( object sender, DoWorkEventArgs e )
        {
            // 開檔
            String FilePath = @"C:\temp\IMG001.JPG";
            FStream = new FileStream( FilePath, FileMode.Open );


            // 將資料讀入 BitmapImage 變成圖檔資源
            BitMap = new BitmapImage( );
            BitMap.BeginInit( );
            BitMap.CacheOption = BitmapCacheOption.OnLoad;
            BitMap.StreamSource = FStream;
            BitMap.EndInit( );
            BitMap.Freeze( );
            FStream.Close( );
        }







以上想法沒有問題,但是問題就在紅色粗斜體這一行,BitmapImage有個特性,就是他的載入圖片這個行為會牽涉到UI的變更,也就是說,當你沒有紅色這一行的時候,BitmapImage跟「會顯示畫面的UI」是同等的,也就是你無法跨執行緒使用他,這個BitmapImage已經屬於DoWork()這個執行緒了(為什麼?因為在函式裡有New產生物件,所以屬於次程序),當你回到RunWorkerCompleted()主執行緒的時候,無法再用他了,會引發「跨執行緒使用UI物件」的InvalidOperationException,那怎麼辦?我已經想要把UI跟Data分開了,如果BitmapImage是個UI物件,那就無法預先載入圖檔了呀,因為我又要在背景執行緒載入圖,不同執行緒卻又不能使用同一個物件,如果你用Dispatch來做,那也失去意義,因為Dispatch最後也是回歸到UI Thread來做事,一樣卡了UI,造成無反應狀態,原來,其中的關鍵就在於當你把圖檔載入之後,要呼叫Freeze()來把資源固定,就可以跟一般物件一樣,可以跨執行緒來使用。達成「讓沒有UI的繁瑣事情可以在背景執行,有UI的更新在前景進行啦」。