2010-10-12 14 views
6

के लिए एक वर्कअराउंड की आवश्यकता है मैं एक जॉग डायल नामक नियंत्रण बनाने के लिए एनएसएसएलडर को उपclass करने की कोशिश कर रहा हूं। असल में मुझे जो स्लाइडर चाहिए वह एक स्लाइडर है जो हमेशा मध्य में शुरू होता है और जब इसे बाएं या दाएं स्थानांतरित किया जाता है तो यह हर बार अधिसूचनाएं भेजता है (एक विशेषता द्वारा निर्धारित किया जा सकता है) अपने वर्तमान मूल्य के कंटेनर को सूचित करता है, फिर जब आप आपको घुंडी से जाने दो, यह बीच में वापस आ जाएगा। मैं स्लाइडर को बीच में वापस करने के लिए कार्यक्षमता को कार्यान्वित करने की उम्मीद कर रहा था और स्लाइडर के माउसअप ईवेंट में अधिसूचनाएं भेजना बंद कर रहा था, लेकिन ऐसा लगता है कि किसी कारण से सेब स्लाइडर पर माउसडाउन ईवेंट के बाद माउसअप ईवेंट को अक्षम करता है और सभी स्लाइडर कार्यक्षमता को संभालता है निचले स्तर पर। क्या वैसे भी मैं माउसअप घटना वापस प्राप्त कर सकता हूं? यदि कोई उचित कार्यवाही का सुझाव नहीं दे सकता है?उप-वर्गीकरण एनएसएसएलडर: गायब माउस अप घटनाओं (कोको ओएसएक्स)

उत्तर

5

जब भी आप देखते हैं कि mouseDragged: या mouseUp: की एक सुपर क्लास के कार्यान्वयन नहीं बुलाया जा रहा है, यह mouseDown: के वर्ग के कार्यान्वयन एक ट्रैकिंग पाश में प्रवेश क्योंकि सबसे अधिक संभावना है। NSSlider समेत कई NSControl उप-वर्गों में यह निश्चित रूप से सच है।

