11

I have a weird problem with positioning a window on screen. I want to center the window on the screen, but i don't know how to do that. Here's what i've got. The window is created from nib by the main controller:

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

Now the IdentFormController has awakeFromNib() method in which it tries to position the window. For the sake of simplicity i've just tried to do setFrameOrigin(NSMakePoint(0, 0)). What happens is as follows:

The first time i create this window, everything works as expected. But if i create it again after releasing the previous, it starts appearing at random positions. Why does it do that?

benzado
  • 82,288
  • 22
  • 110
  • 138
Marius
  • 111
  • 1
  • 3

4 Answers4

15

So as I understand it you want to center the window on the screen?

Well assuming NSWindow *window is your window object then there are two methods...

[window center];

This is the best way to do it but it will ofset to take into account visual weight and the Dock's presence.

If you want dead center then this would work...

// 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];

This code is untested but it gives you a fair idea of what you need to do to get this thing working the way you want, personally I would advise you stick with Apple's code because it has been tested and is what the user would expect to see, also from a design perspective as a designer my self I don't always rely on the actual center to be where the optical center is.

Community
  • 1
  • 1
unknowndomain
  • 985
  • 1
  • 10
  • 34
6

You're probably running afoul of automatic window positioning. Have you tried calling

[myWindowController setShouldCascadeWindows: NO];

?

uliwitness
  • 8,532
  • 36
  • 58
1

First of all, it sounds like you need to check "dealloc on close" or "release on close" in the NSWindow's property inspector. Then the window will clean up after itself and you can remove the (risky) call to [self release] in your own code.

awakeFromNib is called after all objects from the nib have been unarchived and outlets have been connected, but that may be too early to be setting the window coordinates. I believe Cocoa does some work to automatically position subsequent windows below and to the right of existing windows, so that new windows don't completely obscure old ones. It is likely doing this AFTER you set the position in awakeFromNib, stomping on your changes.

The best place to set your window position is probably in one of the NSWindow delegate methods (windowWillBecomeVisible: perhaps), or possibly right before you call makeKeyAndOrderFront:.

benzado
  • 82,288
  • 22
  • 110
  • 138
  • For some reason it didn't work when the release on close was checked. The window might have been deallocating and cleaning up, but how about the controller? Maybe it wasn't being deallocated. As soon as i've added [self release] - the thing finally worked. Maybe it's risky, but at least it works and when you release a controller - then it cleans up the window as well. – Marius Feb 23 '10 at 13:54
  • I think I misinterpreted `[self release]` as applying to the NSWindow instance, not the controller. Maybe to make things clearer, your app delegate should maintain a pointer to the current IdentFormController. Or if you have to release self, use `autorelease` so the object isn't deallocated until the end of the run loop. Regardless: did moving the code to a delegate method help? – benzado Feb 23 '10 at 15:04
  • Well, i didn't have a chance to test it yet, but i'm sure it would work. If it works with [self release] - then why wouldn't it work from outside. By the way: why is [self release] risky? If i'm sure i won't need this controller and nothing's going to try and access it - what problems could occur with [self release] ? – Marius Feb 25 '10 at 12:41
  • `[self release]` is risky because you could be executing the code of an object that has been freed. If it's the last line of your method you will probably be OK most of the time, but there are no guarantees. Why risk it if you can call `autorelease` instead? – benzado Feb 25 '10 at 15:46
  • The discussion about calling `[self release]` is a distraction from your main issue: **window positioning**. Did you have any success using a delegate method like `windowWillBecomeVisible:` instead of putting the code in `awakeFromNib`? – benzado Feb 25 '10 at 15:48
  • Sorry, won't be able to test that for a while. I had success even in awakeFromNib after i made sure that the previous controller has been destroyed. Before that i couldn't set any position at all, it only worked the first time. I will just use your previous idea and modify the app to destroy the previous controller outside of itself before creating another one. Then it will also work and there won't be any releases within the controller itself. And even though everything works like a charm now, the mystery of why it didn't work before still remains. – Marius Feb 26 '10 at 08:51
0

Check out if you can set the centre of your window with the centre of your screen. And set the window position on it. It might work out.

boom
  • 5,856
  • 24
  • 61
  • 96