menubar set font width

Hello,


I have a menu bar element in OS X 10.11 next to the system time.

It's showing the number of seconds since one event, that the user had choosen.

For example the number:

5.230.185


The problem is, that the width of the String changes every second, because of the different width of the numbers 0 to 9.

5.230.181 is thinner than

5.230.188


I want to know how to fix the width of the numbers, that you cannot see this difference. The system time in the menu also don't have this problem.

My title is for example:

statusItem.title = "5.230.181"


Could someone help me?

Answered by DTS Engineer in 71294022

I have seen, that I can use statusItem.attributedTitle instead of statusItem.title.

Right.

But I don't know how to use it.

You’ll have to:

  1. create a font for the monospaced system font of your preferred size

  2. wrap your string in an attributed string that references that font

let font = NSFont.monospacedDigitSystemFontOfSize(12.0, weight: NSFontWeightRegular)
let attributedString = NSAttributedString(string: "foo", attributes: [NSFontAttributeName: font])

Again, I’ve not tried this for an NSStatusItem but I can’t see any reason why it wouldn’t work.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

The problem is, that the width of the String changes every second, because of the different width of the numbers 0 to 9.

Right. The new system font has proportional numbers, which is cool in general but problematic in situations like this.

btw This and other tibits were covered in WWDC 2015 Session 804 Introducing the New System Fonts, which is a really great presentation IMO.

Two things:

  • NSStatusTime has an

    attributedTitle
    property that you can use to set a title string with attributes.
  • You can use

    +[NSFont monospacedDigitSystemFontOfSize:weight:]
    to get a system font variant with monospaced digits.

I expect you’ll be able to combine these point to solve your problem, but I haven’t personally tried it.

Finally, as this is very much an AppKit issue, I’ve moved your thread over to App Frameworks > Cocoa.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello,


thank you very much for your answer.

My problem in this point is, that I'm using swift and never learnd something about objective-c (big mistake).

import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var dorTime: NSMenu!
    var timer = NSTimer()

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        let icon = NSImage(named: "dorunicorn")!
        icon.template = true
     
        statusItem.image = icon
        statusItem.menu = dorTime
        statusItem.length = NSVariableStatusItemLength
        timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: ("getDorTime"), userInfo: nil, repeats: true)
    }


    @IBAction func menuClicked(sender: NSMenuItem) {
        let pasteBoard = NSPasteboard.generalPasteboard()
        pasteBoard.clearContents()
        pasteBoard.writeObjects(NSArray(object: statusItem.title!) as! [NSPasteboardWriting])
    }

    @IBAction func quitClicked(sender: NSMenuItem) {
        exit(0)
    }

    func getDorTime() {
        let userCalendar = NSCalendar.currentCalendar()
        let napTimeComp = NSDateComponents()
        napTimeComp.timeZone = userCalendar.timeZone
        napTimeComp.year = 1821
        napTimeComp.month = 5
        napTimeComp.day = 6
        napTimeComp.hour = 3
        napTimeComp.minute = 14
        napTimeComp.second = 15
     
        let napTime = userCalendar.dateFromComponents(napTimeComp)!
        let dorTime = Int(NSDate().timeIntervalSinceDate(napTime))
        statusItem.title = String(dorTime.addSpaceSeparator)
    }

     extension Int {
         var addSpaceSeparator:String {
        let nf = NSNumberFormatter()
        nf.groupingSeparator = "."
        nf.numberStyle = NSNumberFormatterStyle.DecimalStyle
        return nf.stringFromNumber(self)!
    }
}

}


That is my code, that I'm using.


I want to show the number of seconds from one date (for my example on 6.may 1821, 3:14:15) to today.

As you can see in line 45, in this line, I will bringt the number to the status bar.

I have seen, that I can use statusItem.attributedTitle instead of statusItem.title.

But I don't know how to use it.


Would you please explain me the usage of this on my code? I want to learn it. 🙂


This would be very nice.


Best Regards

Lukas

Accepted Answer

I have seen, that I can use statusItem.attributedTitle instead of statusItem.title.

Right.

But I don't know how to use it.

You’ll have to:

  1. create a font for the monospaced system font of your preferred size

  2. wrap your string in an attributed string that references that font

let font = NSFont.monospacedDigitSystemFontOfSize(12.0, weight: NSFontWeightRegular)
let attributedString = NSAttributedString(string: "foo", attributes: [NSFontAttributeName: font])

Again, I’ve not tried this for an NSStatusItem but I can’t see any reason why it wouldn’t work.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello,

thank you very much. This code works. My project will be finished.

Have a nice day!

menubar set font width
 
 
Q