NSTextField transparent background - macos

I create transparent NSTextField
self.myTextField = [[NSTextField alloc] initWithFrame:CGRectMake(backgroundView.frame.origin.x + backgroundView.frame.size.width + 20, self.projectTitle.frame.origin.y - 30.0, 100, 20)];
self.myTextField.editable = NO;
self.myTextField.bezeled = NO;
self.myTextField.drawsBackground = YES;
self.myTextField.backgroundColor = [NSColor clearColor];
self.myTextField.selectable = NO;
self.myTextField.font = [NSFont fontWithName:#"Helvetica Neue" size:16];
[self addSubview:self.compressingTime];
And as a result text look bad.
If I set background color
self.myTextField.backgroundColor = [NSColor colorWithCalibratedRed:0.85 green:0.85 blue:0.85 alpha:1.0];
everything looks ok
I have also tried with drawsBackground = NO; Do you guys know how to fix this?

The secret is setting ALL THREE of these properties on the NSTextField...
myTextField.bezeled = NO;
myTextField.editable = NO;
myTextField.drawsBackground = NO;

There is a property in the .xib file, on the interface builder window for the text field, under attribute inspector
Check the Display Draws Background
Select a background color. Select clear color for transparent background.

As of 10.12 you can just do:
let label = NSTextField(labelWithString: "HELLO")

Came here looking for this too, and have got the background to give me a transparent grey. Key is to not have a bezel. My code below:
NSTextField *yourLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, width , height * 1.0/3.0)];
yourLabel.editable = false;
yourLabel.bezeled = false;
[yourLabel setTextColor:[NSColor blackColor]];
[yourLabel setBackgroundColor:[NSColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:0.1]];
For completeness I had got the width and height earlier because they get used many times for layout:
height = self.window.frame.size.height;
width = self.window.frame.size.width;

I ended up using CATextLayer instead NSTextField.

I have same problem. Default appearance is empty. I try set dark mode and it work.
self.nameTextField.appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark];

I had this problem just now. I fixed it by removing a property named backgroundColor from the NSTextField's superview.
I was using backgroundColor just as a convenience getter/setter for the CALayer properties on an NSView subclass. Although this property isn't documented on NSView, it looks like I had accidentally overridden a property on NSView.
Yay for subclassing! 😒

The clear color will make the current view (ie)NSTextView's background as transparent hence the color of NSView which holds the NSTextView is visible.

Related

Shadow Effect not working with Resizable NSView

I have written below code for shadow effect for my NSView.
[_nsview setWantsLayer:YES];
_nsview.layer.masksToBounds = NO;
_nsview.layer.cornerRadius = 5;
_nsview.layer.shadowOffset = CGSizeMake(.3f, -.3f);
_nsview.layer.shadowRadius = 10;
_nsview.layer.shadowOpacity = 0.20;
_nsview.layer.shadowColor = [NSColor blackColor].CGColor;
_nsview is outlet of that NSView. Above code works perfectly and gives shadow effect...But problem is that after resizing _nsview shadow getting hide.
Use NSShadow instead:
[_childView setWantsLayer:YES];
_childView.layer.backgroundColor = [NSColor whiteColor].CGColor;
_childView.layer.cornerRadius = 5;
NSShadow *dropShadow = [[NSShadow alloc] init];
[dropShadow setShadowColor:[NSColor colorWithWhite:0.1 alpha:0.6]];
[dropShadow setShadowOffset:NSMakeSize(0, -5)];
[dropShadow setShadowBlurRadius:5];
_childView.shadow = dropShadow;
Unless you're using a layer-hosting view (note: different from a layer-backed view) then you should assume that NSView can change layer properties at any time behind the scenes. Shadows and transforms are the most common properties to change outside of the developer's control.
Here is some useful reading:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/SettingUpLayerObjects/SettingUpLayerObjects.html
https://www.objc.io/issues/14-mac/appkit-for-uikit-developers/

How set font and color on nstextfield in cocoa?

