Getting Components by name not support all actions? - java

I have jTextField named "p0_1000"
And i use below methods can call it by name;
Creating Hashmap in class.
private HashMap componentMap;
Fill hashmap with components name.
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
Component[] components = jDesktopPane1.getComponents();
for (int i=0; i < components.length; i++) {
componentMap.put(components[i].getName(), components[i]);
}
}
For call components by their names.
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
If i use directly p0_1000.setToolTipText("trying"); succesfully appear tooltiptext when mouse on releated textfield.
But if i use getComponentByName("p0_1000").setToolTipText("trying"); setToolTipText not recognized.
getComponentByName("p0_1000") succesfully working i tested. Because if i type "." after method name, avaliable action list come and i can use them (example .setVisible(false) working succesfully)
Some add, set or get commands not in avaliable action list when i call componen by name.
Any advice, idea, comments are appreciated.
Regards.
---SOLVED---
public JComponent getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (JComponent) componentMap.get(name);
}
else return null;
}
Above changes solve my problem.

You probably should be using JComponent which is has setToolTipText. If that's not what you want, you can check if the java.awt.Component is a JComponent and cast:
if (components[i]) instanceof JComponent) {
JComponent jc = (JComponent) components[i];
// now you can use setToolTipText
}

Your problem is that your method is declared to return Component type, and if you look in the API for this class, you'll see that it does not have a setToolTipText(...) method. This method begins in the JComponent class. One solution is to have the Map only collect JComponents and have the method declared to return this type. Incidentally, if you declare your Map with generic parameters, you won't have to do your cast.
i.e., rather than this declaration,
private HashMap componentMap;
use,
private HashMap<String, Component> componentMap;
or if again if this will work for you:
private HashMap<String, JComponent> componentMap;

Related

Iterating changes over multiple labels at once

