2
votes

UPDATE:

I've added a sample project for testing, see at the bottom of the post.

ORIGINAL QUESTION:

I've got an NSWindow and I change its background when some other parameters change.

The window background is a gradient I'm drawing by overriding drawRect in a subclass of the window's view.

class MainWindowView: NSView {
    override func drawRect(dirtyRect: NSRect) {
        var rect = dirtyRect
        let gradient = NSGradient(startingColor: backgroundColor, endingColor: darkerBackgroundColor)
        gradient.drawInRect(rect, relativeCenterPosition: NSPoint(x: 0, y: 0))
        super.drawRect(rect)
    }
}

And I've got two NSTextFields on this window.

The NSTextFields are both set to drawsBackground = false in awakeFromNib and set to borderless in IB.

I'm not using NSAttributedStrings here, only changing the stringValue of the NSTextFields, and of course their textColor.

Everything is working... except that sometimes, the text fields have an unexpected slightly dark semi-transparent background.

NOT GOOD

(It's hard to see on some screens but it's there.)

Question: why does this darker background appear?

And of course: what could I do to fix it?

I'm pretty sure it's the gradient that breaks something but I can't find what...

Note: the project is in Swift but I can read an Objective-C answer.

EDIT:

So indeed it seems to be coming from the gradient that's behind, see this other screenshot from a test window. This time the gradient is drawn in a Custom View under an NSTextView, and the same undesired effect happens: parts of the text field background are visible but shouldn't.

Example 2

UPDATE:

I have made a very simple example in a project for testing, with a gradient that shows the phenomenon more visibly. There's only a window, my gradient class and a text field. You can get it (30ko only) in this ZIP file.

example in project

2

2 Answers

1
votes

You always draw the gradient in the dirty rect. When the text changes, that rect is only the size of the textfield, not of the whole view. Your drawRect function then draws the full gradient in the textfield's background rect, rather than just the portion of the background-view-wide gradient you'd see through the textfield.

If you redraw using your view's frame, and ignore the dirty rect argument, you should get the desired appearance.

0
votes

I'm guessing your text field isn't layer-backed. If not, turn on layers (in IB or via -wantsLayer for the view in code) for at least the text field. If that alone doesn't work, try turning on layers for the gradient-hosting view as well.