objective-c 创建 NSTextField“标签”的示例代码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1507644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sample code for creating a NSTextField "label"?
提问by Todd Ditchendorf
In my desktop Mac OS X app, I'd like to programatically create a NSTextField "label" which has the same behavior and properties as a typical label created in Interface Builder.
在我的桌面 Mac OS X 应用程序中,我想以编程方式创建一个 NSTextField “标签”,它与在 Interface Builder 中创建的典型标签具有相同的行为和属性。
I usually use (and very much like) IB, but in this case it mustbe done programatically.
我通常使用(并且非常喜欢)IB,但在这种情况下,它必须以编程方式完成。
Try as I might, I can't seem to find the combination of method calls that will programatically produce the same label-y behavior as a "Label" dragged from the IB View Library palette.
尽我所能,我似乎找不到方法调用的组合,这些方法调用将以编程方式产生与从 IB 视图库调色板拖动的“标签”相同的标签行为。
Can anyone provide or point out some example code of how to do this programatically? Thx.
谁能提供或指出一些如何以编程方式执行此操作的示例代码?谢谢。
回答by Thibault Martin-Lagardette
A label is actually an instance of NSTextField, a subclass of NSView. So, since it is a NSView, it has to be added to another view.
标签实际上是NSTextField 的一个实例,它是 NSView 的子类。因此,由于它是一个 NSView,因此必须将其添加到另一个视图中。
Here's a working code:
这是一个工作代码:
- (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];
}
回答by rob mayoff
macOS 10.12 and Later
macOS 10.12 及更高版本
Starting with macOS 10.12(Sierra), there are three new NSTextFieldconstructors:
从 macOS 10.12(Sierra) 开始,新增了三个NSTextField构造函数:
NSTextField(labelWithString:), which the header file comment says “Creates a non-wrapping, non-editable, non-selectable text field that displays text in the default system font.”NSTextField(wrappingLabelWithString:), which the header file comment says “Creates a wrapping, non-editable, selectable text field that displays text in the default system font.”NSTextField(labelWithAttributedString:), which the header file comment says “Creates a non-editable, non-selectable text field that displays attributed text. The line break mode of this field is determined by the attributed string's NSParagraphStyle attribute.”
NSTextField(labelWithString:),其中头文件注释说“创建一个非换行、不可编辑、不可选择的文本字段,以默认系统字体显示文本。”NSTextField(wrappingLabelWithString:),其中头文件注释说“创建一个环绕的、不可编辑的、可选择的文本字段,以默认系统字体显示文本。”NSTextField(labelWithAttributedString:),其中头文件注释说“创建一个不可编辑、不可选择的文本字段,显示属性文本。此字段的换行模式由属性字符串的 NSParagraphStyle 属性决定。”
I tested the ones that take a plain (non-attributed string), and they create text fields that are similar to, but not precisely the same as, the text fields created in a storyboard or xib.
我测试了那些采用普通(非属性字符串)的文本字段,它们创建的文本字段与故事板或 xib 中创建的文本字段相似,但不完全相同。
The important difference is that both constructors create a text field with textBackgroundColor(normally pure white) as its background color, while the storyboard text field uses controlColor(normally about 90% white).
重要的区别在于,两个构造函数都创建了一个文本字段textBackgroundColor(通常为纯白色)作为其背景色,而故事板文本字段使用controlColor(通常为 90% 左右的白色)。
Unimportantly, both constructors also set their fonts by calling NSFont.systemFont(ofSize: 0)(which produces a different NSFontobject than my code below, but they wrap the same underlying Core Text font).
不重要的是,两个构造函数也通过调用来设置它们的字体NSFont.systemFont(ofSize: 0)(这会产生NSFont与我下面的代码不同的对象,但它们包装了相同的底层 Core Text 字体)。
The wrappingLabelWithString:constructor sets the field's isSelectableto true. (This is documented in the header file.)
该wrappingLabelWithString:构造函数设置字段的isSelectable到true。(这记录在头文件中。)
macOS 10.11 and Earlier
macOS 10.11 及更早版本
I compared four NSTextFieldinstances: one created by dragging a “Label”?to a storyboard, another created by dragging a “Wrapping Label” to a storyboard, and two in code. Then I carefully modified properties of the code-created labels until all their properties were exactly the same as the storyboard-created labels. These two methods are the result:
我比较了四个NSTextField实例:一个是通过将“标签”拖到故事板创建的,另一个是通过将“包装标签”拖到故事板创建的,还有两个是在代码中创建的。然后我仔细修改了代码创建的标签的属性,直到它们的所有属性都与故事板创建的标签完全相同。这两种方法的结果是:
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
}
}
If you use one of these methods, don't forget to set your field's frame, or turn off its translatesAutoresizingMaskIntoConstraintsand add constraints.
如果您使用这些方法之一,请不要忘记设置您的字段的框架,或关闭它translatesAutoresizingMaskIntoConstraints并添加约束。
Here is the code I used to compare the different text fields, in case you want to check:
这是我用来比较不同文本字段的代码,以防您要检查:
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({ (BOOL TMPSierraOrLater() {
static BOOL result = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
result = [NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 10, 12, 0 }];
});
return result;
}
@implementation NSTextField (TMP)
+ (instancetype)TMP_labelWithString:(NSString *)stringValue {
if (TMPSierraOrLater()) {
return [self labelWithString:stringValue];
}
NSParameterAssert(stringValue);
NSTextField *label = [NSTextField TMP_newBaseLabelWithoutTitle];
label.lineBreakMode = NSLineBreakByClipping;
label.selectable = NO;
[label setContentHuggingPriority:(NSLayoutPriorityDefaultLow + 1) forOrientation:NSLayoutConstraintOrientationHorizontal];
[label setContentHuggingPriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationVertical];
[label setContentCompressionResistancePriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationHorizontal];
[label setContentCompressionResistancePriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationVertical];
label.stringValue = stringValue;
[label sizeToFit];
return label;
}
+ (instancetype)TMP_wrappingLabelWithString:(NSString *)stringValue {
if (TMPSierraOrLater()) {
return [self wrappingLabelWithString:stringValue];
}
NSParameterAssert(stringValue);
NSTextField *label = [NSTextField TMP_newBaseLabelWithoutTitle];
label.lineBreakMode = NSLineBreakByWordWrapping;
label.selectable = YES;
[label setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal];
[label setContentHuggingPriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationVertical];
[label setContentCompressionResistancePriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal];
[label setContentCompressionResistancePriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationVertical];
label.stringValue = stringValue;
label.preferredMaxLayoutWidth = 0;
[label sizeToFit];
return label;
}
+ (instancetype)TMP_labelWithAttributedString:(NSAttributedString *)attributedStringValue {
if (CRKSierraOrLater()) {
return [self labelWithAttributedString:attributedStringValue];
}
NSParameterAssert(attributedStringValue);
NSTextField *label = [NSTextField TMP_newBaseLabelWithoutTitle];
[label setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal];
[label setContentHuggingPriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationVertical];
[label setContentCompressionResistancePriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal];
[label setContentCompressionResistancePriority:NSLayoutPriorityDefaultHigh forOrientation:NSLayoutConstraintOrientationVertical];
label.attributedStringValue = attributedStringValue;
[label sizeToFit];
return label;
}
#pragma mark - Private API
+ (instancetype)TMP_newBaseLabelWithoutTitle {
NSTextField *label = [[self alloc] initWithFrame:CGRectZero];
label.textColor = NSColor.labelColor;
label.font = [NSFont systemFontOfSize:0.0];
label.alignment = NSTextAlignmentNatural;
label.baseWritingDirection = NSWritingDirectionNatural;
label.userInterfaceLayoutDirection = NSApp.userInterfaceLayoutDirection;
label.enabled = YES;
label.bezeled = NO;
label.bordered = NO;
label.drawsBackground = NO;
label.continuous = NO;
label.editable = NO;
return label;
}
@end
.value(forKeyPath: keyPath) as? NSObject)?.description ?? "nil" }).joined(separator: " "))
}
}
}
回答by danielpunkass
This can be tricky to get right. I don't have the recipe for an exact replica handy, but when I've been stuck in a similar situation, here's what I do:
这可能很难做到正确。我手边没有精确复制品的配方,但是当我遇到类似情况时,我会这样做:
- Create a UI element in IB.
- Add an outlet to it from my controller class.
- Break in gdb in awakeFromNib or whatever.
- From the gdb prompt, "p *whateverOutlet" ... this will show you the C struct contents of the label NSTextField that IB set up.
- 在 IB 中创建一个 UI 元素。
- 从我的控制器类向它添加一个插座。
- 在awakeFromNib 或其他方法中中断gdb。
- 在 gdb 提示符下,“p *whateverOutlet”...这将显示 IB 设置的标签 NSTextField 的 C 结构内容。
By looking at all the myriad values in there, you can get a lot of guesses about what you're neglecting to set. Usually it ends up being some magic combination of bezel and border settings, that gets you where you want to be.
通过查看那里的所有无数值,您可以对忽略设置的内容进行很多猜测。通常它最终会成为边框和边框设置的一些神奇组合,让您到达您想要的位置。
回答by g-Off
回答by Steven Degutis
Specifically, you will want to setBordered:NO, and set the bezel style to whatever that bezel style is which I forgot. Also setEditable:NO, and optionally setSelectable:NO. That should suffice.
具体来说,您需要setBordered:NO将边框样式设置为我忘记的边框样式。此外setEditable:NO,和可选setSelectable:NO。那应该就足够了。
回答by Vadim
Disassembled AppKit in Objective-C:
Objective-C 中的反汇编 AppKit:
##代码##