माउस का पता लगाने का एक बेहतर तरीका सेल को उप-वर्ग करना और उचित ट्रैकिंग विधि को ओवरराइड करना है। इस मामले में, आप शायद - (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag चाहते हैं, लेकिन startTracking: और continueTracking: वेरिएंट भी उपयोगी साबित हो सकते हैं जो आप करने की कोशिश कर रहे हैं।

6

ऐसी परिस्थितियों के लिए एक चाल है जिसका उपयोग मैंने किया (लेकिन आविष्कार नहीं किया)। सबसे पहले, आईबी में, स्लाइडर को "निरंतर" के रूप में नामित करें, ताकि आपको स्लाइडर स्थानांतरित होने के कारण एक्शन संदेश मिल जाए। फिर, कार्रवाई विधि में, ऐसा करते हैं:

[NSObject cancelPreviousPerformRequestsWithTarget: self 
    selector: @selector(finishTrack) object: nil ]; 
[self performSelector: @selector(finishTrack) withObject: nil 
    afterDelay: 0.0]; 

बाद माउस जारी की है, finishTrack विधि बुलाया जाएगा।

3

ऐसा लगता है कि केपरियाआ का विचार सबसे साफ समाधान प्रदान करेगा, इसलिए मैं इसे स्वीकार किए गए उत्तर के रूप में चिह्नित करूंगा, लेकिन मैंने अपनी विशिष्ट स्थिति के लिए काम करने वाले एक हैक का उपयोग करना समाप्त कर दिया, इसलिए मैंने सोचा कि मैं इसे भी साझा कर सकता हूं।

जो ऐप मैं बना रहा हूं वह क्रॉस प्लेटफ़ॉर्म होने की आवश्यकता है, इसलिए मैं इस लक्ष्य को प्राप्त करने के लिए कोकोट्रॉन (एक ओपन सोर्स प्रोजेक्ट जो विंडोज़ कोको एपीआई लागू करता है) का उपयोग कर रहा हूं और कोकोट्रॉन स्टॉपट्रैकिंग का समर्थन नहीं करता है: ... ऊपर वर्णित विधि।

सौभाग्य से, एक छोटे परीक्षण कार्यक्रम के साथ खेलते समय हमने यह पाया कि यदि आप NSSlider के माउसडाउन विधि को ओवरराइड करते हैं और उस विधि के सुपर को कॉल करते हैं, तो माउस बटन जारी होने तक यह वापस नहीं आता है, इसलिए आप सुपर में कॉल के बाद माउसडाउन विधि के अंदर माउस में जो भी कोड होना चाहिए उसे बस रख सकते हैं। यह एक गंदे हैक का थोड़ा सा है, लेकिन ऐसा लगता है कि यह एकमात्र समाधान है जो हमारे मामले में काम करेगा, इसलिए हमें इसके साथ जाना होगा।

6

यह मेरे लिए काम करता है (और NSSlider उपवर्गीकरण की तुलना में आसान है):

- (IBAction)sizeSliderValueChanged:(id)sender { 
    NSEvent *event = [[NSApplication sharedApplication] currentEvent]; 
    BOOL startingDrag = event.type == NSLeftMouseDown; 
    BOOL endingDrag = event.type == NSLeftMouseUp; 
    BOOL dragging = event.type == NSLeftMouseDragged; 

    NSAssert(startingDrag || endingDrag || dragging, @"unexpected event type caused slider change: %@", event); 

    if (startingDrag) { 
     NSLog(@"slider value started changing"); 
     // do whatever needs to be done when the slider starts changing 
    } 

    // do whatever needs to be done for "uncommitted" changes 
    NSLog(@"slider value: %f", [sender doubleValue]); 

    if (endingDrag) { 
     NSLog(@"slider value stopped changing"); 
     // do whatever needs to be done when the slider stops changing 
    } 
} 
+1

यह सभी मामलों में काम नहीं करता है (खींचने लगाना और मेनू पर जाने से पहले, आप कभी भी एंडिंग ड्रैग पंजीकृत नहीं करेंगे) –

0

यह उपवर्गीकरण द्वारा ही किया जा सकता है (@mprudhom से जैसे तरीकों पता रिहाई के लिए 100% काम नहीं करेगा)

खींचें की शुरुआत के लिए, आप becomeFirstResponder को पकड़ने के लिए की जरूरत है खींच के अंत के लिए

(इस के लिए आप भी needsPanelToBecomeKey प्रदान करने के लिए हो) तो आपको mouseDown: उपवर्ग के लिए (mousedown इसके बुलाया जरूरत है, लेकिन यह Calle हो जाता है घ जब घुंडी जारी)

नोट: इस दृष्टिकोण अपने स्लाइडर पहले प्रत्युत्तर, किसी अन्य वर्तमान प्रथम प्रत्युत्तर रद्द

नोट कर देगा: बस मामले में किसी को mprudhom

@implementation CustomSlider 

- (void)mouseDown:(NSEvent *)theEvent { 
    [super mouseDown:theEvent]; 
    NSLog(@"OK"); 
} 

- (BOOL)needsPanelToBecomeKey { 
    [super needsPanelToBecomeKey]; 
    return YES; 
} 

- (BOOL)becomeFirstResponder { 
    [super becomeFirstResponder]; 
    NSLog(@"Became first responder."); 
    return YES; 
} 

@end 
1

से दृष्टिकोण सोच रहा है कैसे एक NSSlider साथ स्विफ्ट 3 में इस लक्ष्य को हासिल करने के लिए thats राज्य निरंतर के लिए सेट है:

@IBOutlet weak var mySlider: NSSlider! 

... 

@IBAction func handlingNSSliderChanges(_ sender: Any) { 

    // Perform updates on certain events 
    if sender is NSSlider{ 
     let event = NSApplication.shared().currentEvent 

     if event?.type == NSEventType.leftMouseUp { 
      print("LeftMouseUp event inside continuous state NSSlider") 
     } 
    } 

    // Do continuous updates 
    if let value = mySlider?.integerValue{ 
     demoLabel.stringValue = String(value) 
    } 
} 

... 
0

मैं एक ऐसी ही जरूरत थी, लेकिन एक NSTouchBar पर एक स्लाइडर के लिए । मैंने मार्क प्रूडहोमॉक्स और मार्टिन माजवेस्की के समान "त्वरित और गंदे" दृष्टिकोण का उपयोग किया, निरीक्षण के लिए बस कुछ अलग घटनाएं। यहां स्विफ्ट कोड है जो आपको टचबार पर स्लाइडर के निरंतर मूल्य और अंतिम मान दोनों को ट्रैक करने की अनुमति देता है।

func sliderValueChanged(_ sender: NSSlider) { 
    let doubleValue = sender.doubleValue 

    Swift.print("Continuous value: \(doubleValue)") 

    // find out if touch event has ended 
    let event = NSApplication.shared().currentEvent 
    if event?.type == NSEventType.directTouch { 
     if let endedTouches = event?.touches(matching: .ended, in: nil) { 
      if (endedTouches.count > 0) { 
       Swift.print("The final value was: \(doubleValue)") 
      } 
     } 
    } 
} 
संबंधित मुद्दे