Mouse Down events in Objective-C - objective-c

I know this question has been asked a lot before, but nothing will work for me. The following code will not do anything at all.
- (void) mouseDown:(NSEvent*)event {
NSLog(#"It worked!");
}
I have tried a lot of different methods to get this to work, including creating custom NSEvents in this way:
NSEvent *someEvent;
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
This is my .h file:
#interface test : NSWindow <NSWindowDelegate> {
}
Would somebody explain how to make this do something?

Make sure your class inherits from NSWindow and conforms to the <NSWindowDelegate> protocol. Otherwise, that's just a method that happens to be named mouseDown, and nobody will ever call it.
Update: Change your header file so that it looks like this:
#interface test : NSWindow <NSWindowDelegate> {
}
In other words, don't put a prototype of mouseDown inside the interface definition, or anywhere else in the .h file.
In your implementation file (.m) put just the method:
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
Assuming that you have logging turned on in the device (are you sure you can read NSLog output from elsewhere in your program?), you should see "It worked!" printed there.
I'm not an obj-C expert by any means, but I think by putting the mouseDown prototype inside the interface definition, you were basically creating your own custom mouseDown method which hid the "real" one. This indicated to the compiler that it should not call your mouseDown method on a window click.

Your subclass must have a parent class of NSResponder, otherwise you will not get any events.

You're overriding the NSWindow class, you should be overriding the NSView "contentView" of the NSWindow class to capture mouse events. Most of the decorations (NSViews) on the window outside of the contentView are private.
Just create a new NSView that overrides mouseDown, etc and add it as your content view to the NSWindow object.

Related

Why is this delegate method automatically called in Objective-C?

I'm going through this book called "cocoa programming for mac os x" and I just started with delegates. This whole thing with delegates is still a little bit wacky to me but I think I just need to let it settle.
However there was this one exercise where I should implement a delegate of the main window so that if resized height is always 2xwidth.
So I got 4 files:
AppDelegate.h
AppDelegate.m
WindowDelegate.h
WindowDelegate.m
AppDelegate are just the two standard files that get created when you open a new Cocoa project. I had to look up the solution because I didn't quite know how to accomplish this task.
The solution was just to create a new cocoa class, "WindowDelegat.h/.m" and add this to it's implementation file:
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
NSSize newSize = frameSize;
newSize.height = newSize.width * 2;
return newSize;
}
Then I opened the interface builder, added a new object and made it my WindowDelegate. I then had to ctrl drag from the WindowDelegate to the actual window and made it the window's delegate.
Clicked run and it worked. Yay! But why?
First I thought that "windowWillResize" is just one of these callback functions that get's called as soon as the window is resized but it isn't. Normally methods get invoked because the general lifecycle of an program invokes them or because they are an #IBAction, a button or different control elements.
But "windowWillResize" is non of them. So why is it called?
EDIT: Problem solved! Thanks a lot!
Now I'm trying to connect the delegate to the window programmatically. Therefore I deleted the referencing outlet from WindowDelegate to the actual window in interface builder. It works but I just want to verify that this it the correct way how it's done:
AppDelegate.h
#import <Cocoa/Cocoa.h>
#import "WindowDelegate.h"
#interface AppDelegate : NSObject <NSApplicationDelegate>
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#property (strong) WindowDelegate *winDeleg;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
- (void)awakeFromNib {
[_window setOpaque:NO];
NSColor *transparentColor = [NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.5];
[_window setBackgroundColor:transparentColor];
NSSize initialSize = NSMakeSize(100, 200);
[_window setContentSize:initialSize];
_winDeleg = [[WindowDelegate alloc] init];
[_window setDelegate: _winDeleg];
}
#end
WindowDelegate.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#interface WindowDelegate : NSObject <NSWindowDelegate>
#end
WindowDelegate.m
#import "WindowDelegate.h"
#implementation WindowDelegate
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {
NSSize newSize = frameSize;
newSize.height = newSize.width * 2;
return newSize;
}
- (id)init {
self = [super init];
return self;
}
#end
Why does the #property of WindowDelegate need to be strong?
And isn't my winDeleg an object? Why do I have to access it through _winDeleg when it's an object. I though the underscore is used to access variables?
Thank you for your help!
Clicked run and it worked. Yay! But why?
Because instances of NSWindow have a delegate property that can point to any object that implements the NSWindowDelegate protocol, and that protocol includes the -windowWillResize:toSize: method.
Read that a few times. The reason it's important is that you can create your own object, say that it implements NSWindowDelegate, implement -windowWillResize:toSize:, and set that object as your window's delegate. Then, whenever the user resizes the window, your method will be called and can modify the proposed new size.
Normally methods get invoked because the general lifecycle of an program invokes them or because they are an #IBAction, a button or different control elements. But "windowWillResize" is non of them. So why is it called?
This really isn't so different. Think of delegates as "helper objects." They let you customize the behavior of an object without having to create a whole new subclass. The NSWindowDelegate object is essentially a contract that the NSWindow promises to follow: whenever certain things happen, such as the user resizing the window, the window will call certain methods in its delegate object, if the delegate exists and implements those methods. In the case of NSApplication, a lot of those delegate methods are application lifecycle events, like the app starting up or quitting or getting a message from the operating system. In the case of NSWindow, delegate methods correspond to interesting events that can happen to a window, like the user moving it, hiding it, showing it, maximizing it, moving it to a different screen, etc. Other classes, like text views or network connections or movie players, have their own sets of interesting events and their own delegate protocols to match.
Note that methods marked IBAction really aren't delegate methods, they're just methods that get called by objects like controls that use a target/action paradigm. The IBAction keyword lets the IDE know which methods it should present as possible actions for things like buttons. You often find actions in window controllers and view controllers, and those objects frequently act as a delegate for some other object, but the actions themselves aren't part of the delegate protocol. For example, NSTableView takes a delegate object that determines how the table will act and what's displayed in it. It often makes sense for the view controller that manages the table to be the table's delegate, and that same view controller might also manage some buttons and contain the action methods that said buttons trigger, but the actions aren't part of the NSTableViewDelegate protocol and you therefore wouldn't call them delegate methods.

