最近對於跨平台 GUI 有些興趣,於是就找了 Qt 來玩玩,希望可以做出橫跨 Windows, Linux 和 Mac 的跨平台程式。
記錄一下 Windows 下的 Qt 環境建置,其實 Qt 的官方網站已經提供許多簡單的安裝包,除了使用開源的 GCC compiler 以外,假如有安裝 VS2008 的話,也可以直接下載 「Qt libraries 4.7.0 for Windows (VS 2008, 226 MB)」。
安裝完以後,預設的路徑是在 「C:\Qt\4.7.0\」,當中已經包含預先建置好的範例專案,以及執行檔。直接進入「C:\Qt\4.7.0\examples」探索他的範例程式。在此之前要先手動設定好「環境變數」。
進入 Windows 的環境變數設定,並且在 PATH 當中加入 「C:\Qt\4.7.0\bin;」,注意:不同路徑之間以分號隔開,並且不能多加空格!設到好之後,可以選一個 project 來試跑看看,例如:calculator 專案。
另外,Qt 也提供了 Visual Studio Add-in,安裝之後,VS 當中就會新增建置 Qt 專案的選項,有一些預先提供的 project template 可供使用。
...
10/27/2010
10/26/2010
封裝 openCV 事件成物件的方法成員 - event encapsulation
在使用 openCV 提供的 highgui 時,其提供了一個簡單的滑鼠鍵盤事件機制,透過 cvSetMouseCallback 將 on_mouse 事件綁定到 window_name 視窗。
CVAPI(void) cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param CV_DEFAULT(NULL));
一旦 window_name 視窗發生動作就會驅動 on_mouse 事件方法,但是這個 on_mouse 方法不能是類別的方法成員 ( 例:object->on_mouse ),嘗試後發現,可以利用函數指標將 on_mouse 方法 assign 成 object 的函數指標成員,這樣就可以成功的將事件方法封裝到類別之中。
實作之後發現,此法依舊行不通,單純的函式指標 (如上) ok。但是,成員函式指標 依然無法 work,最後的解決辦法是將 on_mouse 變成一個 cpp 的全域變數,然後再用 friend 使其可以存取類別的私有成員...
...
CVAPI(void) cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param CV_DEFAULT(NULL));
一旦 window_name 視窗發生動作就會驅動 on_mouse 事件方法,但是這個 on_mouse 方法不能是類別的方法成員 ( 例:object->on_mouse ),嘗試後發現,可以利用函數指標將 on_mouse 方法 assign 成 object 的函數指標成員,這樣就可以成功的將事件方法封裝到類別之中。
// ctrl.h
typedef void (*pFun)(int, int, int, int, void*);
class Controller {
public:
Controller();
pFun pFun1;
};
// ctrl.cpp
#include <iostream>
#include <highgui.h>
#include "ctrl.h"
void on_mouse( int event, int x, int y, int flags, void *param )
{
if( event == CV_EVENT_LBUTTONDOWN )
std::cout << "LBUTTONDOWN occurs in the window" << std::endl;
}
Controller::Controller()
{
pFun1 = &on_mouse;
}
// main.cpp
#include <highgui.h>
#include "ctrl.h"
int main()
{
Controller controller;
cvNamedWindow("src", 1);
cvSetMouseCallback( "src", controller.pFun1, 0 );
while(1) {
int c = cvWaitKey(30);
if ( (char)c == 27 ) {
cvDestroyWindow( "src" );
break;
}
}
}
實作之後發現,此法依舊行不通,單純的函式指標 (如上) ok。但是,成員函式指標 依然無法 work,最後的解決辦法是將 on_mouse 變成一個 cpp 的全域變數,然後再用 friend 使其可以存取類別的私有成員...
...
Labels:
encapsulation,
event,
openCV
10/12/2010
用 Google Code 作專案的版本控制
Google Code 上頭除了有許多 open source project 可以挖寶,它也是一個免費的專案 hosting 和版本控制的好工具!
參考資料:
如何將資料夾移除版本控制:http://tortoisesvn.net/node/343
TortoiseSVN 使用簡介:http://www.dev.idv.tw/mediawiki/index.php/TortoiseSVN 使用簡介
......
參考資料:
如何將資料夾移除版本控制:http://tortoisesvn.net/node/343
TortoiseSVN 使用簡介:http://www.dev.idv.tw/mediawiki/index.php/TortoiseSVN 使用簡介
......
Labels:
google,
version control
10/02/2010
[iPhone] 了解 PhotoPicker 當中的委派機制
最近想要實作一個 iPhone 手機上的照相軟體,因此稍微研究了一下有關 camera 相關的資料。首先 iPhone 當中處理 camera 的主要是 UIImagePickerController 這個 class。利用 UIImagePickerControllerDelegate 和 UIImagePickerController 就可以開始處理/控制 iPhone 的 camera 和 photo library。
在 Beginning iPhone3 Development 書中,關於 Camera 的章節範例,主要是以 UIViewerController 下的 ModalView ( - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated ) 模式來呈現擷取到的照片,這個模式下的照片並非全螢幕,仍保留一些 Nav Bar 或者 Tool Bar,跟一般看到的 app 可以在拍照完以後在全螢幕模式下編輯不太一樣。
在 Apple Developer 網站當中有一個 PhotoPicker 的範例,主要就是在演示,如何不使用 ModalView 的方式取得 camera 所拍攝到的原始影像,在將這個影像填入你要呈現的 View 當中。
該範例當中宣告了兩個 ViewController:MyViewController 和 OverlayViewController,前者主要就是客製化的 View 想要用來避開 ModalView 模式的方式。後者的 .h 如下程式碼宣告,這個 class 當中包含了一個 UIImageViewController 並且還有一個 遵守 OverlayViewControllerDelegate 協定的成員 "delegate"。
可以看到這個 OverlayViewControllerDelegate 當中列出了兩個必要實現的方法 didTakePicture 和 didFinishWithCamera。這兩個方法的名稱看起來像是系統發出的事件,但是先前提到,有關照相相關的任務主要是以 UIImagePickerController 這個 class 所控制,所以來看看 OverlayViewControllerDelegate 的 .m 檔。
可以看到在實現 UIImagePickerControllerDellegate 的兩個方法當中,偷偷地把事件和影像的資訊 委派給 OverlayViewControllerDelegate protocol 的方法,那麼誰負責做這個 protocol 當中描述的這兩件事呢,答案就是 MyViewController!
上面 MyViewController 實現碼當中可以看到,他包含了一個 OverlayViewController 物件,並且他將該物件的代理設定為 "自己" ( self.overlayViewController.delegate = self; ),最後他實現了這個 OverlayViewControllerDelegate 這 protocol 的兩個方法,將 UIImagePickerController 得到的影像資料神奇的存到自己的成員 capturedImages 當中。
簡而言之,OverlayViewController 將 UIImagePickerControllerDelegate 和 UIImagePickerController 包裝起來,所以富有預設的圖片顯示功能,但是他並沒有用 Modal 的方式,而是將他取得的照片,傳給自己的 delegate 成員。而 MyViewController 有一個 OverlayController 成員,又將自己指向 OverlayController 的 delegate 成員。因此等效於 UIImagePickerController 把取得的照片傳給 MyViewController。
......
在 Beginning iPhone3 Development 書中,關於 Camera 的章節範例,主要是以 UIViewerController 下的 ModalView ( - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated ) 模式來呈現擷取到的照片,這個模式下的照片並非全螢幕,仍保留一些 Nav Bar 或者 Tool Bar,跟一般看到的 app 可以在拍照完以後在全螢幕模式下編輯不太一樣。
在 Apple Developer 網站當中有一個 PhotoPicker 的範例,主要就是在演示,如何不使用 ModalView 的方式取得 camera 所拍攝到的原始影像,在將這個影像填入你要呈現的 View 當中。
該範例當中宣告了兩個 ViewController:MyViewController 和 OverlayViewController,前者主要就是客製化的 View 想要用來避開 ModalView 模式的方式。後者的 .h 如下程式碼宣告,這個 class 當中包含了一個 UIImageViewController 並且還有一個 遵守 OverlayViewControllerDelegate 協定的成員 "delegate"。
@protocol OverlayViewControllerDelegate; @interface OverlayViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate> { id <OverlayViewControllerDelegate> delegate; UIImagePickerController *imagePickerController; @private ... } @property (nonatomic, assign) id <OverlayViewControllerDelegate> delegate; @property (nonatomic, retain) UIImagePickerController *imagePickerController; ... @end @protocol OverlayViewControllerDelegate - (void)didTakePicture:(UIImage *)picture; - (void)didFinishWithCamera; @end
可以看到這個 OverlayViewControllerDelegate 當中列出了兩個必要實現的方法 didTakePicture 和 didFinishWithCamera。這兩個方法的名稱看起來像是系統發出的事件,但是先前提到,有關照相相關的任務主要是以 UIImagePickerController 這個 class 所控制,所以來看看 OverlayViewControllerDelegate 的 .m 檔。
#pragma mark - #pragma mark UIImagePickerControllerDelegate // this get called when an image has been chosen from the library or taken from the camera // - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage]; // give the taken picture to our delegate if (self.delegate) [self.delegate didTakePicture:image]; if (![self.cameraTimer isValid]) [self finishAndUpdate]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [self.delegate didFinishWithCamera]; // tell our delegate we are finished with the picker } @end
可以看到在實現 UIImagePickerControllerDellegate 的兩個方法當中,偷偷地把事件和影像的資訊 委派給 OverlayViewControllerDelegate protocol 的方法,那麼誰負責做這個 protocol 當中描述的這兩件事呢,答案就是 MyViewController!
- (void)viewDidLoad { self.overlayViewController = [[[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:nil] autorelease]; // as a delegate we will be notified when pictures are taken and when to dismiss the image picker self.overlayViewController.delegate = self; self.capturedImages = [NSMutableArray array]; if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { // camera is not on this device, don't show the camera button NSMutableArray *toolbarItems = [NSMutableArray arrayWithCapacity:self.myToolbar.items.count]; [toolbarItems addObjectsFromArray:self.myToolbar.items]; [toolbarItems removeObjectAtIndex:2]; [self.myToolbar setItems:toolbarItems animated:NO]; } } // as a delegate we are being told a picture was taken - (void)didTakePicture:(UIImage *)picture { [self.capturedImages addObject:picture]; } // as a delegate we are told to finished with the camera - (void)didFinishWithCamera { [self dismissModalViewControllerAnimated:YES]; if ([self.capturedImages count] > 0) { if ([self.capturedImages count] == 1) { // we took a single shot [self.imageView setImage:[self.capturedImages objectAtIndex:0]]; } else { // we took multiple shots, use the list of images for animation self.imageView.animationImages = self.capturedImages; if (self.capturedImages.count > 0) // we are done with the image list until next time [self.capturedImages removeAllObjects]; self.imageView.animationDuration = 5.0; // show each captured photo for 5 seconds self.imageView.animationRepeatCount = 0; // animate forever (show all photos) self.imageView.startAnimating; } } }
上面 MyViewController 實現碼當中可以看到,他包含了一個 OverlayViewController 物件,並且他將該物件的代理設定為 "自己" ( self.overlayViewController.delegate = self; ),最後他實現了這個 OverlayViewControllerDelegate 這 protocol 的兩個方法,將 UIImagePickerController 得到的影像資料神奇的存到自己的成員 capturedImages 當中。
簡而言之,OverlayViewController 將 UIImagePickerControllerDelegate 和 UIImagePickerController 包裝起來,所以富有預設的圖片顯示功能,但是他並沒有用 Modal 的方式,而是將他取得的照片,傳給自己的 delegate 成員。而 MyViewController 有一個 OverlayController 成員,又將自己指向 OverlayController 的 delegate 成員。因此等效於 UIImagePickerController 把取得的照片傳給 MyViewController。
......
Subscribe to:
Posts (Atom)