NSColorPanel blocking mouse up events

吃可爱长大的小学妹 提交于 2020-01-23 11:21:41

问题


I am using a NSColorWell which is set to continuously update. I need to know when the user is done editing the control (mouse up) from the color picker in the color panel.

I installed an event monitor and am successfully receiving mouse down and mouse moved messages, however NSColorPanel appears to block mouse up.

The bottom line is that I want to add the final selected color to my undo stack without all the intermediate colors generated while the user is choosing their selection.

Is there a way of creating a custom NSColorPanel and replacing the shared panel with the thought of overriding its mouseUp and sending a message?

In my research this issue has been broached on a few occasions, however I have not read a successful resolution.

Regards, - George Lawrence Storm, Keencoyote Invention Services


回答1:


I discovered that if we observe color keypath of NSColorPanel we get called one extra time on mouse up events. This allows us to ignore action messages from NSColorWell when the left mouse button is down and to get the final color from keypath observer.

In this application delegate example code colorChanged: is a NSColorWell action method.

void* const ColorPanelColorContext = (void*)1001;

@interface AppDelegate()

@property (weak) NSColorWell *updatingColorWell;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
    NSColorPanel *colorPanel = [NSColorPanel sharedColorPanel];
    [colorPanel addObserver:self forKeyPath:@"color" 
                    options:0 context:ColorPanelColorContext];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
                        change:(NSDictionary *)change context:(void *)context {
    if (context == ColorPanelColorContext) {
        if (![self isLeftMouseButtonDown]) {
            if (self.updatingColorWell) {
                NSColorWell *colorWell = self.updatingColorWell;
                [colorWell sendAction:[colorWell action] to:[colorWell target]];
            }
            self.updatingColorWell = nil;
        }
    }
}

- (IBAction)colorChanged:(id)sender {
    if ([self isLeftMouseButtonDown]) {
        self.updatingColorWell = sender;
    } else {
        NSColorWell *colorWell = sender;
        [self updateFinalColor:[colorWell color]];
        self.updatingColorWell = nil;
    }
}

- (void)updateFinalColor:(NSColor*)color {
    // Do something with the final color...
}

- (BOOL)isLeftMouseButtonDown {
    return ([NSEvent pressedMouseButtons] & 1) == 1;
}

@end



回答2:


In the Interface Builder, select your color well, and then uncheck the Continuous checkbox in the Attributes Inspector. Additionally, add the following line of code somewhere appropriate like in the applicationDidFinishLaunching: method or awakeFromNib method:

[[NSColorPanel sharedColorPanel] setContinuous:NO];

In other words, both the shared color panel and your color well need to have continuous set to NO in order for this to work properly.




回答3:


The proper way to do what you want is to use NSUndoManager's -begin/endUndoGrouping. So you'd do something like this

[undoManager beginUndoGrouping];
// ... whatever code you need to show the color picker
// ...then when the color has been chosen
[undoManager endUndoGrouping];

The purpose of undo groups is exactly what you're trying to accomplish - to make all changes into a single undo.



来源:https://stackoverflow.com/questions/14138852/nscolorpanel-blocking-mouse-up-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!