views:

535

answers:

7

Here's a very specific coding question:

I've recently been asked to maintain some old-ish Java Swing GUI code at work and ran into this problem:

I've attached my own subclass of InputVerifier called MyFilenameVerifier to a JTextField (but it may as well be any JComponent for these purposes). I've overridden the verify() method such that it calls super.verify(input) (where input is the JComponent parameter to verify()). If super.verify(input) comes back false, I do:

input.setBorder(BorderFactory.createLineBorder(Color.RED));

This is a convention used throughout the UI of this application that started long before me, so I don't have a lot of choice as far as using other ways to get the users attention (wish I did). This is just the way it works.

Problem is, once the user goes back and types something valid into the text field, I need a way to set it back to default border (instead of just saying set it to Color.GRAY or whatever, which is a different color from its original border). I need a way to say, "remove the extra decoration and go back to normal" or just set the border to its default, in other words.

+3  A: 

Couldn't you just call input.getBorder() and cache it somewhere before setting the border to red?

Michael Myers
Yes, I could, which I almost immediately realized after asking the question. For reason, I did not see getBorder() in the API spec, even though it's clearly there. I need a break.
Troy Nichols
Why save something you can compute though? Make the Look and Feel do the work for you.
John Gardner
+1  A: 

Not sure how your system is build, but I think you can store the original border before changing it. So you can change it back later

// assuming the Border was not null before
if (!super.verify(input)) {
    original = input.getBorder();
    input.setBorder(...);
} else {
    if (original != null) {
        input.setBorder(original);
        original = null;  // not needed
    }
}
Carlos Heuberger
+3  A: 

input.getBorder()

Wouldn't it be awesome if no one ever saw this and I got away free without the ass-beating I deserve for asking this question?

Troy Nichols
A: 

You need to preserve the existing border when you change it.

One way to do this is to use the methods putClientProperty() and getClientProperty(), which you'll find documented in the API.

kdgregory
A: 

Incidentally, you only need a single static reference to the border-- it's the selfsame border instance used by all JTextFields.

Neil Coffey
+1  A: 

Another possibility, if there are only a few input widgets you need this for is to subclass, e.g. JTextField, add setBorderOverride() and modify getBorder() to return "overriddingBorder" if it is not null.

Then you just use setBorderOverride(redBorder) to make it red and setBorderOverride(null) to clear it.

This of course depends on the painting to use getBorder(), which it may or may not do, and which may be implementation specific.

Software Monkey
+1  A: 

Or without caching anything, you could tell the JComponent to update its UI back to the look and feel's defaults via component.updateUI. That should make the component reset its colors, borders, fonts, etc to match the original settings.

John Gardner
I like this approach better but it didn't work for me. This code sets it to red border fine, but then leaves it there even after calling updateUI().if(super.verify(input)) input.updateUI();else input.setBorder(redBorder);Going with the less graceful caching option for this one I guess
Troy Nichols
interesting. maybe it also requires invalidate/validate/paint? that's what it looks like SwingUtilities.updateComponentTreeUI(c) does.
John Gardner