NSView의 배경색을 변경하는 가장 좋은 방법


149

나는 변경하는 가장 좋은 방법을 찾고 있어요 backgroundColor의를 NSView. 또한에 적합한 alpha마스크 를 설정하고 싶습니다 NSView. 다음과 같은 것 :

myView.backgroundColor = [NSColor colorWithCalibratedRed:0.227f 
                                                   green:0.251f 
                                                    blue:0.337 
                                                   alpha:0.8];

나는 NSWindow이 방법 을 가지고 있으며 NSColorWheel, 또는 NSImage배경 옵션에 대한 열렬한 팬이 아니지만 최선의 경우 기꺼이 사용하려고합니다.

답변:


134

네, 당신의 대답은 옳았습니다. 코코아 방법을 사용할 수도 있습니다.

- (void)drawRect:(NSRect)dirtyRect {
    // set any NSColor for filling, say white:
    [[NSColor whiteColor] setFill];
    NSRectFill(dirtyRect);
    [super drawRect:dirtyRect];
}

스위프트에서 :

class MyView: NSView {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // #1d161d
        NSColor(red: 0x1d/255, green: 0x16/255, blue: 0x1d/255, alpha: 1).setFill()
        dirtyRect.fill()
    }

}

18
NSRectFill을 사용 NSCompositeCopy하여 채우기를 수행하므로 뒤에있는 항목이 모호 해져 상위 뷰 위에 합성되지 않습니다. 부분적으로 (또는 전체적으로) 투명한 색상으로 채울 경우 NSRectFillUsingOperation developer.apple.com/mac/library/documentation/Cocoa/Reference/…NSCompositeSourceOver작업 과 함께 사용 하십시오 .
Peter Hosey

오, 말이 되네요 NSRectFill을 시도했지만 투명성이 작동하지 않았습니다. Cocoa Touch에서 Cocoa로오고 있는데, 어떤 방식으로 Cocoa Touch 프레임 워크가 더 완벽하다는 것을보고 놀랐습니다 (!). NSWindow 또는 UIView처럼 backgroundColor를 설정할 수있는 NSView 클래스 확장을 만들려고 생각했지만 확장 프로그램으로 drawRect를 재정의 할 수는 없다고 생각합니다.
BadPirate

투명도 부분을 놓쳤다 죄송합니다. 예, 코코아 터치는 많은 것들을 더 쉽게 만듭니다. Cocoa touch를 사용하는 경우 휴대 성이 더 뛰어나므로 실제로 자신의 대답이 더 좋습니다.
mohsenr 2016 년

나는 그것을 얻지 못한다. 이것은보기 위에 흰색을 그리는 중이다. 방금 시도했다. 배경색에 대한 질문이 아니 었습니까?
aneuryzm

@Patrick-super drawRect :)를 호출하거나 배경 위에 그려야 할 다른 것들이 있으면 NSRectFill 호출 이후에 있는지 확인하십시오.
BadPirate

116

쉽고 효율적인 솔루션은 Core Animation 레이어를 백업 저장소로 사용하도록 뷰를 구성하는 것입니다. 그런 다음 -[CALayer setBackgroundColor:]레이어의 배경색을 설정하는 데 사용할 수 있습니다 .

- (void)awakeFromNib {
   self.wantsLayer = YES;  // NSView will create a CALayer automatically
}

- (BOOL)wantsUpdateLayer {
   return YES;  // Tells NSView to call `updateLayer` instead of `drawRect:`
}

- (void)updateLayer {
   self.layer.backgroundColor = [NSColor colorWithCalibratedRed:0.227f 
                                                          green:0.251f 
                                                           blue:0.337 
                                                          alpha:0.8].CGColor;
}

그게 다야!


6
주의 : 매우 창의적인 방식으로 응용 프로그램에있을 수있는 WebView를 호출 setLayer:하거나 setWantsLayer:중단합니다! (다른 창에서도 ...)
rluba

1
이 방법에는 다음 setWantsLayer:이 정의되어 있습니다. 레이어 기반 뷰를 사용할 때 레이어와 직접 상호 작용해서는 안됩니다 . 시기 setWantsLayer:setLayer:호출 순서 는 관련이 있습니다.
Stephan

레이어를 설정해서는 안되지만 여전히 달성 할 수 있습니다. objc.io/issues/14-mac/appkit-for-uikit-developers에서 ColoredView
Clafou

80

스토리 보드 애호가라면 코드가 필요없는 방법입니다 .

NSBoxNSView에 서브 뷰로 추가 하고 NSView와 동일하게 NSBox의 프레임을 조정합니다.

