用于创建NSTextField"标签"的示例代码?

Tod*_*orf 51 macos user-interface cocoa objective-c

在我的桌面Mac OS X应用程序中,我想以编程方式创建一个NSTextField"标签",它具有与在Interface Builder中创建的典型标签相同的行为和属性.

我通常使用(并且非常喜欢)IB,但在这种情况下,它必须以编程方式完成.

尽我所能,我似乎无法找到方法调用的组合,这些方法调用将以编程方式生成与从IB视图库调色板拖动的"标签"相同的标签行为.

任何人都可以提供或指出一些如何以编程方式执行此操作的示例代码吗?谢谢.

Thi*_*tte 115

标签实际上是NSTextField的实例,它是NSView的子类.因此,由于它是NSView,因此必须将其添加到另一个视图中.

这是一个有效的代码:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSTextField *textField;

    textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 200, 17)];
    [textField setStringValue:@"My Label"];
    [textField setBezeled:NO];
    [textField setDrawsBackground:NO];
    [textField setEditable:NO];
    [textField setSelectable:NO];
    [view addSubview:textField];
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我确实在寻找更多的基本信息。这不会产生IB中出现的“标签y”行为。 (2认同)
  • 我看到的唯一缺少的是字体错误.如果您正在完全创建文本字段并想使用默认系统字体:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:[[textField cell] controlSize]]] (2认同)

rob*_*off 20

macOS 10.12及更高版本

从macOS 10.12(Sierra)开始,有三个新的NSTextField构造函数:

  • NSTextField(labelWithString:),头文件注释显示"创建一个非包装,不可编辑,不可选择的文本字段,以默认系统字体显示文本."

  • NSTextField(wrappingLabelWithString:),头文件注释显示"创建一个包装,不可编辑,可选择的文本字段,以默认系统字体显示文本."

  • NSTextField(labelWithAttributedString:),头文件注释显示"创建一个不可编辑的,不可选择的文本字段,显示属性文本.此字段的换行模式由属性字符串的NSParagraphStyle属性决定."

我测试了那些采用普通(非属性字符串)的文本字段,它们创建的文本字段与在storyboard或xib中创建的文本字段类似,但不完全相同.

重要的区别在于两个构造函数都创建了一个文本字段textBackgroundColor(通常为纯白色)作为其背景颜色,而故事板文本字段使用controlColor(通常约为90%白色).

不重要的是,两个构造函数也通过调用设置了它们的字体NSFont.systemFont(ofSize: 0)(它产生的NSFont代码与我下面的代码不同,但是它们包含相同的底层Core Text字体).

wrappingLabelWithString:构造函数设置字段的isSelectabletrue.(这在头文件中有记录.)


macOS 10.11和更早版本

我比较了四个NSTextField实例:一个是通过将"Label"拖动到一个故事板创建的,另一个是通过将"Wrapping Label"拖动到一个storyboard创建的,另一个是代码.然后我仔细修改了代码创建标签的属性,直到它们的所有属性与storyboard创建的标签完全相同.这两种方法的结果是:

extension NSTextField {

    /// Return an `NSTextField` configured exactly like one created by dragging a “Label” into a storyboard.
    class func newLabel() -> NSTextField {
        let label = NSTextField()
        label.isEditable = false
        label.isSelectable = false
        label.textColor = .labelColor
        label.backgroundColor = .controlColor
        label.drawsBackground = false
        label.isBezeled = false
        label.alignment = .natural
        label.font = NSFont.systemFont(ofSize: NSFont.systemFontSize(for: label.controlSize))
        label.lineBreakMode = .byClipping
        label.cell?.isScrollable = true
        label.cell?.wraps = false
        return label
    }

    /// Return an `NSTextField` configured exactly like one created by dragging a “Wrapping Label” into a storyboard.
    class func newWrappingLabel() -> NSTextField {
        let label = newLabel()
        label.lineBreakMode = .byWordWrapping
        label.cell?.isScrollable = false
        label.cell?.wraps = true
        return label
    }

}
Run Code Online (Sandbox Code Playgroud)

如果您使用这些方法之一,请不要忘记设置字段的框架,或关闭它translatesAutoresizingMaskIntoConstraints并添加约束.


这是我用来比较不同文本字段的代码,以防您要检查:

import Cocoa

class ViewController: NSViewController {

    @IBOutlet var label: NSTextField!
    @IBOutlet var multilineLabel: NSTextField!

    override func loadView() {
        super.loadView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let codeLabel = NSTextField.newLabel()
        let codeMultilineLabel = NSTextField.newWrappingLabel()

        let labels = [label!, codeLabel, multilineLabel!, codeMultilineLabel]

        for keyPath in [
            "editable",
            "selectable",
            "allowsEditingTextAttributes",
            "importsGraphics",
            "textColor",
            "preferredMaxLayoutWidth",
            "backgroundColor",
            "drawsBackground",
            "bezeled",
            "bezelStyle",
            "bordered",
            "enabled",
            "alignment",
            "font",
            "lineBreakMode",
            "usesSingleLineMode",
            "formatter",
            "baseWritingDirection",
            "allowsExpansionToolTips",
            "controlSize",
            "highlighted",
            "continuous",
            "cell.opaque",
            "cell.controlTint",
            "cell.backgroundStyle",
            "cell.interiorBackgroundStyle",
            "cell.scrollable",
            "cell.truncatesLastVisibleLine",
            "cell.wraps",
            "cell.userInterfaceLayoutDirection"
        ] {
            Swift.print(keyPath + " " + labels.map({ ($0.value(forKeyPath: keyPath) as? NSObject)?.description ?? "nil" }).joined(separator: " "))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 彻底的工作!感谢您度过了难关。 (2认同)

dan*_*ass 8

为了做到这一点,这可能很棘手.我没有精确复制品的配方,但是当我遇到类似的情况时,我就是这样做的:

  1. 在IB中创建UI元素.
  2. 从我的控制器类添加一个插座.
  3. 在awakeFromNib或其他什么中断gdb.
  4. 从gdb提示符"p*whateverOutlet"...这将显示IB设置的标签NSTextField的C结构内容.

通过查看那里的所有无数值,你可以得到很多关于你忽略设置的猜测.通常它最终会成为边框和边框设置的神奇组合,可以让您获得想要的位置.


小智 5

您可以尝试使用nib2objc来获取IB设置的所有属性