Reputation: 7066
Is it possible to strikethrough the text in a label (NSTextField
)?
I have tried to use the Font Panel, but apparently these are ignored when I try to set them:
Upvotes: 5
Views: 2298
Reputation: 469
I'd like to share an easier approach with more options and also point to a mistake in earlier answers.
Easy
To bypass the string length
, use initWithString:attributes:
to apply the attributes on the entire string.
Mistake
All the above examples set a boolean value (kCFBooleanTrue
) for NSStrikethroughStyleAttributeName
.
This is incorrect, since the data type of NSStrikethroughStyleAttributeName
is an integer of type NSUnderlineStyle
.
The reason why the above examples with kCFBooleanTrue
work, is that they cast this boolean to an NSNumber
, resulting in value 1. Which coincidentally matches that of a single line strikethrough NSUnderlineStyleSingle
.
Bonus 1 - style
Using NSUnderlineStyle
properly allows even more flexibility, for example by using a thick line (NSUnderlineStyleThick
) or a double line (NSUnderlineStyleDouble
).
Bonus 2 - color
The strikethrough color can also be defined in the attributes:
dictionary via key NSStrikethroughColorAttributeName
.
All this combined results in the following example:
// Show text with a red single line strikethrough:
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"strikethrough"
attributes:@{
NSStrikethroughStyleAttributeName : [NSNumber numberWithInteger:NSUnderlineStyleSingle],
NSStrikethroughColorAttributeName : [NSColor systemRedColor]
}];
_textField.attributedStringValue = text;
Upvotes: 0
Reputation: 2636
For me it works great combining the approach by sbooth of creating a custom NSTextFieldCell
and overriding drawInteriorWithFrame:inView:
as posted below:
- (void) drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
[self setAttributedStringFromStringValue];
[super drawInteriorWithFrame:cellFrame inView:controlView];
}
- (void) setAttributedStringFromStringValue { // add strikethrough
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self.stringValue];
[attributedString addAttribute:NSStrikethroughStyleAttributeName value:(NSNumber *)kCFBooleanTrue range:NSMakeRange(0, attributedString.length)];
[self setAttributedStringValue:attributedString];
}
Upvotes: 1
Reputation: 16976
You can do it like this, assuming _textField
is set as an outlet in your xib:
- (void) awakeFromNib
{
NSMutableAttributedString *as = [[_textField attributedStringValue] mutableCopy];
[as addAttribute:NSStrikethroughStyleAttributeName value:(NSNumber *)kCFBooleanTrue range:NSMakeRange(0, [as length])];
[_textField setAttributedStringValue:[as autorelease]];
}
Edit:
If you want to write a custom strikethrough NSTextFieldCell
subclass instead, the only method that should be necessary to override is setStringValue:
- (void) setStringValue:(NSString *)aString
{
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:aString];
[as addAttribute:NSStrikethroughStyleAttributeName value:(NSNumber *)kCFBooleanTrue range:NSMakeRange(0, [as length])];
[self setAttributedStringValue:[as autorelease]];
}
Upvotes: 6