I am trying to make a function in my program that will read a string, and then set every jlabel on my page to that string. I am aware of .setText(); but I am intending to do this to 100's of labels at once. Using the below code I intended to use a for loop and call the method for as many times as I will have labels and send the label name within the function. i.e.
button.pressed() {
updateLabel(labelName);
}
public void updateLabel(String name) {
…
}
But to test the code initially I just hardcoded the name of one label in and ran it. the first time it worked but now I get a null pointer exception every time. please someone help. The actual code below:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
labeltest();
}
public void labeltest() {
for (Component c : this.getContentPane().getComponents()) {
if (c.getName().equals("Jlabel")) {
// do the modifications...
((JLabel) c).setText("Updated");
}
}
}
By default, Component.name is null, therefore to select only label, you should use instance of:
private void updateLabels(String str) {
for (Component component : getContentPane().getComponents())
if (component instanceof JLabel)
((JLabel)component).setText(str);
}
I think in general case, there're many component on the panel and a few labels. Therefore
using for (Component component : getComponents()) {} is not the best solution.
In case you want to set the same text to all the labels, then is is better to create a List<JLabel> with all labels that should be updated and us it to set a text:
private final List<JLabel> labels = new ArrayList<>();
private void init() {
add(createLabel());
}
// hide add to labels within create method
private JLabel createLabel() {
JLabel label = new JLabel():
labels.add(label);
return label;
}
In case you want to set different text to the labels, then it is better to set correct name for the labels and use Map<String, JLabel> with all labels:
private final Map<String, JLabel> labels = new HashMap<>();
private final static String NAME_ACCOUNT = "account";
private final static String NAME_SCORE = "score";
private void int() {
add(createLabel(NAME_ACCOUNT));
add(createLabel(NAME_SCORE);
}
// hide add to labels within create method
private JLabel createLabel(String name) {
JLabel label = new JLabel():
label.setName(name);
labels.put(name, label);
return label;
}
Here's a potential problem:
if (c.getName().equals("Jlabel")) {
as most Swing components don't have the name property set unless you, the coder, explicitly set it, and I have to wonder if this is the source of your NullPointerException.
Better to do:
if (c instanceof JLabel) {
// ....
}
So yes, you could recursively iterate through all components held in all Containers on your GUI, checking each if instanceof JLabel, and then casting and setting, but ... no, this is not clean, not good.
Why not simply put the JLabels into a collection such as
List<JLabel> labels = new ArrayList<>();
and then use a for loop, iterate over the list and change the state of the labels.
.... or I wonder if you're looking to use other components to display your Strings, such as a JList<String> perhaps?

Get value of JTextField whose name is stored in a String variable in JAVA [duplicate]

I have in a JFrame some components that I want
to refer into another JFrame and I want
to get them by name and not
do public get/set methods for each.
Is there a way from Swing to get a component reference by its name like do
c#?
e.g. form.Controls["text"]
Thanks
I know this is an old question, but I found myself asking it just now. I wanted an easy way to get components by name so I didn't have to write some convoluted code each time to access different components. For example, having a JButton access the text in a text field or a selection in a List.
The easiest solution is to make all of the component variables be class variables so that you can access them anywhere. However, not everyone wants to do that, and some (like myself) are using GUI Editors that don't generate the components as class variables.
My solution is simple, I'd like to think, and doesn't really violate any programming standards, as far as I know (referencing what fortran was getting at). It allows for an easy and straightforward way to access components by name.
Create a Map class variable. You'll need to import HashMap at the
very least. I named mine componentMap for simplicity.
private HashMap componentMap;
Add all of your components to the frame as normal.
initialize() {
//add your components and be sure
//to name them.
...
//after adding all the components,
//call this method we're about to create.
createComponentMap();
}
Define the following two methods in your class. You'll need to import Component if you haven't already:
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
Component[] components = yourForm.getContentPane().getComponents();
for (int i=0; i < components.length; i++) {
componentMap.put(components[i].getName(), components[i]);
}
}
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
Now you've got a HashMap that maps all the currently existing components in your frame/content pane/panel/etc to their respective names.
To now access these components, it is as simple as a call to getComponentByName(String name). If a component with that name exists, it will return that component. If not, it returns null. It is your responsibility to cast the component to the proper type. I suggest using instanceof to be sure.
If you plan on adding, removing, or renaming components at any point during runtime, I would consider adding methods that modify the HashMap according to your changes.
Each Component can have a name, accessed via getName() and setName(), but you'll have to write your own lookup function.
getComponentByName(frame, name)
IF you're using NetBeans or another IDE that by default creates private variables (fields) to hold all of your AWT/Swing components, then the following code may work for you. Use as follows:
// get a button (or other component) by name
JButton button = Awt1.getComponentByName(someOtherFrame, "jButton1");
// do something useful with it (like toggle it's enabled state)
button.setEnabled(!button.isEnabled());
Here's the code to make the above possible...
import java.awt.Component;
import java.awt.Window;
import java.lang.reflect.Field;
/**
* additional utilities for working with AWT/Swing.
* this is a single method for demo purposes.
* recommended to be combined into a single class
* module with other similar methods,
* e.g. MySwingUtilities
*
* #author http://javajon.blogspot.com/2013/07/java-awtswing-getcomponentbynamewindow.html
*/
public class Awt1 {
/**
* attempts to retrieve a component from a JFrame or JDialog using the name
* of the private variable that NetBeans (or other IDE) created to refer to
* it in code.
* #param <T> Generics allow easier casting from the calling side.
* #param window JFrame or JDialog containing component
* #param name name of the private field variable, case sensitive
* #return null if no match, otherwise a component.
*/
#SuppressWarnings("unchecked")
static public <T extends Component> T getComponentByName(Window window, String name) {
// loop through all of the class fields on that form
for (Field field : window.getClass().getDeclaredFields()) {
try {
// let us look at private fields, please
field.setAccessible(true);
// compare the variable name to the name passed in
if (name.equals(field.getName())) {
// get a potential match (assuming correct <T>ype)
final Object potentialMatch = field.get(window);
// cast and return the component
return (T) potentialMatch;
}
} catch (SecurityException | IllegalArgumentException
| IllegalAccessException ex) {
// ignore exceptions
}
}
// no match found
return null;
}
}
It uses reflection to look through the class fields to see if it can find a component that is referred to by a variable of the same name.
NOTE: The code above uses generics to cast the results to whatever type you are expecting, so in some cases you may have to be explicit about type casting. For example if myOverloadedMethod accepts both JButton and JTextField, you may need to explicitly define the overload you wish to call ...
myOverloadedMethod((JButton) Awt1.getComponentByName(someOtherFrame, "jButton1"));
And if you're not sure, you can get an Component and check it with instanceof...
// get a component and make sure it's a JButton before using it
Component component = Awt1.getComponentByName(someOtherFrame, "jButton1");
if (component instanceof JButton) {
JButton button = (JButton) component;
// do more stuff here with button
}
Hope this helps!
you could hold a reference to the first JFrame in the second JFrame and just loop through JFrame.getComponents(), checking the name of each element.
You can declare a variable as a public one then get the text or whatever operation you want and then you can access it in the other frame(if its in the same package) because it's public.
I needed to access elements inside several JPanels which were inside a single JFrame.
#Jesse Strickland posted a great answer, but the provided code is not able to access any nested elements (like in my case, inside JPanel).
After additional Googling I found this recursive method provided by #aioobe here.
By combining and slightly modifying the code of #Jesse Strickland and #aioobe I got a working code that can access all the nested elements, no matter how deep they are:
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
List<Component> components = getAllComponents(this);
for (Component comp : components) {
componentMap.put(comp.getName(), comp);
}
}
private List<Component> getAllComponents(final Container c) {
Component[] comps = c.getComponents();
List<Component> compList = new ArrayList<Component>();
for (Component comp : comps) {
compList.add(comp);
if (comp instanceof Container)
compList.addAll(getAllComponents((Container) comp));
}
return compList;
}
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
Usage of the code is exactly the same as in #Jesse Strickland code.
If your components are declared inside the same class you're manipulating them from, you simply access these components as attributes of the class name.
public class TheDigitalClock {
private static ClockLabel timeLable = new ClockLabel("timeH");
private static ClockLabel timeLable2 = new ClockLabel("timeM");
private static ClockLabel timeLable3 = new ClockLabel("timeAP");
...
...
...
public void actionPerformed(ActionEvent e)
{
...
...
...
//set all components transparent
TheDigitalClock.timeLable.setBorder(null);
TheDigitalClock.timeLable.setOpaque(false);
TheDigitalClock.timeLable.repaint();
...
...
...
}
...
...
...
}
And, you may be able to access class components as attributes of the class name from other classes in the same namespace too. I can access protected attributes(class member variables), maybe you can access public components, too. Try it!
Swing does provide other ways to implement this, for the sake as exercising here is my version that implements a find in Component hierarchy context.
/**
* Description : Find a component having the given name in container desccendants hierarchy
* Assumptions : First component with the given name is returned
* #return java.awt.Component
* #param component java.awt.Component
* #param componentName java.lang.String
*/
public static Component findComponentByName(Component component, String componentName) {
if (component == null ) {
return null;
}
if (component.getName() != null && component.getName().equalsIgnoreCase(componentName)) {
return component;
}
if ( (component instanceof Container ) ) {
Component[] children = ((Container) component).getComponents();
for ( int i=0; i<children.length; i++ ) {
Component child = children[i];
Component found = findComponentByName( child, componentName );
if (found != null ) {
return found;
}
}
}
return null;
}

