it-swarm.dev

NSTextField "etiket" oluşturmak için örnek kod?

Masaüstümde Mac OS X uygulamasında, programlı olarak, Arayüz Oluşturucu'da oluşturulan tipik bir etiketle aynı davranış ve özelliklere sahip olan bir NSTextField "etiketi" oluşturmak istiyorum.

Genellikle IB kullanırım (ve buna çok benzer), fakat bu durumda yapılması gerekir programlı olarak yapılır.

Olabildiğince deneyin, IB View Library paletinden sürüklenen bir "Label" ile aynı etiket-y davranışını programlı olarak üretecek yöntem çağrılarının birleşimini bulamıyorum.

Herhangi biri bunun programlı olarak nasıl yapılacağına dair bazı örnek kodlar verebilir veya işaret edebilir mi? Teşekkürler.

49

Bir etiket aslında bir NSView alt sınıfı olan NSTextField 'nin bir örneğidir. Bu yüzden, bir NSView olduğu için başka bir görünüme eklenmelidir.

İşte çalışan bir kod:

- (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];
}

macOS 10.12 ve Sonra

macOS 10.12 ile başlayan (Sierra), üç yeni NSTextField yapıcısı var:

  • Üstbilgi dosyası yorumunda bulunan NSTextField(labelWithString:), "Varsayılan sistem fontunda metin görüntüleyen, kaydırılamayan, düzenlenemez, seçilemeyen bir metin alanı oluşturur." 

  • Üstbilgi dosyası yorumunda bulunan NSTextField(wrappingLabelWithString:), "Varsayılan sistem fontunda metni görüntüleyen kaydırma, düzenlenebilir, seçilebilir bir metin alanı oluşturur."

  • Başlık dosyası yorumunda “NSTextField(labelWithAttributedString:)”, “Nitelikli metni görüntüleyen düzenlenebilir, seçilemeyen bir metin alanı oluşturur. Bu alanın satır sonu modu, atfedilen dizenin NSParagraphStyle niteliği ile belirlenir. ”

Düz (atlı olmayan bir dize) alanları test ettim ve onlar bir storyboard veya xib'de oluşturulan metin alanlarına benzeyen ancak tam olarak aynı olmayan metin alanları oluşturdular.

Önemli olan fark, her iki yapıcının da arka plan rengi olarak textBackgroundColor (normalde saf beyaz) bir metin alanı oluştururken, storyboard metin alanı controlColor (normalde yaklaşık% 90 beyaz) kullanır.

Önemsiz bir şekilde, her iki yapıcı da fontlarını NSFont.systemFont(ofSize: 0) (aşağıdaki kodumdan farklı bir NSFont nesnesi üretir, ancak aynı temel Çekirdek Yazı tipini sarar) arayarak ayarlarlar.

wrappingLabelWithString: yapıcısı alanın isSelectable öğesini true olarak ayarlar. (Bu başlık dosyasında belgelenmiştir.)


macOS 10.11 ve Önceki

Dört NSTextField örneğini karşılaştırdım: biri “Label” ı bir storyboard'a sürükleyerek yarattı, diğeri “Sarma Etiketi” ni bir storyboard'a sürükleyerek yarattı, ikisi kodda. Sonra kodun oluşturduğu etiketlerin özelliklerini, tüm özellikleri film şeridi tarafından oluşturulan etiketlerle tamamen aynı olana kadar dikkatlice değiştirdim. Bu iki yöntem sonuçtur:

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
    }

}

Bu yöntemlerden birini kullanıyorsanız, alanınızın çerçevesini ayarlamayı veya translatesAutoresizingMaskIntoConstraints özelliğini kapatıp sınırlamalar eklemeyi unutmayın.


Kontrol etmek istemeniz durumunda, farklı metin alanlarını karşılaştırmak için kullandığım kod:

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: " "))
        }
    }
}
17
rob mayoff

Bu doğru yapmak için zor olabilir. Kullanışlı bir çoğaltma tarifi kullanmıyorum, ancak benzer bir durumda sıkıştığımda, yaptığım şey şu:

  1. IB'de bir UI öğesi oluşturun.
  2. Denetleyici sınıfımdan bir çıkış ekleyin.
  3. Uyanıklıktan gdb'ye ya da her neyse kırın.
  4. Gdb İstemi'nden "p * whateverOutlet" ... bu size IB'nin kurduğu NSTextField etiketinin C yapı içeriğini gösterecektir.

Buradaki sayısız değere bakarak, neyi ihmal ettiğinizle ilgili birçok tahminde bulunabilirsiniz. Genellikle istediğiniz yere götüren, çerçeve ve kenarlık ayarlarının sihirli bir birleşimi olur.

8
danielpunkass

IB'nin ayarladığı tüm özellikleri elde etmek için nib2objc kullanarak deneyebilirsiniz

5
g-Off

Özellikle, setBordered:NO işlevini kullanmak isteyip, çerçeve stilini unuttuğum çerçeve stilini ayarlamak isteyeceksiniz. Ayrıca setEditable:NO ve isteğe bağlı olarak setSelectable:NO. Bu yeterli olmalı.

2
Steven Degutis

Amaç-C'deki Demonte Uygulama Takımı:

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
0
Vadim