I have started coding cocoa app. I have created a NSwindow with initWithContentRect.
I have created a NSTextField. I can not get any of the keyboard events. It is selectable. I also explicitly set editable to true.
I have realized there are similar questions but they are mostly about the responder, key window and Borderlesswindow style.
I have a NSWindows which has a titled window mask , is the key window and it is selected when I set it to be the first responder.
But why cant I type anything into the box.
int style = NSClosableWindowMask |NSTexturedBackgroundWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask;
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 130, 150)
styleMask:style backing:NSBackingStoreBuffered defer:NO];
CGFloat height=20;
NSTextField * username=[[NSTextField alloc] initWithFrame:NSMakeRect(10, NSHeight(window.frame)-80, 100, height)];
[username setEditable:true];
[window.contentView addSubview:username ];
Is it because I need to create a subclass of NSwindow. I see this is suggested when the style is NSBorderlessWindowMask and by overriding
canBecomeKeyWindow it is suggested to solve the issue.
But I am not using NSBorderlessWindowMask.
What am I missing? Any help is appreciated.
From your comment, you say you don't have a Info.plist file. I'm guessing your app isn't even bundled. This is a crucial fact that you left out of your question, which only makes it hard for people to help you.
First, you should create apps the normal way. Make a bundled app with a main NIB. Follow the standard template, except delete the window from the main NIB and use separate window NIBs.
If you aren't equipped to understand what's going wrong with a "manually" constructed app and fix it, then you really shouldn't be going that route.
That said, an unbundled app will start life as a background-only process. What little interactivity you're seeing is, more or less, a bug. You can transform your app into a foreground app by setting the activationPolicy of the application object (instance of NSApplication or a subclass) to NSApplicationActivationPolicyRegular. Then, make it the active app by calling [NSApp activateWithOptions:NSApplicationActivateIgnoringOtherApps].
Related
I have a NSView inside of my "menubar". I have a button where which i click on and add a new NSMenuItem to the menu. However when i run this code which is inside my custom view in the init method sometimes the view will get grayed out and I'm unable to select it. Any ideas what this could be the cause of this. The problem seems to affect all created NSMenuItems after this problem occur.
-(id)initWithFrame:(NSRect)frameRect andTag:(int)tagz{
textfeild = [[NSTextView alloc]initWithFrame:CGRectMake(19,1 , 110, 18)];
[textfeild setFont:[NSFont fontWithName:#"Helvetica" size:15]];
[textfeild setString:[NSString stringWithFormat:#"Notespace %d",tagz]];
[textfeild selectAll:self];
[self addSubview:textfeild];
}
I don't think you are supposed to use [self addSubview:] on a menu item. Instead, you are supposed to create an NSView and place your custom view inside it. Documentation is here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MenuList/Articles/ViewsInMenuItems.html
However, according to the documentation views inside a menu item may not receive keyboard events. It may work sometimes, but since the documentation specifically mentions it you should not place any view that needs keyboard events inside a menu.
What you should do instead, is avoid NSMenu altogether and simply create an NSWindow where the menu would normally appear. You can make your window look/behave like a menu.
Basically I have a main screen that comes up with a background image and three menu choices across the bottom of the screen. When I add these 4 components to the RootViewController's view, everything works fine., but if I do something like
_mainContainer = [[UIView alloc] init];
self.view = _mainContainer;
_firstScreen = [[UIView alloc] initWithFrame:self.view.frame];
"some code here setting up the subviews"
[buttonLeft addTarget:self action:#selector(startGame) forControlEvents:UIControlEventTouchUpInside];
[_firstScreen addSubview:mainMenuBackground];
[_firstScreen addSubview:buttonLeft];
[_firstScreen addSubview:buttonMid];
[_firstScreen addSubview:buttonRight];
[_mainContainer addSubview:_firstScreen];
Essentially if I add everything directly to _mainContainer, the buttons work, if I add it to _firstScreen, then add _firstScreen they don't work.
User interaction is enabled on _firstScreen. I do something similar later in my app and it works fine. Also, not sure if this has anything to do with it, but despite my screen being displayed in landscape, and all options in the plist being set to landscape only, when I run a transition, like flipFromBottom (or whatever its called), my app thinks the "bottom" is with the screen being in portrait until I move to another group of subviews in my app. (So basically the title screen is acting screwy).
I looked everywhere for a solution, hopefully I am not missing something basic.
Hey what is mainMenuBackground?, if its a image , their is no need to make it as a subView, instead, the correct way is to set it as a background image. I hope this will solve your problem
my app has tabBarController with 3 views and in one of them I want to popup a web browser with the ability to return back to the application. To do that I am using UINavigationController.
In myAppDelegate.h I have defined the property UINavigationController *nav and in myAppDelegate.m I have #synthesize nav.
In the class where the webPopup function resides upon pressing the button my code comes to this function.
- (IBAction)showWeb:(id)sender {
myAppDelegate *app=[[UINavigationController alloc] initWIthRootViewController:self];
// because I want to return back to the same view
webController *web = [[webController alloc] initWithStyle:UITableViewStypeGrouped];
[app.nav pushViewController:web animated:YES];
app.nav.view.frame = CGRect(,0,320,430);
[self.view.window addSUbview:app.nav.view];
}
The web popup occurs but it is moved vertically, when I press "back button" my former view appears as well and it is also shifted vertically from what it was before.
After going back and forth few times the thing hangs.
Questions:
1. what can cause the shift?
2. how to avoid when I go "back" to see the title(test from the "back"button, I think this might cause a shift when I go back.
3. how to find out why it hangs after few attempt?
Thanks.
Victor
The line:
myAppDelegate *app=[[UINavigationController alloc] initWIthRootViewController:self];
makes no sense to me. Surely your compiler is warning you about that? What is "myAppDelegate" defined as? Classes should have a capital letter at the front, by the way.
Also, the line
[self.view.window addSUbview:app.nav.view];
is highly suspect, because the UIWindow for your application should have only one child UIView. You shouldn't just add more views willy nilly and expect things to work. It is possible to change the child UIView by removing the old one and adding a new one, but you don't seem to be doing that. Having more than one child UIView of UIWindow gets you into trouble very quickly -- for example, device orientation changing can break.
I'm not exactly clear as to why the app delegate (or the window for that matter) needs to be messed with at all to do what you are trying to do. Sounds like you should just be using standard Nav View Controllers and Web Views.
Also, you are alloc init'ing w/o any memory management.
I'm just not getting this, I want to display a view in my app when a user clicks a button.
I've gotten this far:
NSView* unitMarker = [[NSView alloc] initWithFrame: NSMakeRect( 20.0, 20.0, 80.0, 50.0 ) ];
How would I display this view with a red background?
Thanks
#Aaron: he says he wants to do this programmatically. Also he's using NSView, not UIView, so an iPhone tutorial would be almost irrelevant.
#Mike: Your description of what you want to do is a bit vague. We have a bit of code creating, a view, but no context to tell us exactly what you are trying to do. Do you want the view to come up in a new window or the same? Do you want to replace a view that's already there? We don't even really know your skill level.
I suggest you go check out the documentation for NSView: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html
I've gotten this far:
NSView* unitMarker = [[NSView alloc] initWithFrame: NSMakeRect( 20.0, 20.0, 80.0, 50.0 ) ];
How would I display this view with a red background?
You wouldn't, because a plain NSView doesn't draw anything.
First, you need to subclass NSView, implement drawRect: in that subclass to fill its bounds with red, and instantiate that subclass instead of NSView directly.
You should read the View Programming Guide.
How would I display this view …
You wouldn't. The view displays itself when it is appropriate to do so.
It won't ever be appropriate for it to draw itself until you add it to a view hierarchy. Every window has one, rooted at its content view. You need to add this view either to a content view or to some descendant view (subview, subview of a subview, etc.) of a content view.
You normally should not tell a view to display from your controller. That's the window's job. When you do change a property or properties of the view that affect what it draws, set the view as needing display, and let the window tell the view to display when it's appropriate to do that.
Say this out loud 10 times repeatedly:
Interface Builder is my friend.
I was able to put together a sample project doing exactly what you want to do in about 5 minutes by leveraging Interface Builder as part of the process. http://www.markdouma.com/developer/ShowWindowWithRedView.zip.
You can't show a view without placing it in a window first; by far the easiest way to do this kind of a thing is to drag out a second window in Interface Builder, set it to not be visible on launch, drag a generic NSView custom view onto the Window, set its class to be SRRedView (your red view subclass). As d11wtq posted, you override NSView's primitive drawing method like he shows (though personally I prefer NSBezierPath :-P).
In your controller class, you define IBOutlets, and then hook those up in Interface Builder. These provide you with a way to reference the important parts of your interface so that you can manipulate them programmatically.
I added one IBAction method, which the button in the main window is hooked up to call. That method simply tells the second window to show itself.
- (IBAction)showWindowWithRedView:(id)sender {
[windowWithRedView makeKeyAndOrderFront:nil];
}
In the 8 years or more that I've been doing Cocoa programming, I don't think I've ever needed to resort to manually creating windows and views. It has always been much faster to simply load another nib file that contains the windows or views I need to display. Using Interface Builder along with Xcode to create your app is quite a bit different than how other IDEs work. (Specifically, when you arrange stuff in Interface Builder you're not generating code as much as you are creating instances of UI objects and then "freeze-drying" them in their current arrangement into a .nib archive file. When you launch the app, they are brought back to life. Or at least that's the way I think about it).
You need to subclass NSView and implement drawRect:.
In this case you're just going to fill the entire rect with red.
#interface MyView : NSView {
}
#end
#implementation MyView
-(void)drawRect:(NSRect)dirtyRect {
[[NSColor redColor] set];
NSRectFill(dirtyRect);
}
#end
That's an extremely basic example that does what you want, but if you want to do more complex things (adding borders (strokes) or drawing curves (paths) etc), then you need to learn all the drawing classes available to you.
Scott Stevenson has written some easy to follow tutorials on this:
http://cocoadevcentral.com/d/intro_to_quartz/ and;
http://cocoadevcentral.com/d/intro_to_quartz_two/
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?
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.
You're probably running afoul of automatic window positioning. Have you tried calling
[myWindowController setShouldCascadeWindows: NO];
?
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:.
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.