Create GUI components with states

I was asking about the right way to make a component that holds some state. Like a Jbutton that saves a color in it, or a list item that saves a certain object. So when those GUI components fire an event I can use the saved states to do something with it.
My way was like that:
1- Make a subclass of the required component, like a subclass from Jbutton.
2- Make a Listener for this new subclass : in the listener check if the event source is the subclass, convert it then use the stored data.
Example:
class ColorButton extends JButton
{
static class Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent actionEvent) {
Object source = actionEvent.getSource();
if( source.getClass() == ColorButton.class)
{
ColorButton t = (ColorButton) source;
t.getComponent().setBackground(t.getColor());
}
}
}
//states i want to be saved
private Color c;
private Component comp;
ColorButton(Component comp, Color c) {
setColorChanger(comp, c);
}
/* ......
......
rest of constructors added with those additions
......
*/
private void setColorChanger(Component comp, Color c)
{
this.comp = comp;
this.c = c;
}
Color getColor() {
return c;
}
Component getComponent() {
return comp;
}
}
And I use it this way:
JPanel panel = new JPanel();
ColorButton.Listener l = new ColorButton.Listener();
JButton b = new ColorButton("Blue", panel, Color.BLUE);
JButton r = new ColorButton("Red", panel, Color.RED);
r.addActionListener(l);
b.addActionListener(l);
panel.add(b);
panel.add(r);
add(panel);
So I was wondering if this way is okay or what, I feel it is very boring to make this for every component that should hold a certain states, is there a better way?
Yes, there is a better way. Every single component object should have its own separate ActionListener, so that you don't have to check if( source.getClass() == ColorButton.class), and you can directly access the fields of the component by name, without having to go through the source at all. For that to work, you have to use a non-static inner class, or an anonymous inner class. That if statement is a very old-fashioned and non-OOP way of doing things.
In fact, the component object itself can be its own ActionListener - but that style only allows you to have one ActionListener, and is a bit less well-organised.
The better way is dependent on what kind of state you want to hold and what use you want to make of it. Without thinking that through so that you can state it, it isn't possible to make an overall plan for a better way to do it. Is setting color the only thing you want to do? Do you need to mix regular JButtons with ColorButtons in your application?

how to retrieve the value of a component of a panel in java

