Complete title NSButton

Any way to have an NSButton title to wrap when the width is longer than the width of the button, instead of cropping?

I am trying to create a radio button with text that can be long and have multiple lines. One of the ways I thought this worked is with an NSButton of type NSRadioButton, but cannot use multiple lines of text.

Maybe my best alternative is for the NSButton to be followed by an NSTextView with the mouseDown delegation function on it, causing NSButton state?

+8
objective-c cocoa macos
source share
7 answers

I do not believe that you can. To add support, you need a subclass of NSButtonCell .

However, it is usually a bad idea to have multiple lines of text on a button. The button shortcut should briefly represent the completed action:

On the label on the button there should be a phrase of a verb or verb that describes the action that it performs: saving, closing, printing, deleting, changing a password, etc. If the button acts on one setting, name it as specific as possible; For example, "Select Image ..." is more useful than "Select ..." Because the buttons trigger an immediate action, it is not necessary to use "now" (for example, "Scan Now").

What are you trying to do?

+7
source share

I'm incredibly late, but I still feel obligated to share what I found.

Just add a newline before and after the button name before assigning it to the actual button - and voilà! Now it automatically wraps itself.

The disadvantage of this approach is that, for reasons unknown to me, applications compiled on a specific version of the OS X toggle button pound one line down when launched in newer versions.

+5
source share

Well, here is my excuse for multiline buttons: I am writing an emulator for the IBM 701, complete with a front panel, and, blessing their hearts, the designers of this front panel used multi-line labels. Here is my code. You only need to subclass NSButtonCell (and not NSButton), and only one method needs to be overridden.

 // In Xcode 4.6 (don't know about earlier versions): Place NSButton, then double-click it // and change class NSButtonCell to ButtonMultiLineCell. @interface ButtonMultiLineCell : NSButtonCell @end @implementation ButtonMultiLineCell - (NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView { NSAttributedString *as = [[NSAttributedString alloc] initWithString:[title.string stringByReplacingOccurrencesOfString:@" " withString:@"\n"]]; NSFont *sysFont = [NSFont systemFontOfSize:10]; NSMutableParagraphStyle *paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; [paragraphStyle setAlignment:NSCenterTextAlignment]; NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: sysFont, NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil]; NSSize textSize = [as.string sizeWithAttributes:attributes]; NSRect textBounds = NSMakeRect(0, 0, textSize.width, textSize.height); // using frame argument seems to produce text in wrong place NSRect f = NSMakeRect(0, (controlView.frame.size.height - textSize.height) / 2, controlView.frame.size.width, textSize.height); [as.string drawInRect:f withAttributes:attributes]; return textBounds; // not sure what rectangle to return or what is done with it } @end 
+4
source share

Later, but I also feel obligated to share. You can set the attributedTitle NSButton property for manual migration.

In my case, I wanted the button title to turn around if it was more than 6 characters (Swift 3):

 if button.title.characters.count > 6 { var wrappedTitle = button.title wrappedTitle.insert("\n", at: wrappedTitle.index(wrappedTitle.startIndex, offsetBy: 6)) let style = NSMutableParagraphStyle() style.alignment = .center let attributes = [NSFontAttributeName: NSFont.systemFont(ofSize: 19), NSParagraphStyleAttributeName: style] as [String : Any] button.attributedTitle = NSAttributedString(string: wrappedTitle, attributes: attributes) } 
+2
source share

I'm with Soren; If you need a more detailed description, consider using a tool tip or placing descriptive text in a wrapped text box using a small system font below the radio selection if the descriptive text is just a few lines. Otherwise, you could provide additional information in the background document.

Figuring out a way to say what you need to say in a concise way is the best choice.

+1
source share

Today I see that this can be done simply using the property in the NSButton cell:

myButton.cell?.wraps = true

+1
source share

I had the same problem, and with bated breath I tried to find solutions in this post. (Although I appreciate the advice that button titles should usually be short, I am writing a game and want multi-line responses to behave like buttons).

Sometimes you don’t get from here. My ideal was an NSButton with a multi-line shortcut, but since I can't get it without much trouble, I created PseudoButton: a subclass of NSControl that behaves like a button. It has a hand cursor indicating “you can click here,” and it gives feedback: when you click the mouse, it changes to selectedControlColor, when you release the mouse, it returns to normal. And unlike solutions that use stacks of buttons and labels, there are no problems placing labels and images at the top of the view: the entire view is an interactive area.

 import Cocoa @IBDesignable class PseudoButton: NSControl { @IBInspectable var backgroundColor: NSColor = NSColor.white{ didSet{ self.needsDisplay = true } } override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) let path = NSBezierPath(rect: dirtyRect) backgroundColor.setFill() path.fill() NSColor.black.setStroke() path.lineWidth = 2 path.stroke() } override func mouseDown(with event: NSEvent) { self.backgroundColor = NSColor.selectedControlColor } override func mouseUp(with event: NSEvent) { self.backgroundColor = NSColor.clear guard let action = action else {return} tryToPerform(action, with: self) //@IBAction func pseudobuttonClicked(_ sender: PseudoButton) in the ViewController class } override func resetCursorRects() { addCursorRect(bounds, cursor: .pointingHand) } } 

You use this, like any other control in a storyboard: drag the pseudo-button inward, decorate it as you wish, and connect it to the corresponding IBAction in your viewController class.

I like it better than interfering with NSCell. (According to past experience, NSCell-based hacks break more often).

0
source share

All Articles