Empty all Fields Swing in one shot - java

I have a JPanel that have a lot of JTextFields and JComboBoxes and JRadioButtons, so i want to make them all in the default values in one shot.
I used to empty every field one by one but this take lot of time, and maybe i miss some fields, or some times i can add another fields, so it is not practice at all.
public void empty(){
field1.setText("");
field2.setText("");
field3.setText("");
...
}
So is there any way to make all the fields empty in one shot?
Thank you.

If the JTextFields are not all in the same container, this would be a possible approach:
private List<JTextField> allTextFields = new ArrayList<JTextField>();
private JTextField createNewTextField(String text) {
JTextField textField = new JTextField(text);
allTextFields.add(textField);
return textField;
}
private void resetAllTextFields(){
for (JTextField textField : allTextFields) {
textField.setText("");
}
}
..and then instead of using the constructor JTextField myTextField = new JTextField("content") use JTextField myTextField = createNewTextField("content");

Your question is a bit broad, and no one-size-fits all solution is optimal, but I can say that iterating through a JPanel's components, and clearing all is not the best solution for several reasons, including:
You may later wish to add a component that is not cleared, or that is only cleared under certain conditions, and having code that directly clears components may make this hard to debug and fix.
Most GUI's have layers of JPanels, and if later you add a sub-JPanel, does this mean that you're going to want to recursively iterate through all components and clear them?
Better is to strive to separate concerns, to reduce coupling of the model to the view, and for this reason, likely the cleanest solution is to try to separate your model from your view, à la MVC for instance, clear portions of the model that need to be clear, and in the control clear only those portions of the view bound to that section of the model.

This should work:
Component[] tmp = p.getComponents(); // p is your JPanel
for(Component c : tmp) {
if(c instanceof JTextField) {
((JTextField) c).setText("");
}
}
and you can even do different code for different component types...

The link How to clear all input fields within a JPanel i think it help me, my code should look like this :
private void clearAllFields() {
for (Component C : myPanel.getComponents()) {
if (C instanceof JTextField || C instanceof JTextArea) {
((JTextComponent) C).setText("");
}
if (C instanceof JComboBox) {
((JComboBox) C).setSelectedIndex(0);
}
if (C instanceof JRadioButton) {
((JRadioButton) C).setSelected(false);
}
if(C instanceof JDateChooser){
((JDateChooser) C).setDate(null);
}
}
}

Related

get type of a component in a JPanel

I have a foreach loop that iterates all components in a jPanel, and I want to get the type of a components and check if it's a JRadioButton.
this is the code I tried:
for (Component c : ((Container)jPanel1).getComponents() )
{
if(((JRadioButton)c).isSelected() && c.getComponentType()) {
if(!listrep.contains(((JRadioButton)c).getText())) {
((JRadioButton)c).setForeground(new java.awt.Color(204, 0, 0));;
}
}
}
but it won't work.
How can I do that?
You could use the instanceof operator, but this will give your code a bad code smell as does your entire plan. Better to put the components of interest into an ArrayList for ready reference.
Or even better, get the selected JRadioButton's ButtonModel directly from the ButtonGroup that you use to bind them together.
ButtonModel selectedModel = buttonGroup.getSelection();
if (selectedModel != null) {
// use the selected button's model here
}
for (Component c : jpanel1.getComponents()) {
if (c instanceof JRadioButton) {
//Do what you need to do, if you need to call JRadioButton methods
//you will need to cast c to a JRadioButton first
}
}

Swing - Custom Buttons w/Synth