i have jdialog. and i have added 50 buttons inside a jpanel in the jdialog.
Now i want to get the values of the buttons which is set by button.setText()
now my code looks like this
Component[] all_comp=mydialog.getComponents();
for(int i=0;i<=all_comp.length;i++)
{
Container ct=all_comp[i].getParent();
String panel_name=ct.getName();
}
i tried my best to find out all possible ways like taking all other functions of the component class.
but no result.
now i want to get the value of the buttons.(like button.getText).
how to do that??
You have to check whether current component is a button. If it is, cast it to button and call its getText():
Component[] all_comp=mydialog.getComponents();
for(int i=0;i<=all_comp.length;i++) {
if (all_comp[i] instanceof Button) {
String text = ((Button)all_comp[i]).getText();
// this is the text. Do what you want with it....
}
}
What you really want to do is pass mydialog into a method that will find all of the JButtons that are contained in it. Here is a method where if you pass in a Container (JDialog is a Container) and a List it will fill up the List with all of the JButtons the JDialog contains regardless of how you added the JButtons.
private void getJButtons(Container container, List<JButton> buttons) {
if (container instanceof JButton) {
buttons.add((JButton) container);
} else {
for (Component component: container.getComponents()) {
if (component instanceof Container) {
getJButtons((Container) component, buttons);
}
}
}
}
Basically this method looks to see if the Container passed in is a JButton. If it is then it adds it to the List. If it isn't then it looks at all the children of the Container and recursively calls getJButtons with the Container. This will search the entire tree of UI components and fill up the List with all JButtons it finds.
This is kind of ugly to have to create a List and pass it into the getButtons method so we will create a wrapper method that looks nicer
public List<JButton> getJButtons(Container container) {
List<JButton> buttons = new ArrayList<JButton>();
getJButtons(container, buttons);
return buttons;
}
This convenience method simply creates your List for you, passes it to our recursive method and then returns the List.
Now that we have the recursive method and the convenience method we can call the convenience method to get a list of all of our JButtons. After that we just loop over the items in the list and call getText() or whatever else you want to do with your buttons:
for (JButton button: getJButtons(mydialog)) {
String text = button.getText();
...
}

Get a Swing component by name