I want set font on panel and change the selected font. I am using NSColorWell to open and select the color. For font, what can I use? How can I open the font panel and perform action when font panel is closed?
Currently I am using
'- (IBAction)Open_Font_Button:(id)sender
{
NSFontManager *fontManager = [NSFontManager sharedFontManager];
[fontManager setDelegate:self];
[fontManager setTarget:self];
[fontManager orderFrontFontPanel:self];
}
- (void)changeFont:(id)sender
{
font = [sender convertFont:font];
NSLog(#"%#", font);
}
'
but on chnageFont, when I change any font or its size it crashes.
I assume you have outlets to the ColorWell and textField connected:
IBOutlet NSColorWell *colorWell;
IBOutlet NSTextField *textfield;
You should set some things about the NSColorPanel:
[NSColor setIgnoresAlpha:NO];
[[NSColorPanel sharedColorPanel] setShowsAlpha:YES];
When you open or close a window that might display a color panel you should be sure you aren't left with a color panel hanging around:
if ([NSColorPanel sharedColorPanelExists])
{
[[NSColorPanel sharedColorPanel] close];
}
Then in your IBAction method for the color well you can get the color:
NSColor *color;
color = [colorWell color];
You can then set the font and color with:
[textField setFont:anNSFont *];
[textField setTextColor:color];
EDIT:
I just realized you're also asking how to get a new font from the font panel.
To get a new font from the font panel your code should actually work fine unless "font" (the old font) was never initialized. If font is null then [sender convertFont:font] will return null.
This prints null:
- (void)changeFont:(id)sender
{
NSFont *font;
font = [sender convertFont:font]; // Reset the font
NSLog(#"%#", font);
}
This prints a font:
- (void)changeFont:(id)sender
{
NSFont *font = [NSFont fontWithName:#"Helvetica" size:12]; // Initialize the old font
font = [sender convertFont:font]; // Reset the font
NSLog(#"%#", font);
}

Auto-Resizing of NSTextView and/or NSScrollView

I have an NSTextView inside an NSView (which is being used by a NSPopover, don't know if that is relevant) that I'm trying to resize automatically and programmatically (cf caption).
I have been struggling with a lot of stuff, namely :
Looking at NSLayoutManager and usedRectForTextContainer that give me aberrant size values
(usedRectForTextContainer : {{0, 0}, {0.001, 28}})
Modifying NSScrollView frame, [NSScrollView contentView], [NSScrollView documentView]
Getting rid of AutoLayout
I reached the point where I can resize my scollview and my Popover, but I can't get the actual height of the text inside the NSTextView.
Any kind of help would be appreciated.
-(void)resize
{
//Get clipView and scrollView
NSClipView* clip = [popoverTextView superview];
NSScrollView* scroll = [clip superview];
//First, have an extra long contentSize and ScrollView to test everything else
[popover setContentSize:NSMakeSize([popover contentSize].width, 200)];
[scroll setFrame:(NSRect){
[scroll frame].origin.x,[scroll frame].origin.y,
[scroll frame].size.width,155
}];
NSLayoutManager* layout = [popoverTextView layoutManager];
NSTextContainer* container = [popoverTextView textContainer];
NSRect myRect = [layout usedRectForTextContainer:container]; //Broken
//Now what ?
}
I still have no idea why I can't use [layout usedRectForTextContainer:container], but I managed to get the NSTextView's height by using :
-(void)resize
{
//Get glyph range for boundingRectForGlyphRange:
NSRange range = [[myTextView layoutManager] glyphRangeForTextContainer:container];
//Finally get the height
float textViewHeight = [[myTextView layoutManager] boundingRectForGlyphRange:range
inTextContainer:container].size.height;
}
Here is some functional code that I have tested myself for swift. usedRectForTextContainer is not broken it just is set lazily. To set it i call glyphrangefortextcontainer
I found the answer here: http://stpeterandpaul.ca/tiger/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html
let textStorage = NSTextStorage(string: newValue as! String)
let textContainer = NSTextContainer(size: NSSize(width: view!.Text.frame.width, height:CGFloat.max))
let layoutManager = NSLayoutManager()
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = NSLineBreakMode.ByWordWrapping
textStorage.font = NSFont(name: "Times-Roman", size: 12)
layoutManager.glyphRangeForTextContainer(textContainer)
let rect = layoutManager.usedRectForTextContainer(textContainer)
Swift.print(rect)
The documentation also suggest that is the the case:

how to get window with semi-transparent blurred background

I'd like to get a window that has a semi-transparent blurred background, just like what the Terminal can do. See this video, about 30 sec in, to see what I mean: http://www.youtube.com/watch?v=zo8KPRY6-Mk
See an image here: http://osxdaily.com/wp-content/uploads/2011/04/mac-os-x-lion-terminal.jpg
I've been googling for an hour, and can't get anything to work. I believe I need to somehow create a core animation layer and add a background filter, but I've been unsuccessful so far... I just see the gray background of my window. Here's the code I've got so far:
Code:
// Get the content view -- everything but the titlebar.
NSView *theView = [[self window] contentView];
[theView setAlphaValue:0.5];
// Create core animation layer, with filter
CALayer *backgroundLayer = [CALayer layer];
[theView setWantsLayer:YES];
[theView setLayer:backgroundLayer];
CIFilter *blurFilter = [CIFilter filterWithName:#"CIGaussianBlur"];
[blurFilter setDefaults];
[theView layer].backgroundFilters = [NSArray arrayWithObject:blurFilter];
[[theView layer] setBackgroundFilters:[NSArray arrayWithObject:blurFilter]];
Any tips or examples to do what I'm trying to do?
Thanks!
no need for layers and filters, NSWindow can do it itself
[mywindow setOpaque:NO];
[mywindow setBackgroundColor: [NSColor colorWithCalibratedHue:0.0 saturation:0.0 brightness:0.2 alpha:0.5]];
please do not use this, as it will alpha your title bar also (post it here just in case others need)
[mywindow setOpaque:NO];
[mywindow setBackgroundColor: [NSColor blackColor]];
[mywindow setAlphaValue:0.5];
For the transparency use Jiulong Zhao's suggestion.
For a blurred background use this
The call on a NSWindow :
[self enableBlurForWindow:self];
The function :
-(void)enableBlurForWindow:(NSWindow *)window
{
//!!!! Uses private API - copied from http://blog.steventroughtonsmith.com/2008/03/using-core-image-filters-onunder.html
CGSConnection thisConnection;
uint32_t compositingFilter;
int compositingType = 1; // Under the window
/* Make a new connection to CoreGraphics */
CGSNewConnection(NULL, &thisConnection);
/* Create a CoreImage filter and set it up */
CGSNewCIFilterByName(thisConnection, (CFStringRef)#"CIGaussianBlur", &compositingFilter);
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:2.0] forKey:#"inputRadius"];
CGSSetCIFilterValuesFromDictionary(thisConnection, compositingFilter, (__bridge CFDictionaryRef)options);
/* Now apply the filter to the window */
CGSAddWindowFilter(thisConnection, [window windowNumber], compositingFilter, compositingType);
}
NB: It uses a private API
For those reading this in 2017 and using Swift 4 and wanting to change your BG Alpha you can add the following to your custom NSWindow class:
self.backgroundColor = NSColor.black
self.backgroundColor = NSColor.init(calibratedHue: 0, saturation: 0, brightness: 0, alpha: 0.2)
p.s. I do not need the blur effect yet and when I do, I'll update the answer

Changing alpha of window background, not the whole window

so i have a quick question i have the method below which sets the alpha value of a window depending on the value from a slider, however the content of the window also becomes translucent and eventually disappears with the window.
Is there a way to just change the alpha value of the window and not the content view inside it?
- (IBAction)changeTransparency:(id)sender {
// Set the window's alpha value. This will cause the views in the window to redraw.
[self.window setAlphaValue:[sender floatValue]];}
Thanks, Sami.
Apple's docs gives a way to do this. The key is to set the window's backgroundColor's alpha to the desired value. You must also make sure to set the window's opaque property to NO (which is YES by default.)
e.x.
// At some point in your code...
[window setOpaque:NO];
// Then in your changeTransparency: method...
NSColor *backgroundColor = [window backgroundColor];
backgroundColor = [backgroundColor colorWithAlphaComponent:[sender floatValue]];
[window setBackgroundColor:backgroundColor];
Here is another way.
Suppose,
self.window <--- base view and this alpha will be changed (but exacatly fake).
subView1, subView2 <-- these views are contents of self.window. and theier alpha should not be changed.
self.window.backgroundColor = [UIColor clearColor];
UIView* anAlphaView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.frame.size.widht, self.window.frame.size.height)];
anAlphaView.backgroundColor = [UIColor blackColor]; // as you want
anAlphaView.alpha = 0.5f; // as you want.
[self.window addSubview:anAlphaView];
[anAlphaView release];
[self.window addSubview:subView1]; // you should add sub views to self.window
[self.window addSubview:subView2];
You can make a method using above code :)

Resources