Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

McBgnr

macrumors regular
Original poster
Apr 13, 2009
144
0
In my application I want to know if the user has clicked on NSButton and not released the mouse, that is the user clicks and holds mouse on NSButton. Is there a way to track this action of user and react accordingly?
 

garethlewis2

macrumors 6502
Dec 6, 2006
277
1
In all honesty, I don't think this is possible.

You connect a button to an action in Interface Builder. Even if you could record the fact that the button is being held, who would get the event? Not your application. NSApplication forwards all messages received in the message loop, so you would probably need to override a very low level method there in either the CFRunloop or NSRunloop.
 

McBgnr

macrumors regular
Original poster
Apr 13, 2009
144
0
Thanks for the reply.

Even I was thinking that it would not be easy to track the holding of mouse on a button because we get a single action.

How can I override the message loop? I am not sure... Any pointers wrt it are welcome.
 

Thomas Harte

macrumors 6502
Nov 30, 2005
400
4
I continue to be enthusiastic but inexperienced at Cocoa, but have you tried subclassing NSButton and supplying mouseUp, mouseDown and, if you're interested, mouseDragged methods as per the informal protocol defined by NSResponder?
 

McBgnr

macrumors regular
Original poster
Apr 13, 2009
144
0
I tried to debug the code little more and realised that although the buttonclick function was getting called only once the user has released the button after holding it for a long time. Thus, my problem could be due to some other reason.

The problem that I am facing is that I have a worker thread in my code and from the worker thread i am calling perfromselectoronmainthread for updating some UI elements. But when the button is held by the user it, the performselectoronmainthread does not update the UI. I am not sure why the UI thread is not updating the UI while the user has held the button.

I am using performselectormainthread with waitUntilDone flag set to TRUE.

Please suggest how this problem could be solved.
 

Krevnik

macrumors 601
Sep 8, 2003
4,100
1,309
Depends on how you define it as a problem. Is the problem that the UI doesn't update, or that the worker thread hangs while it waits for the main thread to unblock?

If the former, there isn't a whole lot you can do here.

If the latter, then the focus should be on not blocking the worker thread while the main thread is blocked. I'd personally do something like packaging the UI data as something that can be placed in a cross-thread data structure, adding it a queue object in the worker thread, and using the call into the main selector as an 'event'. You can even use a flag or some other check to make sure the selector being called multiple times doesn't actually try to perform work multiple times.
 

McBgnr

macrumors regular
Original poster
Apr 13, 2009
144
0
Thats gives another way to look at the problem.... yes it is indeed correct that I can take it as the worker thread is waiting for main thread to unblock.

I had earlier tried using performselectoronmainthread with waitUntilDone flag set to NO, but it did not update the UI at all. Thus I had shifted to waitUntilDone=YES. I had packaged my data in an object of myClass and was sending the object to the selector method as
Code:
myClass *obj = [[[myClass alloc] init] autorelease];
//initialize obj members here

//send obj to updateUserInterface method 
[self performSelectorOnMainThread:@selector (updateUserInterface) withObject:obj waitUntilDone:YES];


Which other APIs can I use for this purpose so that my worker thread would not block and my job would be done.Please suggest.


[EDIT] Another thing that I am concerned is that when the Button is being held in the Main Window, the worker thread is getting blocked. Does it main that for that duration the UI thread will not be able to update other components as well?
 

Krevnik

macrumors 601
Sep 8, 2003
4,100
1,309
No, it won't be able to update the UI on the main thread if something is blocking it from doing so. As that is functionality in AppKit, there isn't a whole lot you can do. I don't really know of many apps that can get away with updating while the mouse is down when written in Cocoa.

If you send an autoreleased object, you very well could wind up sending a nil/invalid object by the time the selector actually fires. I'd either use a different data structure (an array or something will probably work best) that lives in the class that will do the updating. Put your objects into that array, and only have the selector use the /latest/ or /last/ item in the array to update the UI when it fires. That way, you can simply empty/clear the array after one update and be done, no matter what causes the main thread to not run your selector for awhile.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
I think something else is going on in your code. I created a very simple demo project on 10.5 to test and I didn't see any delay when clicking and holding down on a button. The UI updates just fine. Here is the code I used (maybe I've oversimplified the situation?):

Code:
- (void)awakeFromNib {
    [NSThread detachNewThreadSelector:@selector(thread)
            toTarget:self withObject:nil];
}

- (void)thread {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSInteger i = 0;
    for (;;) {
        [self performSelectorOnMainThread:@selector(setNumber:)
                    withObject:[NSNumber numberWithInteger:i++]
                    waitUntilDone:YES];
        [NSThread sleepForTimeInterval:0.1];
    }

    [pool release];
}

- (void)setNumber:(NSNumber *)num {
    [textField setIntegerValue:[num integerValue]];
}
 

McBgnr

macrumors regular
Original poster
Apr 13, 2009
144
0
Yes even I think that something else is also going on in my code... because even I tried a simple program and it worked.

In my thread I am enumerating through the file system to get the file names of the contents of the dirs... but not sure why the thread is not updating the UI when the button is held.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.