How to access objects from different classes in Cocoa Programming

I have an NSTextField subclass (called "txtField1" and used as Custom Class for a Text Field in my interface builder) and I would like to be able to access an NSComboBox object which present in my interface builder from this class.
This is my code:
txtField1.h:
#import <Cocoa/Cocoa.h>
#interface txtField1 : NSTextField
#end
txtField.m:
#import "txtField1.h"
#implementation txtField1
-(void)mouseDown:(NSEvent *)theEvent
{
HERE I would like to be able to write something like:
[combobox SetHidden:YES];
}
#end
I would like to be able to set access the combobox SetHidden property, in the mouseDown event.
Can you please tell me how to do that? I have tried different solutions found on internet but didn't obtain anything at all!
Any help would be appreciated.
Here are a lot of ways, and answers here, to do :
Update a label through button from different view
Xcode - update ViewController label text from different view
Setting label text in another class
Set label on another view to stored NSDate
EDIT:
-(void)mouseDown:(NSEvent *)theEvent
{
HERE I would like to be able to write something like:
[combobox SetHidden:YES];
/*
use the shared instance of comboBox here and make it hidden.
Also, you can use binding to make it hidden
*/
}
From my point of view txtField1 class is not better place to this code.
You can add NSControlTextEditingDelegate protocol to your NSViewController implementation (that already contains IBOutlets for txtField1 and combobox) and in method – control:textView:doCommandBySelector: implement hiding of your NSComboBox

Mouse Down events in Objective-C? [duplicate]

