包裹NSButton标题

时间:2009-03-22 14:57:15

标签: objective-c cocoa macos

如果NSButton标题的宽度超过按钮宽度而不是被剪裁,那么是否有任何方法可以将其包裹起来?

我正在尝试使用一个文本可以很长且有多行的单选按钮。我认为让它工作的一种方法是使用NSRadioButton类型的NSButton,但不能使多行文本工作。

也许我最好的选择是让一个NSButton后跟一个NSTextView,并在其上触发NSButton状态的mouseDown委托函数?

8 个答案:

答案 0 :(得分:7)

我不相信你可以。您必须继承NSButtonCell以添加对此的支持。

也就是说,在按钮上放置多行文本通常是个坏主意。 A button label should concisely represent the action performed:

  

按钮上的标签应该是动词或动词短语,用于描述其执行的操作 - 保存,关闭,打印,删除,更改密码等。如果按钮作用于单个设置,请尽可能具体地标记按钮;例如,“选择图片......”比“选择...”更有用。因为按钮会立即启动操作,所以不必在标签中使用“现在”(例如立即扫描)。

你想做什么?

答案 1 :(得分:5)

我太迟了,但我仍然觉得有必要分享我发现的东西。

只需在按钮标题之前和之后添加换行符,然后再将其分配给实际按钮 - vo!它现在自动包裹。

这种方法的缺点是,由于我不知道的原因,在某个版本的OS X上编译的应用程序在新版本上运行时会将按钮标题向下移动一行。

答案 2 :(得分:4)

这里是我需要多行按钮的借口:我正在为IBM 701编写一个模拟器,配有前面板,并且,他们的心灵,前面板的设计者使用了多行标签。这是我的代码。您只需要子类化NSButtonCell(而不是NSButton),并且只需要覆盖一个方法。

// 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

答案 3 :(得分:2)

即使是晚些时候,我也觉得有必要分享。您可以设置NSButton的attributionTitle属性以实现手动换行。

在我的情况下,如果按钮标题大于6个字符(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)
}

答案 4 :(得分:1)

我和Sören在一起;如果您需要更长的描述,请考虑使用工具提示或使用收音机选项下方的小系统字体在描述文本字段中放置描述性文本(如果描述性文本只有几行)。否则,您可以在帮助文档中提供更多信息。

尽管如此,找出一种方法来简明扼要地说出你需要说的话是最好的选择。

答案 5 :(得分:1)

从今天开始,我看到可以使用NSButton单元格上的一个属性来简单地完成此操作:

myButton.cell?.wraps = true

答案 6 :(得分:0)

我遇到了同样的问题,并下定决心尝试解决本文中的解决方案。 (虽然我很欣赏建议,通常应该使按钮标题简短,但我正在编写游戏,并且希望多行答案的行为类似于按钮)。

有时候,您不是从这里到达那里的。我的理想选择是带有多行标签的NSButton,但是由于我没有那么麻烦就无法做到这一点,所以我创建了一个PseudoButton:一个行为类似于按钮的NSControl子类。它带有一个手形光标,指示“您可以单击此处”,并提供反馈:单击鼠标时,它将更改为selectedControlColor,释放鼠标时,它将恢复正常。与尝试堆叠按钮和标签的解决方案不同,在视图顶部放置标签和图像没有问题:整个视图都是可单击的区域。

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)
    }


}

您可以像在故事板上的任何其他控件一样使用此控件:将Pseudobutton拖入其中,随意装饰它,然后将其连接到viewController类中的相应IBAction。

我比加入NSCell更好。 (根据过去的经验,基于NSCell的黑客更有可能被破解)。

答案 7 :(得分:0)

这有点晚了,这是我的代码在标题中插入新行:

 public class MyAsyncTask extends AsyncTask<String,String,String>
    {
        @Override
        protected String doInBackground(String... params) {

            try {

                JedisPoolConfig config = new JedisPoolConfig();
                config.setMaxIdle(8);
                config.setMaxTotal(18);
                JedisPool pool = new JedisPool(config, "localhost", 6379, 2000);
                Jedis jedis = pool.getResource();
                jedis.set("m", "f");
                jedis.close();
                pool.close();
            }
            catch (Exception e){

            }

            return null;
        }
        @Override

        protected void onPostExecute(String s) {

        }
    }

只需将原始标题作为参数,它将返回多个行标题。