스토리 보드 또는 XIB에서 제목 위치를 없음으로 변경하고 상자 유형을 사용자 정의로 , 테두리 유형을 "없음"으로, 테두리 색상을 원하는대로 변경하십시오.

스크린 샷은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

결과는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오


NSBox를 사용하면 나에게 효과적이었습니다. 레이어 기반 뷰로 전환하면 다시 그리기 문제가 발생했지만 상자는 그렇지 않았습니다.
Henrik

4
이것은 문서에 포함되어야하는 훌륭하고 간단한 솔루션입니다
UKDataGeek

그래도 NSPopover 삼각형을 색칠합니까?
Ribena

나는이 답변을 제공하기 위해 단 하나의 공의를 유감스럽게 생각합니다.
오리온 엘렌 질

33

먼저 WantsLayer를 YES로 설정하면 레이어 배경을 직접 조작 할 수 있습니다.

[self.view setWantsLayer:YES];
[self.view.layer setBackgroundColor:[[NSColor whiteColor] CGColor]];

26

내가하는 방법을 알아 냈다고 생각하십시오.

- (void)drawRect:(NSRect)dirtyRect {
    // Fill in background Color
    CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSetRGBFillColor(context, 0.227,0.251,0.337,0.8);
    CGContextFillRect(context, NSRectToCGRect(dirtyRect));
}

감사. dirtyRect를 CGRect로 변환해야했습니다. 마지막 줄을 CGContextFillRect(context, NSRectToCGRect(dirtyRect));수정했습니다. 답변을 편집 할 수 있습니까?
Ross

1
그들은 무료로 다리를 연결했다 : /
BadPirate

6
64 비트 또는 iOS 용으로 구축하거나 64 비트와 같은 32 비트를 구축 할 때 NSRect는 CGRect를 말하는 또 다른 방법입니다. 그러나 그렇지 않은 경우 이들은 독립적 인 구조체이며 동일한 멤버로 구성되어 있어도 객체 ( "isa"포인터가있는 구조체 만 참조하는 용어이므로 "무료로 브리지") 할 수 없습니다. 포인터를 사용하여 전달되지만 일반적인 구조에는 사용되지 않습니다.
Raphael Schweikert

drawRect를 사용하면 그리기 시간 등이 추가됩니다. CALayer는 10.8 이상에서 더 나은 솔루션입니다.
Tom Andersen

22

나는이 모든 대답을 겪었지만 불행히도 나를 위해 일한 사람은 없습니다. 그러나 약 1 시간의 검색 후이 매우 간단한 방법을 찾았습니다. :)

myView.layer.backgroundColor = CGColorCreateGenericRGB(0, 0, 0, 0.9);

8
NSView에는 항상 레이어가있는 것은 아니며,이 경우 아무 것도하지 않습니다. Ioretoparisi의 답변을 참조하십시오.
Kalle

3
내 컨트롤러의 viewDidLoad 메서드 (self.myCustomView) 에서이 코드를 수행하는 데 많은 시간을 보냈습니다. viewWillAppear 메서드를 대신 사용해야한다는 것을 알았습니다.
surfrider

21

편집 / 업데이트 : Xcode 8.3.1 • Swift 3.1

extension NSView {
    var backgroundColor: NSColor? {
        get {
            guard let color = layer?.backgroundColor else { return nil }
            return NSColor(cgColor: color)
        }
        set {
            wantsLayer = true
            layer?.backgroundColor = newValue?.cgColor
        }
    }
}

용법:

let myView = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
print(myView.backgroundColor ?? "none")     //  NSView's background hasn't been set yet = nil
myView.backgroundColor = .red               // set NSView's background color to red color
print(myView.backgroundColor ?? "none")
view.addSubview(myView)

나는 이것이 가장 깨끗한 해결책이라고 생각하지만 Objc.io 사람들이 여기에서 한 진술에 대해 우려하고 있습니다 : objc.io/issues/14-mac/appkit-for-uikit-developers- "... 상호 작용을 시도해서는 안됩니다 AppKit이 해당 레이어를 소유하고 있기 때문에 직접 레이어를 사용합니다. " 무엇이 잘못 될지 잘 모르겠습니다. 어느 쪽이든, 나는이 솔루션을 내 자신의 코드로 채택하고 있습니다.
Kevin Sliech

7

최고의 솔루션 :

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.wantsLayer = YES;
    }
    return self;
}

- (void)awakeFromNib
{
    float r = (rand() % 255) / 255.0f;
    float g = (rand() % 255) / 255.0f;
    float b = (rand() % 255) / 255.0f;

    if(self.layer)
    {
        CGColorRef color = CGColorCreateGenericRGB(r, g, b, 1.0f);
        self.layer.backgroundColor = color;
        CGColorRelease(color);
    }
}