I know this question has been asked a lot before, but nothing will work for me. The following code will not do anything at all.
- (void) mouseDown:(NSEvent*)event {
NSLog(#"It worked!");
}
I have tried a lot of different methods to get this to work, including creating custom NSEvents in this way:
NSEvent *someEvent;
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
This is my .h file:
#interface test : NSWindow <NSWindowDelegate> {
}
Would somebody explain how to make this do something?
Make sure your class inherits from NSWindow and conforms to the <NSWindowDelegate> protocol. Otherwise, that's just a method that happens to be named mouseDown, and nobody will ever call it.
Update: Change your header file so that it looks like this:
#interface test : NSWindow <NSWindowDelegate> {
}
In other words, don't put a prototype of mouseDown inside the interface definition, or anywhere else in the .h file.
In your implementation file (.m) put just the method:
- (void) mouseDown:(NSEvent*)someEvent {
NSLog(#"It worked!");
}
Assuming that you have logging turned on in the device (are you sure you can read NSLog output from elsewhere in your program?), you should see "It worked!" printed there.
I'm not an obj-C expert by any means, but I think by putting the mouseDown prototype inside the interface definition, you were basically creating your own custom mouseDown method which hid the "real" one. This indicated to the compiler that it should not call your mouseDown method on a window click.
Your subclass must have a parent class of NSResponder, otherwise you will not get any events.
You're overriding the NSWindow class, you should be overriding the NSView "contentView" of the NSWindow class to capture mouse events. Most of the decorations (NSViews) on the window outside of the contentView are private.
Just create a new NSView that overrides mouseDown, etc and add it as your content view to the NSWindow object.

How do I handle a mousedown event inside a window in Cocoa

How do I handle a mousedown event inside a window in Cocoa?
My code:
-(void)mouseDown:(NSEvent *)event {
NSLog(#"yay");
}
I am using Mac OS10.6, in xcode 4.0.1.
EDIT:
Yes, this is in the app delegate, but this is my .h:
#interface jumperAppDelegate : NSWindow {
Which I have done before in app delegates (just not for mouse events). This is really annoying me
Make sure you inherit from NSWindow, as well as conform to the <NSWindowDelegate> protocol. Like this:
#interface YourWindow : NSWindow <NSWindowDelegate> {}
#end
Then you should receive the event notification.
-(void)mouseDown:(NSEvent *)event {
}
For this method to be called the class it is being called in needs to inherit from NSResponder. Windows and views are all subclasses of NSResponder. If the class you are calling this from is not a subclass of NSResponder then the method will not fire.
* Update *
Also be sure to override acceptsFirstResponder to return yes.
- (BOOL)acceptsFirstResponder {
return YES;
}
I don't know for sure, but I have heard that in your header file (.h) that you need to replace the "NSObject" with "NSWindow". I would test it but I am not at my computer right now.
Also, make sure that you put the following code into your header file:
- (void) mouseDown:(NSEvent*)event;
EDIT: I have done some tests and research, but I cannot get it to work. I have two tips though.
Use the '-acceptsFirstMouse method.
Try creating an NSEvent:
NSEvent * someEvent;
-(void)mouseDown:(NSEvent*)someEvent;
This probably won't work, but I will have more information tomarrow

Objective C Delegate for the Main Application Window

So I'm trying to do this exercise where I need to set a delegate for the main window. The purpose is to make sure that when the user resizes the window, it's always twice as wide as it is high.
This is my AppController.h file:
#import <Cocoa/Cocoa.h>
#interface AppController : NSObject
{
NSWindow *windowWillResize;
}
#end
and this is my AppController.m file:
#import "AppController.h"
#implementation AppController
- (id) init
{
[super init];
windowWillResize = [[NSWindow alloc] init];
[windowWillResize setDelegate:self];
return self;
}
- (NSSize) windowWillResize:(NSWindow *)sender
toSize:(NSSize)frameSize;
{
NSLog(#"size is changing");
return frameSize;
}
#end
However, I can remove the line
[windowWillResize setDelegate:self];
since I set the delegate in Interface Builder, but I'm not sure why this works.
How does windowWillResize know that I'm referring to the main application window since I'm doing a completely new
windowWillResize = [[NSWindow alloc] init];
I have a feeling that I am completely doing this wrong. Could someone point me in the right direction? Thanks!
Indeed, you don't need to create a NSWindow *windowWilResize since a newly created Cocoa app already has a main window. You don't need to implement an -init method either.
You only need to set you appController as a delegate of your main window in Interface Builder and to implement the -windowWillResize: method in your appController.
If you are familiar with french language, you can take a look at a blog entry I have written on this subject: Délégation en Cocoa.
You're leaking an instance of NSWindow. In -init you create an NSWindow instance. However, that is not used because when the NIB loads, it sets up all the connections that you specified in Interface Builder and you start using the window from the NIB instead. Do not create a window object in code - Interface Builder does it for you! :-)
In fact, it's not quite "instead"; your app controller is now the delegate for both NSWindow instances - the one that comes from the NIB and the one you instantiated in -init. However as the in-code NSWindow is never used anywhere else, it's still redundant and should be removed.
If you just want to maintain the aspect ratio of the window you can use either of these two NSWindow methods:
setAspectRatio:(NSSize)
setContentAspectRatio:(NSSize)
The first method locks the entire window size, including the title bar. The second one just the content. You can call this method during the initialization of your window inside the delegate (for example: -applicationDidFinishLaunching)