Reset/remove a border in Swing - java

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.

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

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.

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?

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

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.

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.

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

Related

Java Swing How can I create a Color Swatch in my custom ColorChooserPanel?

I'm working on my custom ColorChooserPanel class, but I don't know how to create a ColorSwatch.
I found a class named ColorSwatch or something like that but its package private and I can't access it.
How can I ensure that I have a proper color chooser?
First, you need to think about the way this should work, to formulate your goals into action points that you can always check and see whether and how they are fulfilled:
it should be displayed
it should handle click events
it should be able to return a color (the last chosen color, or a default in lack of that)
Now, a very common way of supporting color choosers is to have something like in this image:
However, this is way too complex for a first implementation. You should first have something which "works", that is, you are able to choose colors to taste success and then work out the subsequent details. Unless you say otherwise, I'm assuming that the Basic colors section is good for now. In that case, you can create a class, which contains a JPanel, containing clickable elements. Your class needs to have a Color member, which one can get calling a getter and which is set when a clickable item inside your JPanel is clicked. The clickable items can be JPanels on their own, for example.
If you prefer something ready-made, then kindly read these:
https://docs.oracle.com/javase/tutorial/uiswing/components/colorchooser.html
https://coderanch.com/t/332515/java/Color-Palette

How to update a panel which shows details of an object

I have a panel, let's call it detailsPanel, which holds a Person reference and displays its field values in the following manner:
Name: person.getName ();
Surname: person.getSurname ();
Emain: person.getEmail ();
.... .......
.... .......
And so on. I will use JLabels (correctly aligned using a GridBagLayout) to show each (fieldName, fieldValue). I have a lot of fields to display.
The problem is that the panel which shows the details must be always visible, i.e it will not be shown in a modal JDialog, so that i could create the panel by simply reading my Person object fields at the panel creation.
The panel must always be visible, and its Person reference will change when the user selects a different row in a Person list. This means i will call a method to update its state, something like:
detailsPanel.setPerson (aPerson);
Now, i'm wondering how i should update all the fields. Should i keep a reference to all the JLabels which show the values, and use setText(value) on each of them when i update the panel, or would it be better to override getText() method for every label, returning the correct field value, so that in the update method i would only repaint the panel, and the text would automatically change when the getter method is used on a different Person object?
Any suggestion is appreciated!
Since this is UI stuff which is usually called almost never (relative to how often things are called in other computation) you don't need to worry about efficiency at all. Just do what you think is the most elegant solution. There are three options That quickly come to my mind. They are ordered from quick and static to elegant and reusable:
Quick and dirty: create your constructor and make everything look nice. Then move everything from the constructor to a separate init() method and every time the entities change, you just call removeAll(); and then init() again.
As you suggested, keep a reference to all labels and use the setPerson() method to update all panels. Then call this method in the constructor (this is arguably the most common solution).
As you suggested, build your own extension of JLabel. This new class should either have an update() method which is to be called when things change, or have it set its own listeners to ensure that it gets notified of any relevant change.
If you are planning to create a single panel which is supposed to display all kinds of objects, you could have those object implement an interface called Displayable which gives you generic access to all its values and maybe even listeners to each value. An alternative to the Displayable interface is to use reflection and use annotations to allow the panel to get its values for display.
Please note that the most elegant solution is - contrary to what some people may tell you - not always the best for any situation. How much maintenance do you expect there to be in the future? How big is the application? Will you ever hand off the code to someone else? All these and more need to be considered to decide how "nice" you want your solution to be.

Java swing - creating text field on button's place

When specific action is performed, I want to replace button with text field. I know that I have to call button1.setVisible(false); but I don't know how to create text field on the exact same place. I am using NetBeans designer, if you can give me a hint, how to add 2 components at same place, and switch between then, something like switching between layers in photoshop, if something like that is possible, would be great. Thanks
For many components in one space, use a CardLayout as see in this short example.

How to make button highlighted or pale in java swing properly?

I'm using Swing with default UI (without any special skins).
How to make some buttons/textfields more bright or more pale? It means the user is expected/not expected(although not completely disabled) to press the button.
Example: user had changed a field - "save" button becomes more bright (for example, green). Status is "compilation failed" - "execute" button is pale (although user can still execute previous version of something). User filled in "password" field - he expected to fill in "password confirmation" - so it becomes bright.
I have: {normal, disabled, invisible}
I want: {bright, normal, pale, disabled, invisibe}.
How to make it properly, without hacking with drawing things, with separation of content and presentation? I want it to look well even if user overridden colour settings in the system. Should I use some other toolkit?
I expect something like I set hints for the given control, and then skin read hints and applies additional look and feel options (such as brighter background) without me dealing with concrete colours. May be one skin will use other background and some other skin will use other font for this effect. Like in enabled/disabled case, but more flexible.
Just use setBackground() to change the color to match the component's status. Maybe even create a Custom Component that has a method to change the status and it knowns which color matches that status.
I'm not sure that I see the value in what you're trying to achieve from the examples that you've provided. Is it possible that users could get confused about how the application works if you give them functionality that differs from their expected user experience?
If the user hasn't yet changed a field, the save button could be completely disabled. What's the value in being able to save if there have been no changes made. Alternatively, if you still dead set on making this distinction, can you do it in another way? Perhaps a visual queue, an icon next to the field that's changed, cell highlighting, or a * appended to the end of the text on the window name to show that there are unsaved changes in a window, perhaps?
From a purely user experience perspective, I don't think you want to go messing with the way people expect applications to behave unless you have a really good reason!

How do I prevent button surround from displaying in Java?

Sorry for the odd choice of words for the title, however, "border" seems to be the inappropriate term. While it is true that the visible line surrounding an icon in a JToggleButton can be made invisible by using setBorderPainted(false), the same is not true for JCheckBox and JRadioButton.
I can not use the JToggleButton and therefore need to use either the JCheckBox or JRadioButton (or some derivative of JToggleButton I am not aware of), but need the square or circle, respectively, to be non-visible when there is no icon on the button. Also, using setVisible(false) eliminates the button from the layout, however, I need the space to be reserved and not have the component layout change (using GroupLayout).
Any suggestions? Am I going to have to create a custom renderer? I will be looking at that in the mean time.
The route into this would be through customising the look at feel by changing some of the UI properties in the UImanager (the sort of thing that allows you to make simple tweaks with fonts and colours and presumably the images used for the checkboxes or radiobuttons) -- but it's many years since I last did that sort of thing and can't remember the details.
A little Googling turned up this project to inspect current property values, so might at least help with indicating the right part of the APIs to be looking at.
You have to choices here:
1) Customize Look and Feel as described in previous entry.
2) Create your own custom controls by inheriting from existing ones and overriding component painting.
I found a cheap and easy (read hack) for this. I created an empty transparent icon and used it when I didn't want any item to be displayed.

Categories