헤헤 시작할 때마다 임의의 배경색을 원한다면 효과가있을 것입니다. 조금 더 복잡하지만 rect rect (허용 된 답변)로 동일한 작업을 수행합니다.
BadPirate

BG 색상을 그리는 것이 문제라면 "drawRect :"를 재정의
해야하는 것

예, 최고 답변 stackoverflow.com/a/2962882/285694 가 그 답변을 제공합니다. 내 질문에 실제로 알파 채널이 필요했기 때문에이 질문에 검사를주었습니다 .- stackoverflow.com/a/2962839/285694- 기술적 으로이 질문은 NSView에서 배경을 알파 채널로 설정하는 것에 관한 것입니다 (NSWindow에서와 같이). -그러나 나는 많은 사람들이 여기에 색을 설정하는 방법을 찾고 있다고 생각합니다.
BadPirate

6

스위프트에서 :

override func drawRect(dirtyRect: NSRect) {

    NSColor.greenColor().setFill()
    NSRectFill(dirtyRect)

    super.drawRect(dirtyRect)
}

5

NSView의 하위 클래스 인 NSBox를 사용하면 쉽게 스타일을 지정할 수 있습니다.

스위프트 3

let box = NSBox()
box.boxType = .custom
box.fillColor = NSColor.red
box.cornerRadius = 5

NSBox는 삼각형 부분이 있기 때문에 NSPopover의 경우 도움이되지 않습니다.
AnaghSharma

5

의심 할 여지없이 가장 쉬운 방법은 색상 세트 자산과도 호환됩니다.

스위프트 :

view.setValue(NSColor.white, forKey: "backgroundColor")

목표 -C :

[view setValue: NSColor.whiteColor forKey: "backgroundColor"];

인터페이스 빌더 :

backgroundColor인터페이스 빌더에서 유형 의 사용자 정의 속성 을 추가하십시오 NSColor.


이것은 문서화되지 않은 동작에 의존하며 이후 버전의 AppKit에서 계속 작업하려면 피해야합니다.
nschmidt

3

나는 다음을 테스트했고 (Swift에서) 나를 위해 일했다.

view.wantsLayer = true
view.layer?.backgroundColor = NSColor.blackColor().colorWithAlphaComponent(0.5).CGColor

이 작업을 수행 한 후보기 위에 이미지를 넣었습니까? 아니면 NSImageView 대신 NSView를 사용 했습니까?
justColbs 2016 년

3

Swift 3에서 확장을 생성하여 수행 할 수 있습니다.

extension NSView {
    func setBackgroundColor(_ color: NSColor) {
        wantsLayer = true
        layer?.backgroundColor = color.cgColor
    }
}

// how to use
btn.setBackgroundColor(NSColor.gray)


1

신속하게 NSView를 서브 클래스 화하고 이것을 할 수 있습니다

class MyView:NSView {
    required init?(coder: NSCoder) {
        super.init(coder: coder);

        self.wantsLayer = true;
        self.layer?.backgroundColor = NSColor.redColor().CGColor;
    }
}

1
Swift 4.2 Xcode 10 self.layer? .backgroundColor = NSColor.red.cgColor
brian.clear

1

재사용이 가능한 작은 클래스 (Swift 4.1)

class View: NSView {

   var backgroundColor: NSColor?

   convenience init() {
      self.init(frame: NSRect())
   }

   override func draw(_ dirtyRect: NSRect) {
      if let backgroundColor = backgroundColor {
         backgroundColor.setFill()
         dirtyRect.fill()
      } else {
         super.draw(dirtyRect)
      }
   }
}

// Usage
let view = View()
view.backgroundColor = .white

1

backgroundColor뷰 레이어를 백업 한 후 레이어를 설정하기 만하면됩니다 .

view.wantsLayer = true
view.layer?.backgroundColor = CGColor.white

0

응용 프로그램이 실행되는 동안 시스템 전체 모양 변경 (어두운 모드 켜기 또는 끄기)을 지원합니다. 뷰의 클래스를 먼저 BackgroundColorView로 설정 한 경우 Interface Builder에서 배경색을 설정할 수도 있습니다.


class BackgroundColorView: NSView {
    @IBInspectable var backgroundColor: NSColor? {
        didSet { needsDisplay = true }
    }

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        wantsLayer = true
    }

    required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
        wantsLayer = true
    }

    override var wantsUpdateLayer: Bool { return true }

    override func updateLayer() {
        layer?.backgroundColor = backgroundColor?.cgColor
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.