(macOS, Swift, storyboards)
Can I change a label on hover?
WHAT I HAVE TRIED
1- I have put a button in storyboard and make it transparent. It works if I click, but I could nof find how to if hover
@IBOutlet weak var label1: NSTextField!
@IBAction func button1(_ sender: NSButton) {
label1.textColor = NSColor.gray
}
2- I have put a NSView and drag a NSClickGestureRecognizer to it. Again, it works on click but I cannot find a way to do it with hover
@IBOutlet weak var label2: NSTextField!
@IBAction func gestureRecognizer1(_ sender: NSClickGestureRecognizer) {
label2.textColor = NSColor.gray
}
I could find something in Apple documentation. But it talks about UIButton. I cannot find a way to adapt to my case:
https://developer.apple.com/documentation/uikit/uihovergesturerecognizer
Please explain exactly what you did, eventually post the code.
- You created a new class definition in XCode, from File menu:
File > New > File
- Select MacOS and Cocoa class
- Subclass of NSTextField
- name LabelWithHelp
Is it how you proceeded ?
You should have got a new file with the following content
import Cocoa
class LabelClass: NSTextField {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
}
Now replace the content with the following (I have corrected a few errors)
import Cocoa
class LabelWithHelp: NSTextField {
var textForHover = "Some new text" // This will be changed as needed
var nonHoverText : String?
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here. If needed
}
// MARK: - Mouse Events
// --------------------- mouseEntered --------------------------------------------------------------
// Description: When hovering over label
// Parameters
// theEvent: NSEvent
// Comments :
// Need to have defined trackingArea
// -------------------------------------------------------------------------------------------------
override func mouseEntered(with theEvent: NSEvent) {
super.mouseEntered(with: theEvent)
nonHoverText = self.stringValue // Save the actual content
self.stringValue = textForHover // replace in label
}
// --------------------- mouseExited --------------------------------------------------------------
// Description: Exit from hover
// Parameters
// theEvent: NSEvent
// Comments :
// -------------------------------------------------------------------------------------------------
override func mouseExited(with theEvent: NSEvent) {
super.mouseExited(with: theEvent)
self.stringValue = nonHoverText ?? "" // replace with original text
}
}
In the view, in IB, create a label
Change its type to LabelWithHelp
In the ViewController where the label is:
- declare an IBOutlet for the label and a tracking area
@IBOutlet weak var label: LabelWithHelp!
fileprivate var labelTrackingArea : NSTrackingArea?
Connect the IBOutlet to the label in IB
- in viewDidload, set the tracking area:
labelTrackingArea = NSTrackingArea(rect: label.bounds, options: [NSTrackingArea.Options.mouseEnteredAndExited, NSTrackingArea.Options.cursorUpdate, NSTrackingArea.Options.activeInKeyWindow], owner: label, userInfo: nil)
label.addTrackingArea(labelTrackingArea!)
Run
You should see the label change when you hover on it and return to its value when exiting.