per page, with , order by , clip by
Results of 0 - 1 of about 0 (0.001 sec.)
章 15. 農民曆
@digest: f27e37a76d3c293cffe9ef02d1fdf68a
@id: 133004
@mdate: 2003-09-19T18:46:42Z
@size: 16783
@type: text/html
content-type: text/html; charset=ISO-8859-1
generator: DocBook XSL Stylesheets V1.61.3
#keywords: tempcell (88334), calendarbox (73953), calendarview (69990), daymatrix (69263), lunarcalendardate (65547), yearlabel (64842), updatedate (59699), lastyearbutton (58948), nextyearbutton (58948), monthmatrix (54223), newdate (45262), monthcell (44167), daycell (40827), currentmonth (39799), lunardate (38796), 農曆 (36340), startdayofweek (33166), 民曆 (32129), 形15 (30995), 農民 (29794), initwithframe (29556), 日期 (27894), montharray (27250), currentyear (27250), 份. (24651), monthofyear (24371), nscentertextalignment (24371), nscalendardate (24177), nsmakerect (23210), 來顯 (22510), 個ce (22494), 期. (22316)
章 15. 農民曆 前一頁 部 V. 基礎 GNUstep 程式設計 下一頁 章 15. 農民曆 農民曆目前還是常常會用到. 在這裡製做一個計算農曆的程式, 主要是介紹 NSMatrix 的用法. 在這裡做一個顯示日期的 View, 如下: 圖形 15.1. CalendarView 太陽曆轉農曆不是這裡的重點, 有興趣人可以參考程式碼. 在這裡只列出其 Interface. LunarCalendarDate.h #ifndef _LunarCalendarDate_ #define _LunarCalendarDate_ #include <Foundation/NSObject.h> @interface LunarCalendarDate: NSObject { int lunarDay, lunarMonth; } - (void) setDate: (NSCalendarDate *) date; - (int) dayOfMonth; - (int) monthOfYear; @end #endif /* _LunarCalendarDate_ */ 在 LunarCalendarDate 中設定日期, 即可得知農曆的月, 日. 這個轉換程式不能保證完全正確. 只能計算 1998-2003 年的日期. 接著, 使用 Gorm 建立如下的使用者介面: 圖形 15.2. 農民曆的使用者介面 繼承自 NSView, 製做一個 CalendarView 類別. 使用這個類別做為 Custom Class 的類別. 設定大小為寬 240, 高 270. 在最上面加個 NSTextField, 用來顯示農曆. 在 CalendarView 中加入一個 "label" outlet. 圖形 15.3. 增加 outlet 連結 "label" outlet 至 NSTextField 圖形 15.4. 連結 outlet 將檔案存成 LunarCalendar.gorm. 接著要實作 CalendarView. CalendarView.h #ifndef _CalendarView_ #define _CalendarView_ #include <AppKit/AppKit.h> @interface CalendarView : NSView { NSBox *calendarBox; NSTextField *yearLabel; NSButton *lastYearButton, *nextYearButton; NSMatrix *monthMatrix, *dayMatrix; NSCalendarDate *date; NSArray *monthArray; /* Outlet */ id label; } - (NSCalendarDate *) date; - (void) setDate: (NSCalendarDate *)date; /* Used by interface */ - (void) updateDate: (id) sender; @end #endif /* _CalendarView_ */ CalendarDate.m Setup basic header and functions #include "CalendarView.h" #include "LunarCalendarDate.h" @implementation CalendarView #define isLeapYear(year) (((year % 4) == 0 && ((year % 100) != 0)) || (year % 400) == 0) static short numberOfDaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3 1}; 在這裡使用 NSMatrix 來顯示月份及日期. - (id) initWithFrame: (NSRect) rect { int i, j, count=0; NSImage *rightArrow, *leftArrow; NSButtonCell *monthCell, *dayCell, *tempCell; NSArray *weekArray; [super initWithFrame: rect]; 增加一個 NSBox, 等下所有的圖形介面都會加入這個 NSBox. calendarBox = [[NSBox alloc] initWithFrame: NSMakeRect(0, 0, 240, 270)]; [calendarBox setBorderType: NSGrooveBorder]; [calendarBox setTitlePosition: NSAtTop]; [calendarBox setTitle: @"Calendar"]; 使用兩個按鈕及一個字串來顯示及調整年份. 其中的圖檔是 GNUstep 附加的. 當使用者按下按鈕時, -updateDate: 會被呼叫. yearLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(85, 220, 60, 20)]; [yearLabel setStringValue: @"This Year"]; [yearLabel setBezeled: NO]; [yearLabel setBackgroundColor: [NSColor windowBackgroundColor]]; [yearLabel setEditable: NO]; [yearLabel setSelectable: NO]; [yearLabel setAlignment: NSCenterTextAlignment]; leftArrow = [NSImage imageNamed: @"common_ArrowLeft.tiff"]; rightArrow = [NSImage imageNamed: @"common_ArrowRight.tiff"]; lastYearButton = [[NSButton alloc] initWithFrame: NSMakeRect(10, 220, 22, 22)]; [lastYearButton setImage: leftArrow]; [lastYearButton setImagePosition: NSImageOnly]; [lastYearButton setBordered: NO]; nextYearButton = [[NSButton alloc] initWithFrame: NSMakeRect(198, 220, 22, 22)]; [nextYearButton setImage: rightArrow]; [nextYearButton setImagePosition: NSImageOnly]; [nextYearButton setBordered: NO]; [lastYearButton setTarget: self]; [lastYearButton setAction: @selector(updateDate:)]; [nextYearButton setTarget: self]; [nextYearButton setAction: @selector(updateDate:)]; [calendarBox addSubview: yearLabel]; [calendarBox addSubview: lastYearButton]; [calendarBox addSubview: nextYearButton]; RELEASE(yearLabel); RELEASE(lastYearButton); RELEASE(nextYearButton); Matrix 可以將 NSCell 排成棋盤狀. NSCell 是精簡版的 NSView, 可參考 Introduction to Controls and Cells . 首先是要定義 NSMatrix 中的 Cell 的屬性, NSMatrix 會用這個 Cell 來顯示所有的 Cell. 每個 Cell 都有個標箋 (Tag), 以用來區份各個 Cell. monthArray = [[NSArray alloc] initWithObjects: @"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec", nil]; monthCell = [[NSButtonCell alloc] initTextCell: @""]; [monthCell setBordered: NO]; [monthCell setShowsStateBy: NSOnOffButton]; [monthCell setAlignment: NSCenterTextAlignment]; monthMatrix = [[NSMatrix alloc] initWithFrame: NSMakeRect(10, 165, 210, 50) mode: NSRadioModeMatrix prototype: monthCell numberOfRows: 2 numberOfColumns: 6]; for (i = 0; i < 2; i++) for (j = 0; j < 6; j++) { tempCell = [monthMatrix cellAtRow: i column: j]; [tempCell setTag: count]; [tempCell setTitle: [monthArray objectAtIndex: count]]; count++; } RELEASE(monthCell); weekArray = [NSArray arrayWithObjects: @"Sun", @"Mon" @"Tue", @"Wed", @"Thr", @"Fri", @"Sat", nil]; dayCell = [[NSButtonCell alloc] initTextCell: @""]; [dayCell setBordered: NO]; [dayCell setShowsStateBy: NSOnOffButton]; [dayCell setAlignment: NSCenterTextAlignment]; dayMatrix = [[NSMatrix alloc] initWithFrame: NSMakeRect(10, 20, 210, 120) mode: NSRadioModeMatrix prototype: dayCell numberOfRows: 7 numberOfColumns: 7]; for (j = 0; j < 7; j++) { tempCell = [dayMatrix cellAtRow: 0 column: j]; [tempCell setTitle: [weekArray objectAtIndex: j]]; [tempCell setAlignment: NSCenterTextAlignment]; [tempCell setEnabled: NO]; } RELEASE(dayCell); count = 0; for (i = 1; i < 7; i++) for (j = 0; j < 7; j++) { [[dayMatrix cellAtRow: i column: j] setTag: count++]; } 當 NSMatrix 被按下時, 會呼叫 Matrix 的 action, 在這裡設為 -updateDate:. [monthMatrix setTarget: self]; [monthMatrix setAction: @selector(updateDate:)]; [dayMatrix setTarget: self]; [dayMatrix setAction: @selector(updateDate:)]; [calendarBox addSubview: monthMatrix]; [calendarBox addSubview: dayMatrix]; RELEASE(monthMatrix); RELEASE(dayMatrix); [self addSubview: calendarBox]; RELEASE(calendarBox); return self; } 在 dayMatrix 的內容因月份而改變, 所以當日期變時, 其日期的顯示要隨之改變. - (void) setDate: (NSCalendarDate *) newDate { int i, currentDay, currentMonth, currentYear; int daysInMonth, startDayOfWeek, day; NSCalendarDate *firstDayOfMonth; NSButtonCell *tempCell; LunarCalendarDate *lunarDate; 在這裡保留日期, 在 -dealloc 中釋放. ASSIGN(date, newDate); 更新年份. [yearLabel setStringValue: [date descriptionWithCalendarFormat: @"%Y"]]; 更新月份. currentMonth = [date monthOfYear]; [monthMatrix selectCellWithTag: currentMonth-1]; 更新日期. currentYear = [date yearOfCommonEra]; firstDayOfMonth = [NSCalendarDate dateWithYear: currentYear month: currentMonth day: 1 hour: 0 minute: 0 second: 0 timeZone: [NSTimeZone localTimeZone]]; daysInMonth = numberOfDaysInMonth[currentMonth - 1]; if ((currentMonth == 2) && (isLeapYear(currentYear))) daysInMonth++; startDayOfWeek = [firstDayOfMonth dayOfWeek]; day = 1; for (i = 0; i < 42; i++) { tempCell = [dayMatrix cellWithTag: i]; if (i < startDayOfWeek || i >= (daysInMonth + startDayOfWeek)) { [tempCell setEnabled: NO]; [tempCell setTitle: @""]; } else { [tempCell setEnabled: YES]; [tempCell setTitle: [NSString stringWithFormat: @"%d", day++]]; } } currentDay = [date dayOfMonth]; [dayMatrix selectCellWithTag: startDayOfWeek + currentDay - 1]; 使用 LunarCalendarDate 計算農曆日期, 並在 label 中更新. /* Update label */ lunarDate = [LunarCalendarDate new]; [lunarDate setDate: date]; [label setStringValue: [NSString stringWithFormat: @"%@ %d", [monthArray objectA tIndex: [lunarDate monthOfYear]-1], [lunarDate dayOfMonth]]]; RELEASE(lunarDate); } 當這個程式開始時, 需要預設成當日時間. 但 CalendarView 不是 NSApp 的代理者, 所以無法知道程式何時始動. 但當 Gorm 被載入時, 會呼叫 -awakeFromNib, 因此可以使用 -awakeFromNib 來知道程式開始了. - (void) awakeFromNib { [self setDate: [NSCalendarDate calendarDate]]; } 最後, 要處理使用者輸入的部份. 所有使用者輸入都會進到 -updateDate:, 所以要依 sender 來做區別. - (void) updateDate: (id) sender { int i=0, j=0, k=0; NSCalendarDate *newDate; if (sender == lastYearButton) { i = -1; } else if (sender == nextYearButton) { i = 1; } else if (sender == monthMatrix) { j = [[[sender selectedCells] lastObject] tag] + 1 - [date monthOfYear]; } else if (sender == dayMatrix) { k = [[[[sender selectedCells] lastObject] stringValue] intValue] - [date dayO fMonth]; } newDate = [date addYear: i month: j day: k hour: 0 minute: 0 second: 0]; LunarCalendarDate 只支援 1998-2031, 因為超過的年份不與反應. if (([newDate yearOfCommonEra] > 1998) && ([newDate yearOfCommonEra] < 2031)) [self setDate: newDate]; } 程式碼在此: LunarCalendar-src.tar.gz 前一頁 上一層 下一頁 章 14. 系統資訊 內容 章 16. NSLookupService ...
http://www.gnu.org/savannah-checkouts/non-gnu/gstutorial/zh_TW/ch15.html - [detail] - [similar]
PREV NEXT
Powered by Hyper Estraier 1.4.13, with 213331 documents and 1081083 words.