I have in a JFrame some components that I want
to refer into another JFrame and I want
to get them by name and not
do public get/set methods for each.
Is there a way from Swing to get a component reference by its name like do
c#?
e.g. form.Controls["text"]
Thanks
I know this is an old question, but I found myself asking it just now. I wanted an easy way to get components by name so I didn't have to write some convoluted code each time to access different components. For example, having a JButton access the text in a text field or a selection in a List.
The easiest solution is to make all of the component variables be class variables so that you can access them anywhere. However, not everyone wants to do that, and some (like myself) are using GUI Editors that don't generate the components as class variables.
My solution is simple, I'd like to think, and doesn't really violate any programming standards, as far as I know (referencing what fortran was getting at). It allows for an easy and straightforward way to access components by name.
Create a Map class variable. You'll need to import HashMap at the
very least. I named mine componentMap for simplicity.
private HashMap componentMap;
Add all of your components to the frame as normal.
initialize() {
//add your components and be sure
//to name them.
...
//after adding all the components,
//call this method we're about to create.
createComponentMap();
}
Define the following two methods in your class. You'll need to import Component if you haven't already:
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
Component[] components = yourForm.getContentPane().getComponents();
for (int i=0; i < components.length; i++) {
componentMap.put(components[i].getName(), components[i]);
}
}
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
Now you've got a HashMap that maps all the currently existing components in your frame/content pane/panel/etc to their respective names.
To now access these components, it is as simple as a call to getComponentByName(String name). If a component with that name exists, it will return that component. If not, it returns null. It is your responsibility to cast the component to the proper type. I suggest using instanceof to be sure.
If you plan on adding, removing, or renaming components at any point during runtime, I would consider adding methods that modify the HashMap according to your changes.
Each Component can have a name, accessed via getName() and setName(), but you'll have to write your own lookup function.
getComponentByName(frame, name)
IF you're using NetBeans or another IDE that by default creates private variables (fields) to hold all of your AWT/Swing components, then the following code may work for you. Use as follows:
// get a button (or other component) by name
JButton button = Awt1.getComponentByName(someOtherFrame, "jButton1");
// do something useful with it (like toggle it's enabled state)
button.setEnabled(!button.isEnabled());
Here's the code to make the above possible...
import java.awt.Component;
import java.awt.Window;
import java.lang.reflect.Field;
/**
* additional utilities for working with AWT/Swing.
* this is a single method for demo purposes.
* recommended to be combined into a single class
* module with other similar methods,
* e.g. MySwingUtilities
*
* #author http://javajon.blogspot.com/2013/07/java-awtswing-getcomponentbynamewindow.html
*/
public class Awt1 {
/**
* attempts to retrieve a component from a JFrame or JDialog using the name
* of the private variable that NetBeans (or other IDE) created to refer to
* it in code.
* #param <T> Generics allow easier casting from the calling side.
* #param window JFrame or JDialog containing component
* #param name name of the private field variable, case sensitive
* #return null if no match, otherwise a component.
*/
#SuppressWarnings("unchecked")
static public <T extends Component> T getComponentByName(Window window, String name) {
// loop through all of the class fields on that form
for (Field field : window.getClass().getDeclaredFields()) {
try {
// let us look at private fields, please
field.setAccessible(true);
// compare the variable name to the name passed in
if (name.equals(field.getName())) {
// get a potential match (assuming correct <T>ype)
final Object potentialMatch = field.get(window);
// cast and return the component
return (T) potentialMatch;
}
} catch (SecurityException | IllegalArgumentException
| IllegalAccessException ex) {
// ignore exceptions
}
}
// no match found
return null;
}
}
It uses reflection to look through the class fields to see if it can find a component that is referred to by a variable of the same name.
NOTE: The code above uses generics to cast the results to whatever type you are expecting, so in some cases you may have to be explicit about type casting. For example if myOverloadedMethod accepts both JButton and JTextField, you may need to explicitly define the overload you wish to call ...
myOverloadedMethod((JButton) Awt1.getComponentByName(someOtherFrame, "jButton1"));
And if you're not sure, you can get an Component and check it with instanceof...
// get a component and make sure it's a JButton before using it
Component component = Awt1.getComponentByName(someOtherFrame, "jButton1");
if (component instanceof JButton) {
JButton button = (JButton) component;
// do more stuff here with button
}
Hope this helps!
you could hold a reference to the first JFrame in the second JFrame and just loop through JFrame.getComponents(), checking the name of each element.
You can declare a variable as a public one then get the text or whatever operation you want and then you can access it in the other frame(if its in the same package) because it's public.
I needed to access elements inside several JPanels which were inside a single JFrame.
#Jesse Strickland posted a great answer, but the provided code is not able to access any nested elements (like in my case, inside JPanel).
After additional Googling I found this recursive method provided by #aioobe here.
By combining and slightly modifying the code of #Jesse Strickland and #aioobe I got a working code that can access all the nested elements, no matter how deep they are:
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
List<Component> components = getAllComponents(this);
for (Component comp : components) {
componentMap.put(comp.getName(), comp);
}
}
private List<Component> getAllComponents(final Container c) {
Component[] comps = c.getComponents();
List<Component> compList = new ArrayList<Component>();
for (Component comp : comps) {
compList.add(comp);
if (comp instanceof Container)
compList.addAll(getAllComponents((Container) comp));
}
return compList;
}
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
Usage of the code is exactly the same as in #Jesse Strickland code.
If your components are declared inside the same class you're manipulating them from, you simply access these components as attributes of the class name.
public class TheDigitalClock {
private static ClockLabel timeLable = new ClockLabel("timeH");
private static ClockLabel timeLable2 = new ClockLabel("timeM");
private static ClockLabel timeLable3 = new ClockLabel("timeAP");
...
...
...
public void actionPerformed(ActionEvent e)
{
...
...
...
//set all components transparent
TheDigitalClock.timeLable.setBorder(null);
TheDigitalClock.timeLable.setOpaque(false);
TheDigitalClock.timeLable.repaint();
...
...
...
}
...
...
...
}
And, you may be able to access class components as attributes of the class name from other classes in the same namespace too. I can access protected attributes(class member variables), maybe you can access public components, too. Try it!
Swing does provide other ways to implement this, for the sake as exercising here is my version that implements a find in Component hierarchy context.
/**
* Description : Find a component having the given name in container desccendants hierarchy
* Assumptions : First component with the given name is returned
* #return java.awt.Component
* #param component java.awt.Component
* #param componentName java.lang.String
*/
public static Component findComponentByName(Component component, String componentName) {
if (component == null ) {
return null;
}
if (component.getName() != null && component.getName().equalsIgnoreCase(componentName)) {
return component;
}
if ( (component instanceof Container ) ) {
Component[] children = ((Container) component).getComponents();
for ( int i=0; i<children.length; i++ ) {
Component child = children[i];
Component found = findComponentByName( child, componentName );
if (found != null ) {
return found;
}
}
}
return null;
}

Categories