162 votes

Meilleure façon de modifier la couleur d'arrière-plan d'un NSView

Je cherche le meilleur moyen de changer le backgroundColor d'un NSView . J'aimerais également être en mesure de définir les paramètres appropriés de l'option alpha masque pour le NSView . Quelque chose comme :

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

Je remarque que NSWindow a cette méthode, et je ne suis pas un grand fan de la NSColorWheel ou NSImage des options de fond, mais si ce sont les meilleures, je suis prêt à les utiliser.

143voto

mohsenr Points 5433

Oui, ta propre réponse était la bonne. Vous pouvez également utiliser les méthodes Cocoa :

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

Dans Swift :

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 votes

NSRectFill utilise NSCompositeCopy pour faire le remplissage, de sorte qu'il va frapper tout ce qui se trouve derrière lui - il ne se composera pas au-dessus de toute vue ancêtre. Pour les remplissages dont la couleur est partiellement (ou totalement) transparente, utilisez la commande NSRectFillUsingOperation developer.apple.com/mac/library/documentation/Cocoa/Référence/ avec le NSCompositeSourceOver fonctionnement.

0 votes

Oh, c'est logique. J'ai essayé NSRectFill mais la transparence n'a pas fonctionné. J'arrive à Cocoa depuis Cocoa Touch, et je suis surpris de voir qu'à certains égards, le framework Cocoa Touch est plus complet ( !). J'ai pensé faire une extension de classe pour NSView qui vous permettrait de définir backgroundColor comme vous pouvez le faire avec NSWindow ou UIView, mais je ne pense pas que vous pouvez remplacer drawRect avec une extension.

0 votes

Désolé d'avoir manqué la partie sur la transparence. Oui, Cocoa touch rend beaucoup de choses plus faciles. Si vous faites également Cocoa touch, votre propre réponse est en fait meilleure, car elle est plus portable.

123voto

loretoparisi Points 1206

Une solution simple et efficace consiste à configurer la vue pour qu'elle utilise une couche Core Animation comme magasin de sauvegarde. Vous pouvez alors utiliser -[CALayer setBackgroundColor:] pour définir la couleur de fond du calque.

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

C'est ça !

6 votes

Attention : appel setLayer: o setWantsLayer: casse les WebViews que vous pouvez avoir dans votre application de manière très créative ! (Même dans des Windows différents...)

1 votes

Dans la méthode setWantsLayer: est définie : Lorsque vous utilisez des vues adossées à des couches, vous ne devez jamais interagir directement avec la couche. . L'ordre dans lequel setWantsLayer: y setLayer: est appelé est pertinent.

0 votes

Vous ne devez pas définir la couche mais vous pouvez quand même y parvenir. Voir ColoredView à l'adresse objc.io/issues/14-mac/appkit-for-uikit-developers

26voto

BadPirate Points 11614

Je crois que j'ai trouvé comment faire :

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

0 votes

Merci. J'avais besoin de convertir le dirtyRect en CGRect. J'ai modifié la dernière ligne en CGContextFillRect(context, NSRectToCGRect(dirtyRect)); Pouvez-vous modifier votre réponse ?

1 votes

Ils avaient l'habitude d'être pontés sans frais :/

6 votes

Lorsque vous construisez pour 64 bits ou iOS ou que vous construisez 32 bits comme 64 bits, NSRect est juste une autre façon de dire CGRect. Sinon, cependant, il s'agit de structs indépendants, et même s'ils peuvent être composés des mêmes membres, ils ne peuvent jamais être "toll-free-bridged" car c'est un terme qui se réfère uniquement aux objets (structs qui ont un pointeur "isa" et sont passés autour en utilisant des pointeurs), mais pas aux structures génériques.

23voto

greenhouse Points 111

J'ai parcouru toutes ces réponses et aucune d'entre elles n'a fonctionné pour moi malheureusement. Cependant, j'ai trouvé ce moyen extrêmement simple, après environ une heure de recherche : )

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

9 votes

Notez que les NSViews n'ont pas toujours une couche, dans ce cas, cela ne fait rien. Voir la réponse de Ioretoparisi.

3 votes

J'ai passé beaucoup de temps à essayer d'exécuter ce code dans la méthode viewDidLoad de mon contrôleur (pour self.myCustomView). J'ai découvert que vous devez utiliser la méthode viewWillAppear à la place.

7voto

Nagaraj Points 348

Meilleure solution :

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

0 votes

Hehe. Cela pourrait fonctionner si vous voulez avoir une couleur de fond aléatoire à chaque lancement, mais c'est un peu plus compliqué que de faire la même chose avec draw rect (réponse acceptée).

0 votes

S'il s'agit simplement de dessiner une couleur de BG, quel est l'intérêt de surcharger la fonction "drawRect :".

0 votes

Oui, la meilleure réponse stackoverflow.com/a/2962882/285694 donne cette réponse. Ma question exigeait en fait un canal alpha, j'ai donc coché cette case stackoverflow.com/a/2962839/285694 - Techniquement, cette question concerne le réglage de l'arrière-plan d'un NSView avec un canal Alpha (comme vous pouvez le faire avec NSWindow) -- Mais je pense que beaucoup de personnes viennent ici pour savoir comment régler la couleur (c'est pourquoi la première réponse est plus populaire).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X