2010-02-12 70 views
10

我有一個奇怪的問題,在屏幕上定位一個窗口。我想將窗口居中在屏幕上,但我不知道該怎麼做。這是我得到的。由主控制器從筆尖創建窗口:可可窗口位置異常

IdentFormController *ftf = [[IdentFormController alloc] initWithWindowNibName:@"IdentForm"]; 
[[ftf window] makeKeyAndOrderFront:self]; 

現在IdentFormController具有其中它試圖定位窗口awakeFromNib()方法。爲了簡單起見,我只是試圖做setFrameOrigin(NSMakePoint(0,0))。會發生什麼如下:

我第一次創建這個窗口,一切都按預期工作。但是如果我在釋放之前再次創建它,它會開始出現在隨機位置。它爲什麼這樣做?

+5

* ftf *是一個變量的可怕名稱,並可能在稍後成爲維護問題。 – 2010-03-21 14:05:03

回答

1

首先,聽起來好像您需要在NSWindow的財產檢查員中檢查「關閉時的dealloc」或「關閉時釋放」。然後,窗口將自行清理,您可以在自己的代碼中刪除(風險)呼叫[self release]

awakeFromNib在來自筆尖的所有對象都被解除存檔並且插座已連接之後被調用,但這可能爲設置窗口座標提供了太早的時間。我相信可可做了一些工作來自動將後面的窗口放在現有窗口的右下方,以便新窗口不會完全遮擋舊窗口。在你設置了awakeFromNib中的位置之後,可能會這樣做,跺腳你的改變。

設置窗口位置的最佳位置可能在NSWindow代表方法之一(或許是windowWillBecomeVisible:),或者可能在您撥打makeKeyAndOrderFront:之前。

+0

由於某種原因,當關閉發佈時被檢查不起作用。該窗口可能已經釋放並清理,但控制器如何?也許它沒有被釋放。只要我添加了[自我釋放] - 這個事情終於奏效了。也許這是有風險的,但至少它有效,當你釋放一個控制器時 - 它也會清理窗口。 – Marius 2010-02-23 13:54:53

+0

我想我誤解了'[self release]'適用於NSWindow實例,而不是控制器。也許爲了讓事情更清楚,你的應用程序委託應該維護一個指向當前IdentFormController的指針。或者如果你必須釋放self,使用'autorelease',這樣對象不會被釋放,直到運行循環結束。無論如何:是否將代碼移至委託方法幫助? – benzado 2010-02-23 15:04:11

+0

那麼,我還沒有機會測試它,但我相信它會工作。如果它與[自我釋放]一起工作 - 那麼爲什麼它不能從外部工作。順便說一句:爲什麼[自我釋放]有風險?如果我確定我不需要這個控制器,並且沒有任何東西會嘗試訪問它,但[自釋放]會發生什麼問題? – Marius 2010-02-25 12:41:10

0

看看您是否可以用屏幕中心設置窗口中心。並在上面設置窗口位置。它可能會解決。

14

因此,據我瞭解,你想要在屏幕上居中窗口?

那麼假設NSWindow *window是你的窗口對象,然後有兩種方法...

[window center]; 

這是做到這一點的最好方式,但它會OFSET考慮到視覺重量和碼頭的存在。

如果你想死點那麼這將工作...

// Calculate the actual center 
CGFloat x = (window.screen.frame.size.width - window.frame.size.width)/2; 
CGFloat y = (window.screen.frame.size.height - window.frame.size.height)/2; 

// Create a rect to send to the window 
NSRect newFrame = NSMakeRect(x, y, window.frame.size.width, window.frame.size.height); 

// Send message to the window to resize/relocate 
[window setFrame:newFrame display:YES animate:NO]; 

此代碼是未經測試,但它給你的,你需要做的就是這件事的工作,你所希望的方式是什麼一個公平的想法,我個人建議你堅持使用Apple的代碼,因爲它已經過測試,並且是用戶期望看到的,從設計角度來看,作爲設計師我自己並不總是依賴實際中心來成爲光學中心是。

5

您可能會遇到自動窗口定位的問題。您是否嘗試致電

[myWindowController setShouldCascadeWindows: NO];