title: Java Elegantly access property passed to component, e.g. JComponent a & b use Font 1 Color 2. Access 1 & 2 dynamically, & show they used in a & b
body: <p>Summary: When Building JComponent you often declare property variables (fonts, colors, dimensions etc.). Many Components in a  GUI share the same format (e.g. sets of buttons, textfields). So you define a subclass of Font font. If you want to implement a groupwide change for every Component that only uses font, how do you go about this? My current solution is to create an ArrayList for every property and then add the Component which uses it. This is tedious.</p>
  
  <p>In other words I want to be able to dynamically identify my named variables used in building a component(i.e. the properties), so that I can implement changes throughout the programme.</p>
  
  <p>I have tried using the Java reflection utility but had problems with this method arise and are described later on.</p>
  
  <p>first things first: Lets define an example to show you what I am doing. Build a class, define some Components, define property variables, add the properties to the components.</p>
  
  <pre><code>import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.FlowLayout;
  import java.awt.Font;
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  
  import javax.swing.JButton;
  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  
  public class CLASSNAME{
  //First define all variables to be accessed within the class      //so they can be accessed within the whole class.
  
  JPanel panel;
  JButton button;
  JLabel label;
  
  String stringButton;
  String stringLabel;
  int[] setCol={125,125,125};
  Font font;
  Color color;
  Dimension dimension;
  Dimension dimension2;
  FlowLayout flowlayout;
  
  //Then build the UI class
  classUI extends JFrame{
  panel =new JPanel();
  button =new JButton();
  label =new JLabel();
  
  //Then define spec variables to pass into these components.
  
  stringButton="Button"; 
  stringLabel="Label";
  
  font =new Font("Arial",font.PLAIN,18);
  color =new Color(setCol[1],setCol[2],setCol[3]);
  dimension =new Dimension(150,150);
  dimension2=new Dimension(100,100);
  flowlayout =new FlowLayout();
  
  //Pass these spec variables into the components as required.
  
  panel.setLayout(flowlayout);
  panel.setPreferredSize(dimension);
  panel.setBackground(color);
  
  
  label.setFont(font);
  label.setText(stringLabel);
  label.setBackground(color);
  label.setPreferredSize(dimension2);
  
  button.setText(stringButton);
  button.setFont(font);
  button.setPreferredSize(dimension2);
  </code></pre>
  
  <p>Must predefine each variable ahead of time as the first input into the class to access all the components and component property  variables from anywhere within the class including in functions or  outside the class. (but see below answer by <a href="https://stackoverflow.com/users/13956/fd">fd</a>if you don't want to predefine each Component.)</p>
  
  <p>So specific example : to change property of JComponent, you need new instance of the property variable, and then need to repaint that component, and the panel if its visible.</p>
  
  <pre><code>font=new Font("Arial",font.PLAIN,12);
  //Camickr  correctly commented I had left these two lines out.    
  label.setFont(font);
  button.setFont(font);
  
  // I think this is redundant - namely when setting a property 
  // the component is repainted automatically.
  label.repaint();    
  button.repaint();
  
  /* does the panel the component is displayed on need a repaint()?
   * from what I can tell usually not.
   */
  </code></pre>
  
  <p>This is fine if you have 5 components, and you don't need changes.
  However if you start to have about 30 - 50 components in a GUI, and you want to implement a change... e.g. just change the fonts of the components which use font, you have a list of 50 components, so I want to dynamically access these.</p>
  
  <p>Therefore:
  1) I want to <em>dynamically</em> find all components by name and component type. 
  I have a part way solution using java.reflect.util</p>
  
  <p>2) I want to <em>dynamically</em> find which property (spec) variable was used when defining a component. java.reflect.util does not keep a record of which components pass which variable.</p>
  
  <p>There is a solution to the problem which is not <em>dynamic</em>: Declare an ArrayList for every spec, and manually add to it each time it is used.
  Example:
  //for each property used in a JComponent create an arraylist.
  //so for the example you should define the ArrayLists as follows</p>
  
  <pre><code>ArrayList&lt;Object&gt;     spec_stringButton=new ArrayList();
  ArrayList&lt;Object&gt;     spec_arraystringLabel=new ArrayList();
  ArrayList&lt;Object&gt;     spec_arrayfont =new ArrayList();
  ArrayList&lt;Object&gt;     spec_color =new ArrayList();
  ArrayList&lt;Object&gt;     spec_dimension =new ArrayList();
  ArrayList&lt;Object&gt;     spec_dimension2=new ArrayList();
  ArrayList&lt;Object&gt;     spec_flowlayout =new ArrayList();
  </code></pre>
  
  <p>and then :
  //manually add which components used each variable. This sucks.<br>
       spec_stringButton.add(button);</p>
  
  <pre><code> spec_arraystringLabel.add(label);
  
   spec_arrayfont.add(button);
   spec_arrayfont.add(label);
  
   spec_color.add(label);
   spec_color.add(panel);
  
   spec_dimension.add(panel);
  
   spec_dimension2.add(button);
   spec_dimension2.add(label);
  
   spec_flowlayout.add(panel);
  </code></pre>
  
  <p>This solution does work. But it is not an elegant solution. It is very labour intensive, you've got to remember to add each component that uses a property.</p>
  
  <p>Whenever you need to make a groupwide change you can do this easily enough :</p>
  
  <pre><code> //spec=new spec;
   dimension2=new Dimension(80,40);
  
   int i=0;
   for (i=0;i&lt;spec_dimension2.size();i++){
   JComponent a=(JComponent)spec_dimension2.get(i);
   //component.setSpec(new spec);
   a.setPreferredSize(dimension2);
  //component.repaint();
   a.repaint();
  //proof we have made the change.
   System.out.println(a.getPreferredSize());
   }
  </code></pre>
  
  <p>Is there no way to dynamically access which property variable was used by a component?</p>
  
  <p>What tools are available? After much searching the Java.lang. reflect utility comes to mind. </p>
  
  <p>From the tutorial:</p>
  
  <pre><code>//Field comes from java.lang.reflect.field
  try {
  int i=0;
  Class cls = Class.forName("CLASSNAME");
  
  Field fieldlist[] = cls.getDeclaredFields();
  for ( i= 0; i &lt; fieldlist.length; i++) {                       
      Field fld = fieldlist[i];
  
  
  
  System.out.println("    name = " + fld.getName());
  System.out.println("    decl class = " +fld.getDeclaringClass());
  System.out.println("    type= " + fld.getType());
  System.out.println("    declaredannotations="+fld.getDeclaredAnnotations());
  System.out.println("    generic type="+fld.getGenericType());
  System.out.println("    get type ="+fld.getType());
  System.out.println("    hashcode="+fld.hashCode());
  System.out.println("    to generic string="+fld.toGenericString());
  int mod = fld.getModifiers();
  System.out.println("    modifiers = " +Modifier.toString(mod));
                             System.out.println("    -----");
  }                      
  </code></pre>
  
  <p>I went to reflect utility and tried all the methods above. The println strings outputs the following and shows that you can dynamically gain access to declared variables in a class, including the class type (e.g. the component type):</p>
  
  <pre><code>name = panel
  decl class = class CLASSNAME
  type= class javax.swing.JPanel
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class javax.swing.JPanel
  get type =class javax.swing.JPanel
  hashcode=-1546142233
  to generic string=javax.swing.JPanel CLASSNAME.panel
  modifiers = 
  -----
  name = button
  decl class = class CLASSNAME
  type= class javax.swing.JButton
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class javax.swing.JButton
  get type =class javax.swing.JButton
  hashcode=141398225
  to generic string=javax.swing.JButton CLASSNAME.button
  modifiers = 
  -----
  name = label
  decl class = class CLASSNAME
  type= class javax.swing.JLabel
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class javax.swing.JLabel
  get type =class javax.swing.JLabel
  hashcode=-1550792425
  to generic string=javax.swing.JLabel CLASSNAME.label
  modifiers = 
  -----
  name = stringButton
  decl class = class CLASSNAME
  type= class java.lang.String
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.lang.String
  get type =class java.lang.String
  hashcode=1112659264
  to generic string=java.lang.String CLASSNAME.stringButton
  modifiers = 
  -----
  name = stringLabel
  decl class = class CLASSNAME
  type= class java.lang.String
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.lang.String
  get type =class java.lang.String
  hashcode=23733888
  to generic string=java.lang.String CLASSNAME.stringLabel
  modifiers = 
  -----
  name = font
  decl class = class CLASSNAME
  type= class java.awt.Font
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.awt.Font
  get type =class java.awt.Font
  hashcode=-1514161236
  to generic string=java.awt.Font CLASSNAME.font
  modifiers = 
  -----
  name = color
  decl class = class CLASSNAME
  type= class java.awt.Color
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.awt.Color
  get type =class java.awt.Color
  hashcode=-1607952256
  to generic string=java.awt.Color CLASSNAME.color
  modifiers = 
  -----
  name = dimension
  decl class = class CLASSNAME
  type= class java.awt.Dimension
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.awt.Dimension
  get type =class java.awt.Dimension
  hashcode=456448645
  to generic string=java.awt.Dimension CLASSNAME.dimension
  modifiers = 
  -----
  name = dimension2
  decl class = class CLASSNAME
  type= class java.awt.Dimension
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.awt.Dimension
  get type =class java.awt.Dimension
  hashcode=-1120040849
  to generic string=java.awt.Dimension CLASSNAME.dimension2
  modifiers = 
  -----
  name = flowlayout
  decl class = class CLASSNAME
  type= class java.awt.FlowLayout
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class java.awt.FlowLayout
  get type =class java.awt.FlowLayout
  hashcode=-466921925
  to generic string=java.awt.FlowLayout CLASSNAME.flowlayout
  modifiers = 
  -----
  name = setCol
  decl class = class CLASSNAME
  type= class [I
  declaredannotations=[Ljava.lang.annotation.Annotation;@15dfd77
  generic type=class [I
  get type =class [I
  hashcode=1871572573
  to generic string=int[] CLASSNAME.setCol
  modifiers = 
  -----
  </code></pre>
  
  <p>So here we have a dynamic method to access every declared variable be it a component or spec. (This feature does not exist in c++!)</p>
  
  <p>fld.getName() will list all declared variable names in a class.</p>
  
  <p>fld.getType() will provide the Component types and even the properties (font, color etc) we want but they need to be extracted.</p>
  
  <p>So it should be possible to dynamically extract / create a list of all Components, and all property variables.</p>
  
  <p>Great. But still no method to show which variable passed to which component. There does not seem to be a direct way of accessing the variable property name used. Bother.</p>
  
  <p>So... one solution: its possible to go through each components, and if it matches the current one (e.g. if Dimension is 100,100 then it must be variable dimension). But if you define two variables with same current parameters? It would be much more effective to be able to access variable name. So that's no good.</p>
  
  <p>Can Java show which property (what I have called spec variable) was used when defining a component? in plain English=if I defined Font font can I find components which use font.</p>
  
  <p>if not... can someone think of a way to dynamically add the variable to the  ArrayList without the manual schlep of "spec_stringButton.add(button)";</p>
  
  <p>The second problem is the Reflect utility in Java. The println string shows you can get access to each Component and what type it is, e.g. JPanel, JLabel, JButton etc. But how on earth do you use the string name and pass that into an object? </p>
  
  <p>QUESTION 2 to be answered: how do I change access Field and pass it into something I can use? I have managed to pass the Field into a String. But to get the Object name from a string to a component is producing problems.</p>
  
  <pre><code> // this String objectname works.
  
  String type= fld.getType().getName();
  </code></pre>
  
  <p>The output of this string should allow you to access and limit your search to JComponent types.</p>
  
  <p>However getting access to the object and then casting it to a JComponent object from the String name was a fumble.</p>
  
  <p>first:</p>
  
  <pre><code>  String name=fld.getName(); 
  </code></pre>
  
  <p>name gives you your component names.</p>
  
  <p>Using arraylist method </p>
  
  <pre><code>ArrayList&lt;Object&gt; a=new ArrayList();
  a.add(name);
  JComponent b=(JComponent)a.get(0);
  </code></pre>
  
  <p>This produces the following beautiful error:
      java.lang.ClassCastException: java.lang.String cannot be cast to<br>
       javax.swing.JComponent</p>
  
  <p>I am struggling to convert the output of the String variable name and cast it into object. Advice please. </p>
  
  <p>So Ideally Elegant solution would be able to say something like:  </p>
  
  <p>variable spec =new spec.  </p>
  
  <p>1) for every use of variable property get the component name and type.<br>
  (I know  this is backwards type of logic).</p>
  
  <p>2) using component type, reset variable spec appropriately 
  e.g. component.setSpec(new spec);</p>
  
  <pre><code>(e.g. for a font TitledBorder would have to be setTitleFont(),
  otherwise setFont();)
  </code></pre>
  
  <p>3) component.repaint();  </p>
  
  <p>Other potential solutions might be try to dynamically add the spec as an arraylist. Has anyone written a class which can track the variable names used to add properties to all components? If not could someone work on a solution. </p>
  
  <p>I am currently trying addPropertyListener to each Component. This triggers an event when you change a property (but not a Layout). Perhaps it might be possible to identify the variable used (the spec) and use the fact that a property change has been registered to dynamically add to the ArrayList solution.</p>
  
  <p>For convenience: the code I have written here is complete in one section. 
  Please use to make changes to implement your solution. Or to play around with an example.</p>
  
  <pre><code>import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.FlowLayout;
  import java.awt.Font;
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  import java.util.ArrayList;
  
  import javax.swing.JButton;
  import javax.swing.JComponent;
  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  
  
   class CLASSNAME extends JFrame{
  JPanel panel;
  JButton button;
  JLabel label;
  
  String stringButton;
  String stringLabel;
  
  Font font;
  Color color;
  Color color2;
  Dimension dimension;
  Dimension dimension2;
  FlowLayout flowlayout;
  
  int[] setCol={125,125,125};
  int[] setCol2={100,100,100};
  
  public CLASSNAME(){
  panel =new JPanel();
  button =new JButton();
  label =new JLabel();
  
  stringButton="Button";
  stringLabel="Label";
  font =new Font("Arial",font.PLAIN,18);
  color =new Color(setCol[0],setCol[1],setCol[2]);
  color2=new Color(setCol2[0],setCol2[1],setCol2[2]);
  
  dimension =new Dimension(150,150);
  dimension2=new Dimension(150,150);
  flowlayout =new FlowLayout();
  
  
  
  panel.setLayout(flowlayout);
  panel.setPreferredSize(dimension);
  panel.setBackground(color);
  
  label.setFont(font);
  label.setText(stringLabel);
  label.setBackground(color2);
  
  button.setText(stringButton);
  button.setFont(font);
  
  /* This is the reflect utility. Allows you dynamic access to the list of  
   * components in a class.
   */
  
  try {
  int i=0;
  Class cls = Class.forName("CLASSNAME");
  
  Field fieldlist[] = cls.getDeclaredFields();
  for ( i= 0; i &lt; fieldlist.length; i++) {                       
      Field fld = fieldlist[i];
  try{               
  String objectname= fld.getType().getName();
  Object a=objectname;                    
  System.out.println("preferredsize="+((JComponent) a).getPreferredSize());
  }catch(Exception e){}
  System.out.println("    name = " + fld.getName());
  System.out.println("    decl class = " +fld.getDeclaringClass());
  System.out.println("    type= " + fld.getType());
  System.out.println(" declaredannotations="+fld.getDeclaredAnnotations());
  System.out.println("    generic type="+fld.getGenericType());
  System.out.println("    get type ="+fld.getType());
  System.out.println("    hashcode="+fld.hashCode());
  System.out.println("    to generic string="+fld.toGenericString());
  int mod = fld.getModifiers();
  System.out.println("    modifiers = " +Modifier.toString(mod));
         System.out.println("    -----");
  
  }
  }catch (Throwable a) {System.err.println(a);}
  
  //This is my current solution. Create an array list for each property,
  // and add to it every time you add a property to a Component.
  
  ArrayList&lt;Object&gt;     spec_stringButton=new ArrayList();
  ArrayList&lt;Object&gt;     spec_arraystringLabel=new ArrayList();
  ArrayList&lt;Object&gt;     spec_arrayfont =new ArrayList();
  ArrayList&lt;Object&gt;     spec_color =new ArrayList();
  ArrayList&lt;Object&gt;     spec_dimension =new ArrayList();
  ArrayList&lt;Object&gt;     spec_dimension2=new ArrayList();
  ArrayList&lt;Object&gt;     spec_flowlayout =new ArrayList();
  
   //and then:
  
   spec_stringButton.add(button);
  
   spec_arraystringLabel.add(label);
  
   spec_arrayfont.add(button);
   spec_arrayfont.add(label);
  
   spec_color.add(label);
   spec_color.add(panel);
  
   spec_dimension.add(panel);
  
   spec_dimension2.add(button);
   spec_dimension2.add(label);
  
   spec_flowlayout.add(panel);
  
  
  //so then whenever you need to make a groupwide change you can do 
  //this with just 7 lines:
  
  
   dimension2=new Dimension(80,40);
   int i=0;
   for (i=0;i&lt;spec_dimension2.size();i++){
   JComponent a=(JComponent)spec_dimension2.get(i);
   a.setPreferredSize(dimension2);
   a.repaint();
   //shows that the change has been implemented.
   System.out.println(a.getPreferredSize());
   }
  
  }
  }
  </code></pre>