I am trying to subclass NSSlider to create a control called a jog dial. Basically what I need is a slider which always starts at the middle and when it is moved to the left or right it will send notifications every so often (determined by an attribute one can set) informing its container of its current value, then when you let you go of the knob, it will return to the middle. I was hoping to implement the functionality to return the slider to the middle and stop sending notifications in the mouseUp event of the slider but it seems that for some reason apple disables the MouseUp event after a mouseDown event on the slider and handles all the slider functionality at a lower level. Is there anyway I can get the mouseUp event back? If not can anyone suggest a reasonable workaround?
相关问题
- Xcode debugger displays incorrect values for varia
- Is there a way to report errors in Apple documenta
- Advice for supporting both Mac and Windows Desktop
- Avoid cmake to add the flags -search_paths_first a
- NSOutlineView drag line stuck + blue border
相关文章
- 现在使用swift开发ios应用好还是swift?
- Visual Studio Code, MAC OS X, OmniSharp server is
- xcode 4 garbage collection removed?
- IntelliJ IDEA can't open projects or add SDK o
- Automator: How do I use the Choose from List actio
- ImportError: No module named twisted.persisted.sty
- How can I vertically align my status bar item text
- Converting (u)int64_t to NSNumbers
This can be done only by subclassing (methods like from @mprudhom won't work 100% for know release)
For the beginning of the drag, you need to catch
becomeFirstResponder
(for this you need to also provideneedsPanelToBecomeKey
)for the end of dragging, you need to subclass
mouseDown:
(its called mouseDown, but it gets called when knob released)Note: this approach will make your slider the first responder, canceling any other current first responder
Note: approach from mprudhom
I had a similar need, but for a slider on an NSTouchBar. I used a similar "quick-and dirty" approach as Marc Prud'hommeaux and Martin Majewski, just slightly different events to inspect. Here's the Swift code that allows you to track both the continuous value AND the final value of the slider on a touchbar.
It seems that Kperryua's idea would provide the cleanest solution so I will mark that as the accepted answer, but I ended using a bit of a hack that worked for my specific situation so I thought I might share that as well.
The app that I am making needs to be cross platform so I am using Cocotron (an open source project that implements much of the Cocoa API on Windows) to achieve this goal and cocotron does not support the stopTracking:... method mentioned above.
Luckily, while playing around with a little test program we made it was discovered that if you override the the mouseDown method of the NSSlider and call the super of that method, it does not return until the mouse button is released, so you can just put whatever code should be in mouseUp inside the mouseDown method after the call to super. This is a bit of a dirty hack but it seems to be the only solution that will work in our case so we are going to have to go with it.
Whenever you notice that a superclass's implementation of
mouseDragged:
ormouseUp:
is not getting called, it's most likely because the class's implementation ofmouseDown:
enters a tracking loop. This is certainly true of manyNSControl
subclasses includingNSSlider
.A better way to detect a mouse up is to subclass the cell and override the appropriate tracking method. In this case, you probably want
- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag
, but thestartTracking:
andcontinueTracking:
variants might prove useful as well for what you're trying to do.Just in case someone is wondering how to achieve this in Swift 3 with an NSSlider thats state is set to continuous:
There is a trick that I use (but didn't invent) for such situations. First, in IB, designate the slider as "continuous", so that you'll get action messages as the slider is moved. Then, in the action method, do this:
After the mouse is released, the
finishTrack
method will be called.