I am working on a project using Synth for the UI and want to implement some custom buttons. The buttons need to make use of style settings from a synth XML settings file - e.g. font colors which are different for different states (MOUSE_OVER, PRESSED, etc).
The problem I'm stuck on is that some of the buttons need to have extra sub-components - e.g. some need more than one label. I want the sub-components to pick up the same style settings as the standard button sub-components.
I feel like I ought to be able to just extend JButton and override/extend paintComponent to call the draw methods of some child components. I'm a bit unsure about a few aspects of that approach though: e.g. what parameters to pass to paintComponent; and how to ensure the sub-components get the correct Synth style settings (particularly wrt. the states).
An aside: I have tried extending JPanel but have run into some difficulties with that approach (see here: JPanel states for Synth).
EDIT: So, I've discovered that it is possible to add sub-components to buttons and have them render correctly. It seems that even though JButton.getLayout() returns null, the button will use an OverlayLayout unless you call JButton.setLayout(). Calling JButton.setLayout(null) does prevent the OverlayLayout being used, so that's how I'm handling the layout.
I'm looking into a couple of different approaches to updating the styles for the child controls, will report back on those later.
So, in case it's of use to anyone else here's the approach I took in the end:
class CustomButton extends JButton {
CustomButton() {
// ... normal button init
// Enable absolute positioning of sub-components.
setLayout(null);
updateStyles();
getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
updateStyles();
}
});
}
private void updateStyles() {
// See below for implementation.
}
private int getSynthComponentState() {
// This is basically a copy of SynthButtonUI.getComponentState(JComponent)
int state = SynthConstants.ENABLED;
if (!isEnabled()) {
state = SynthConstants.DISABLED;
}
if (model.isPressed()) {
if (model.isArmed()) {
state = SynthConstants.PRESSED;
} else {
state = SynthConstants.MOUSE_OVER;
}
}
if (model.isRollover()) {
state |= SynthConstants.MOUSE_OVER;
}
if (model.isSelected()) {
state |= SynthConstants.SELECTED;
}
if (isFocusOwner() && isFocusPainted()) {
state |= SynthConstants.FOCUSED;
}
if (isDefaultButton()) {
state |= SynthConstants.DEFAULT;
}
return state;
}
}
I found 2 approaches to how to implement the updateStyles() method: (A) change the name of the component to use a different named style, or (B) copy the style settings from the button to the sub-components. Approach (A) is pretty straightforward, approach (B) works as follows:
private void updateStyles() {
SynthStyle ss = SynthLookAndFeel.getStyle(this, Region.BUTTON);
SynthContext sc = new SynthContext(this, Region.BUTTON, ss, getSynthComponentState());
for (Component c : getComponents()) {
c.setFont(ss.getFont(sc));
c.setBackground(ss.getColor(sc, ColorType.BACKGROUND));
c.setForeground(ss.getColor(sc, ColorType.FOREGROUND));
// ... and so on if you have other style elements to be changed.
}
}
Approach (A) is probably better if you're changing more than a couple of style settings with each different state, although it could get unwieldy if you have different styles for a lot of different states. If you're only changing a couple of style settings (e.g. in my case I only care about colours, at least for now) then approach (B) seems best.
There's also the approach suggested by trashgod of implementing a custom UI delegate (extending BasicButtonUI) but if you take that route I think you'll have to re-implement much of SynthButtonUI.

set focus for all fields

I noticed I can use getName() as part of the trick.
What is java.awt.Component.getName() and setName() used for?
But I don't really have a clue where to start. What type of listener should I use (assuming the textfield / or box is currently blinking / selected)
This is my previous question, and thank you for the help guys.
How do I use requestFocus in a Java JFrame GUI?
I realize that for each component (Textfield) that I am creating, I have to insert a statement like requestFocus (or using transferFocus).
Is it possible to apply this policy to all the fields???
I have several textfields and ComboBox. The problem I hit is that I don't want to write methods for every single field / box.
For example, I write a method like this
private JTextField getFirstNameEntry() {
.... do something
}
because my instructor writes his program like this
private JPanel getJContentPane() {
jContentPane = new JPanel();
jContentPane.setLayout(new java.awt.FlowLayout(FlowLayout.LEADING));
jContentPane.add(makeLabel(" First Name *", 100, 20));
jContentPane.add(getFirstNameEntry(), null);
jContentPane.add(makeLabel(" Middle Initial", 100, 20));
jContentPane.add(getMiddleInitialEntry(), null);
// etc
return jContentPane;
However, to save redundancy (that was my motive at first), say I have a box, I can simply add the following code inside the method above: getJContentPane()
titleBox = new JComboBox(new String[]{"Mr.","Mrs.","Ms.","Dr.","Prof.","Rev."});
jContentPane.add(titleBox);
But doing this, I still need to create a method to do addItemListener
private void setComboBoxFocus() {
titleBox.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = titleBox.getSelectedItem().toString();
System.out.println(titleSelected);
titleBox.transferFocus();
}
}
});
}
However, this doesn't really save redundancy at all. If I have more than one ComboBox to be added, I would have to write another similar method. In fact, even in the case with one ComboBox (titleBox), I would still end up with writing a method for titleBox.
So my question is: is there a way to write a general method that can call focus to all (maybe one for ComboBox type)?
Thank you and sorry for the long post.
Why not take a JComboBox argument to your setComboBoxFocus() method, which allows you to set that listener to any JComboBox you may have? Like so:
private void setComboBoxFocus(JComboBox box) {
box.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = box.getSelectedItem().toString();
System.out.println(titleSelected);
box.transferFocus();
}
}
});
}

Fast replacement for JComboBox / BasicComboBoxUI?

I've got a JComboBox that potentially can have thousands of items. They're sorted, and there's find-as-you-type, so in principle it's not completely unusable.
In practice, it's pretty unusable with just a couple of hundred items. I managed to improve the initial display performance using setPrototypeDisplayValue(), but BasicListUI still insists on configuring the list cell renderer for every item in the box (see BasicListUI.updateLayoutState()).
This, or something like it, is apparently a known issue to Sun; it has been for going on eight years now, so I'm not holding my breath.
Short of implementing my own UI, has anyone got a workaround?
JList might be a better choice, as it uses a fly-weight approach to rendering and appears to support find-as-you-type.
If you use JComboBox, add entries to the model before the component itself starts listening. This SortedComboBoxModel uses a simple insertion sort that is acceptable for a few thousand entries:
class SortedComboBoxModel extends DefaultComboBoxModel {
/** Add elements by inserting in lexical order. */
#Override
public void addElement(Object element) {
this.insertElementAt(element, 0);
}
/** Insert in lexical order by name; ignore index. */
#Override
public void insertElementAt(Object element, int index) {
String name = element.toString();
for (index = 0; index < this.getSize(); index++) {
String s = getElementAt(index).toString();
if (s.compareTo(name) > 0) {
break;
}
}
super.insertElementAt(element, index);
}
}
Here's the hack that I came up with. The drawbacks are:
if you want to maintain the look and feel, you have to separately subclass each BasicComboBoxUI extension you care about
you have to use reflection to load your UI classes, since (for instance) a subclass of WindowsComboBoxUI won't load on Linux
it won't work with L&Fs (e.g. MacOS?) that don't extend BasicComboBoxUI
it makes assumptions about the ListCellRenderer that may not always be warranted
I'm still open to cleaner solutions.
class FastBasicComboBoxUI extends BasicComboBoxUI {
#Override
public void installUI(JComponent c) {
super.installUI(c);
Object prototypeValue = this.comboBox.getPrototypeDisplayValue();
if (prototypeValue != null) {
ListCellRenderer renderer = comboBox.getRenderer();
Component rendererComponent = renderer
.getListCellRendererComponent(this.listBox,
prototypeValue, 0, false, false);
if (rendererComponent instanceof JLabel) {
// Preferred size of the renderer itself is (-1,-1) at this point,
// so we need this hack
Dimension prototypeSize = new JLabel(((JLabel) rendererComponent)
.getText()).getPreferredSize();
this.listBox.setFixedCellHeight(prototypeSize.height);
this.listBox.setFixedCellWidth(prototypeSize.width);
}
}
}
}
I'm still open to cleaner solutions.
Later
Turns out this only solved some of the problems. Initial display of a combo box with a large number of items could still be really slow. I had to make sure the popup list box immediately gets a fixed cell size, by moving the code into the ComboPopup itself, as follows. Note that, as above, this depends on the prototype value.
#Override
protected ComboPopup createPopup() {
return new BasicComboPopup(comboBox) {
#Override
protected JList createList() {
JList list = super.createList();
Object prototypeValue = comboBox.getPrototypeDisplayValue();
if (prototypeValue != null) {
ListCellRenderer renderer = comboBox.getRenderer();
Component rendererComponent = renderer
.getListCellRendererComponent(list, prototypeValue, 0, false, false);
if (rendererComponent instanceof JLabel) {
// Preferred size of the renderer itself is (-1,-1) at this point,
// so we need this hack
Dimension prototypeSize = new JLabel(((JLabel) rendererComponent)
.getText()).getPreferredSize();
list.setFixedCellHeight(prototypeSize.height);
list.setFixedCellWidth(prototypeSize.width);
}
}
return list;
}
};
}

ListCellRenderer not Firing Events on Child Components

The following ListCellRenderer does not receive click events on the nested ComboBoxes. Do I need to enable something?
class FilterCellRenderer implements ListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Filter filter = (Filter)value;
JPanel filterPanel = new JPanel();
FlowLayout layout = new FlowLayout();
layout.setAlignment(FlowLayout.LEFT);
filterPanel.setLayout(layout);
filterPanel.add(new JLabel(filter.getLabel()));
final List<Object> options = filter.getOptions();
if (options.size() > 1) {
JComboBox optionCombo = new JComboBox(new AbstractComboBoxModel() {
public int getSize() {
return options.size();
}
public Object getElementAt(int index) {
return options.get(index);
}
});
optionCombo.setSelectedItem(filter.getValue());
filterPanel.add(optionCombo);
}
if (isSelected) {
filterPanel.setBackground(list.getSelectionBackground());
filterPanel.setForeground(list.getSelectionForeground());
}
return filterPanel;
}
}
Renderer components in swing work like "rubber stamps" -they are just used to render/paint a value and are not added to the parent container in the usual way (just think how a single component could be added in multiple places!).
It sounds like you may want an editor rather than a renderer (an editor is a fully-fledged component, added in one place at any given time). Failing that you will have to install the MouseListener on the JList instead.
Since I didn't need to select rows, I ended up just dynamically adding and elements to a JPanel with a custom layout. Allowed for full component behaviour without having to hack a table.
It's a little bit tricky this. I believe you need to replace the JList with a single column JTable. Then set a table cell editor as well as renderer. IIRC, there might be a problem losing the first click (which gets used to select that cell edited).
Also it's a very good idea to reuse the components between each call to getCellRendererComponent. The components are used as a stamp and then discarded. Performance will suck massively if they are recreated each time.

Categories

Resources