Java Forum / GUI / February 2008
Confused about referencing info stored in a JFrame
jamestechinfo@yahoo.com - 12 Feb 2008 22:05 GMT I've tried to develop several JFrame programs in the past and it always drives me crazy because I can't figure out how to set Classes I've developed, which aren't Components, but are critical to storing information necessary for the program to operate, so that they can be seen by components inside the frame. I'm not very knowledgable about the structure and coding of Swing/AWT programs, but I understand the princepals of passing data between methods and classes, and it is very frustrating to me that I cannot find an easy way (or even a working way at this point) to reference the info with my program the way I need to.
To illustrate my question with a real example, I'm trying to write a program which allows employees at my job to easily receive products from deliveries by scanning the barcode on the product or putting in the supplier code on the invoice.
The program needs to be able to extract product info from the database (to match the scanned barcode and to give the receiver visual verification that the info in the system is correct), and it needs to be able to match the product with the vendor, and thus the vendor codes, which go with the invoice.
I've connected my first draft/test program to the database using a class I call dbInfo. This class stores the connection information specific to our database, and also acts as a container/manager for other classes which populate arraylists such as VendorList, BrandList, and lists for any other info which is tied to a primary key in the database and might change during the use of the program (this way in the info in the form can be refreshed by simply using one dbInfo method).
My dbInfo class populates all its info into the appropriate lists correctly. I cannot, however, get my components to see this info. For example, I have a VendorBox, which is a JComboBox that selects the vendor for the invoice.
My original vendorBox grabbed its vendor information directly from the database by storing its own JDBC info and generating the SQL statement itself. This worked fine, but is not very modular, I had to add code to every other component that dealt with this info which would to reference the specific VendorBox on that JFrame form. If I could get the components to see the dbInfo for the form, I could just store the reference to VendorBox as dbInfo.invoiceVendor and any other component could have easy access to it by simply knowing where dbInfo was.
Long explanations can be hard to read, so here's a basic diagram
------------------------------ JFrame
}Components
| }VendorBox ( a ComboBox which selects the | vendor to receive from ) }dbInfo (not a component) }VendorList ------------------------------ My Question: How to I get VendorBox to see VendorList (or dbInfo for that matter)? ------------------------------
*Note: I'm using Netbeans 5.5, which doesn't allow me to edit the component initialisation proccess inline. I think I might be able to do this using the properties window, but I haven't had any luck getting this to work*
What I've tried:
Just putting it in based on its name and location:
1) A direct reference - using a setdbInfo() method, which sets the dbInfo equal to JFrameName.dbInfoVariableName. Netbeans gives me a variable (or symbol or something of the like) not found.
2) The Netbeans property window - because I have setdbInfo() and getdbInfo() fields in my VendorBox class, Netbeans shows dbInfo in the property window. Trying to edit this property gives me a form which among other things says 'form connection mode' and has options like 'from property' and 'from method'. None of the options have any options to select within them, which I think is because i need to do something to set up the form connections, but I'm not sure and my own personal searches have not presented me with useful information.
At this point I thought I'd try to make a finddbInfo class, which would just find the dbInfo class by crawling its way out
3) Introspection - When I read the description of this I sighed relief, I thought it would show me the class that my VendorBox was inside, but as far as I can tell it only shows you the class inheritance information. I tried all the getxxx() commands netbeans offered for code completion, but all I got back was info from the classes my vendorBox was built on or null.
4) VendorBox.getParent() - combined with introspection, I used this to progress a Class from displaying info about my vendorBox to info about its containing panels, when I progressed to the outmost panel, however, instead of getting the JFrame info on the next entry, I got null.
At this point I cried, cut myself, and poured the rest of my drink out for my dead homies.
Please help me, I enjoy using Java because I can work with it quickly, but I feel like screaming sometimes because I can't pass a simple piece of info to a component. I've learned so much more than I needed to and wasted so much valuable time trying to do this and I know in my heart that there is an easy answer that will make me feel simultaneously stupid and relieved. I need that feeling like you wouldn't believe, and I'm sure there our other amateur programers out there who could benefit greatly by understanding why my methods don't work.
On that note, if you could even explain why solutions like 1) or 4) don't work, I think a lot of people could benefit from that info.
Jeff Higgins - 13 Feb 2008 00:56 GMT jamestechinfo wrote:
> ------------------------------ > JFrame [quoted text clipped - 9 lines] > that matter)? > ------------------------------ What would VendorBox.getModel().class return?
Jeff Higgins - 13 Feb 2008 02:22 GMT > jamestechinfo wrote: >> [quoted text clipped - 13 lines] >> > What would VendorBox.getModel().class return? Here are two simple code examples.
Using a Custom Data Model http://preview.tinyurl.com/2kskc9
Sharing the Data Model for a JComboBox and JList http://preview.tinyurl.com/2wqh86
Roedy Green - 13 Feb 2008 16:21 GMT >I've tried to develop several JFrame programs in the past and it >always drives me crazy because I can't figure out how to set Classes >I've developed, which aren't Components, but are critical to storing >information necessary for the program to operate, so that they can be >seen by components inside the frame. You normally extend JFrame. Then you can put all the data you want inside the frame either static or instance. You can write getters/setters for outsiders to access the data. --
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Daniel Pitts - 13 Feb 2008 22:44 GMT >> I've tried to develop several JFrame programs in the past and it >> always drives me crazy because I can't figure out how to set Classes [quoted text clipped - 5 lines] > inside the frame either static or instance. You can write > getters/setters for outsiders to access the data. While it is common to extends JFrame, I wouldn't say its normal. I prefer to create my own class and use new JFrame();
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Roedy Green - 14 Feb 2008 05:46 GMT On Wed, 13 Feb 2008 14:44:24 -0800, Daniel Pitts <newsgroup.spamfilter@virtualinfinity.net> wrote, quoted or indirectly quoted someone who said :
>While it is common to extends JFrame, I wouldn't say its normal. >I prefer to create my own class and use new JFrame(); What are the advantages of doing it that way? --
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Daniel Pitts - 14 Feb 2008 07:12 GMT > On Wed, 13 Feb 2008 14:44:24 -0800, Daniel Pitts > <newsgroup.spamfilter@virtualinfinity.net> wrote, quoted or indirectly [quoted text clipped - 9 lines] > The Java Glossary > http://mindprod.com Clarity. I'm not creating a new type of JFrame, just a differently configured JFrame. Extends is useful for polymorphism, it shouldn't be used for "simple code reuse".
Not to mention that it helps me separate out the JFrame configuration logic from the JFrame itself, a lot of that logic often could easily be applied to a different type of container (such as Applet or JInternalFrame). If I don't extends JFrame, I have a much more flexible system.
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
RedGrittyBrick - 14 Feb 2008 10:04 GMT >>> While it is common to extends JFrame, I wouldn't say its normal. >>> I prefer to create my own class and use new JFrame(); [quoted text clipped - 10 lines] > JInternalFrame). If I don't extends JFrame, I have a much more flexible > system. How do you deal with JPanels?
A while back I switched from extending JFrame to instantiating them in my own class. I still find it convenient to extend JPanel because I haven't worked out a convenient method for creating and using panels that doesn't involve extending JPanel - do you use a factory method?
frame.add(new FooPanelFactory().getJPanel()); // ?
Currently I'd have FooPanel extend JPanel and add methods like getFoo() and setFoo();
Could I just wrap a JPanel in a FooView class and transfer methods getJPanel() or getContainer(), getFoo() and setFoo() to class FooView?
Some days I wish Sun had a consistently promulgated clear set of best practises for Java/Swing that covered this, and more :-)
jamestechinfo@yahoo.com - 13 Feb 2008 21:24 GMT I'm so glad glad that I got some replies right away. I was a little worried no one would see it with all the cigarette kid spam I saw on the group when I posted (who comes up with this stuff). Thanks to both of you.
-------------------------
Jeff -
I don't have my laptop on me at the moment, but if I remember correctly, Netbeans said that getModel() returns the rendering model used to draw the object.
The examples you posted mad me happy, I thought from the begining the most intelligent way to do it had to be set the info during the constructor, but, like I said in my post, I've been using Netbeans, and it autogenerates the initialization of the components and overwrites any code you try to add to it. I haven't been able to find the place to insert the code via menus, but at least with this I know I need to start scouring the Netbean's help files and not trying to figure out what is wrong with my approach.
Thanks a million
---------------------
Roedy -
Even though I'm not sure your answer address my issue completely, I'm glad you posted, I read all the JDBC stuff on your page a month or so ago in preparation for this project (as well as some other stuff on your page). It really helped out. I didn't realize it was your site till I clicked the link, but its cool how things like that come full circle.
I planned to expand the program beyond receiving invoices, so I was going to make specific extensions of JFrame for different kinds of forms, but the dbInfo class is actually declared inside the JFrame and intialised in its constructor, so the method of calling the dbInfo's pointer from the component should be itdentical. My problem is that I can't figure out how to make a call which says (without putting the info in the constructor, because I can't figure out how to pass info to a components constructor in netbeans):
'call field 'x' from the JFrame which this component resides in'
If you've already addressed this on your site, or can come up with a working code example, I'd love to see it, and I'd really appreciate it.
------------ Side Notes - ------------ I guess the reason I can't use a sequence getParent() to see the JFrame is because JPanels are designed to work in both Applets and JFrames, which would require.
I'm wary to switch development tools, but maybe something else would make this much simpler, what do you guys use?
Jeff Higgins - 14 Feb 2008 00:10 GMT jamestechinfo wrote:
> Jeff - > > I don't have my laptop on me at the moment, but if I remember > correctly, Netbeans said that getModel() returns the rendering model > used to draw the object. getModel() called on a JComboBox , returns the (data) model for the JComboBox, (not) a rendering model.
See the ListModel interface; <http://java.sun.com/javase/6/docs/api/javax/swing/ListModel.html>, and its sub interfaces; ComboBoxModel, MutableComboBoxModel, and its known implementing classes: AbstractListModel, DefaultComboBoxModel, DefaultListModel.
For the rendering part, see; ListCellRenderer, <http://java.sun.com/javase/6/docs/api/javax/swing/ListCellRenderer.html> and ComboBoxEditor: <http://java.sun.com/javase/6/docs/api/javax/swing/ComboBoxEditor.html>
Other Swing components have similar data and rendering models.
Data models can listen to components for changes in their content, and components can listen to data models for changes in the data See Writing Event Listeners for details. <http://java.sun.com/docs/books/tutorial/uiswing/events/index.html>.
Please ignore <http://java.sun.com/docs/books/tutorial/uiswing/learn/index.html>, and start here: <http://java.sun.com/docs/books/tutorial/uiswing/index.html>.
> The examples you posted mad me happy, I thought from the begining the > most intelligent way to do it had to be set the info during the > constructor, but, like I said in my post, I've been using Netbeans, > and it autogenerates the initialization of the components and > overwrites any code you try to add to it. I haven't been able to find > the place to insert the code via menus, but at least with this I know
> I need to start scouring the Netbean's help files and not trying to > figure out what is wrong with my approach. Scouring these will help as well. <http://java.sun.com/javase/6/docs/api/> Maybe more.
Good luck
jamestechinfo@yahoo.com - 14 Feb 2008 19:35 GMT All this info makes since, and makes for a valid discussion on the best way to implement JFrames, ComboBox info, etc., but its not really the point of my post, which is 'referencing info stored in a JFrame'. I know I can get a little too wordy, but please read at least read this post in its entirety before responding so the information contained in the rest of the thread applies to the topic. Thats not to say I don't appreciate the responses/info, but I think that, especially with all the spam and a low activity rating on the group from google, that it is best if we do our best to keep a threads info tied to its title.
Whether they are extensions of JFrames or regular JFrames with additional info declared inside them, JFrames can definitely contain information which may need to be accessed or changed by components. The point of this thread is what are the options for doing this.
Example: You want to make a ComboBox which changes the window size to certain presets, maintained in the list.
As Jeff has illustrated with links to examples, the obvious way to do this is to ask for/pass the JFrame during the components constructor/ construction. This is the simplest answer I can think of, but it presents problems:
--------------------------- 1) My Netbeans problem:
In Netbeans, and thus likely in other IDE's, the part of the code which populates components into the JFrame is automatically generated, and thus, can not be edited in-line without the edits being overwritten during the next build/compile (probably before then, I'm not familiar with the specifics). This means you must use the IDE's property configuration tools, which can be less than self-explanatory, and, as is the case in netbeans, do not offer code completion, which can be an important productivity tool.
*Also of note is that when I attempt to make the JFrame and/or dbInfo part of the info received by the components constructor, Netbean's visual builder will not allow me to add the component to the form because it does not have all this info it needs to put it together, meaning I still have to figure out how to pass info to the constructor for the visual builder to work, even if the parameters are correct for configuring the component at runtime. Giving the component dummy data gets it into the builder, but trying to set its data from my JFrames main method leads to many entries in the ComboBox being null. This seems to be a concurrency issue, because if I put add enough function calls after the initComponents() method and before the setComboBoxInfo() it works out fine. This seems like a haphazard way of handling the situation though.
----------------------------
2) There may be legitimate reasons, beyond IDE implementation, to have the component find out what frame it is in on its own.
I.E. You want to code and distribute for others to use a JAVA component which is designed to work with the data from a given program 'x'. Giving the component the ability to find the frame simplifies the process other programmers will have to go through to configure it.
---------------------------
3) There should be more than one way to skin a cat.
Maybe I'm crazy, or just ahead of my time, or both...
but it seems to me that there has to be another reasonably simple way to do this. If the constructor method is the only safe way to do it, what are the bad ways and why. Does anyone here know how to ask:
'is this panel inside a JFrame or an Applet'
That seems like a darn good question to me.
--------------------------------
Perhaps the solution is to ask the EventQueue what thread is this component on and what is the JFrame that goes with that thread.
Jeff Higgins - 15 Feb 2008 04:02 GMT > All this info makes since, and makes for a valid discussion on the > best way to implement JFrames, ComboBox info, etc., but its not really > the point of my post, which is 'referencing info stored in a JFrame'. Lets note that for future reference. * Note The point of jamestechinfo's post is 'referencing info stored in a JFrame'.
> I know I can get a little too wordy, but please read at least read > this post in its entirety before responding so the information > contained in the rest of the thread applies to the topic. Ok
> Thats not > to say I don't appreciate the responses/info, but I think that, > especially with all the spam and a low activity rating on the group > from google, that it is best if we do our best to keep a threads info > tied to its title. You're welcome, and I agree.
> Whether they are extensions of JFrames or regular JFrames with > additional info declared inside them, JFrames can definitely contain > information which may need to be accessed or changed by components. Yes, JFrames can do that, but...
> The point of this thread is what are the options for doing this. * Note Topic clarification. What are the options for referencing info stored in a JFrame.
> Example: You want to make a ComboBox which changes the window size to > certain presets, maintained in the list. *Note Example shift from previous posts. Use the ComboBox DATA MODEL and the AWT EVENT API.
> As Jeff has illustrated with links to examples, the obvious way to do > this is to ask for/pass the JFrame during the components constructor/ > construction. This is the simplest answer I can think of, but it > presents problems: The examples I cited:
Using a Custom Data Model http://preview.tinyurl.com/2kskc9
A Class was defined: class ArrayListComboBoxModel extends AbstractListModel implements ComboBoxModel
It had a main method which instantiated a local Jframe object,the constructor for the JFrame was passed a String , "The title of the JFrame".
The constructor of the single JComboBox was passed a reference to an instance of an ArrayListComboBoxModel, that instance was a local to the main method of ArrayListComboBoxModel.
The example was intended to illustrate the use of the ListModel and ComboBox interfaces as pointed to in my previous post.
Sharing the Data Model for a JComboBox and JList http://preview.tinyurl.com/2wqh86
Ditto above.
> --------------------------- > 1) My Netbeans problem: Yes. <dragons> * Note Major topic shift.
> In Netbeans, and thus likely in other IDE's, the part of the code > which populates components into the JFrame is automatically generated, [quoted text clipped - 7 lines] > *Also of note is that when I attempt to make the JFrame and/or dbInfo > part of the info received by the components constructor, What component? A java.awt.Component?
According to the API6 Javadocs java.awt.Component has this constructor:
Component() Constructs a new component.
A javax.swing.JComboBox? According to the API6 Javadocs javax.swing.JComboBox has these constructors:
JComboBox() Creates a JComboBox with a default data model. JComboBox(ComboBoxModel aModel) Creates a JComboBox that takes its items from an existing ComboBoxModel. JComboBox(Object[] items) Creates a JComboBox that contains the elements in the specified array. JComboBox(Vector<?> items) Creates a JComboBox that contains the elements in the specified Vector.
> Netbean's > visual builder will not allow me to add the component to the form [quoted text clipped - 7 lines] > calls after the initComponents() method and before the > setComboBoxInfo() it works out fine.
> This seems like a haphazard way > of handling the situation though. Yes. Since neither of us knows wtf you just said.
> ---------------------------- > > 2) There may be legitimate reasons, beyond IDE implementation, to have > the component find out what frame it is in on its own. java.awt.Components have no need to know of their container. Look at the Application Programming Interface for java.awt.Component for details.
> I.E. You want to code and distribute for others to use a JAVA > component which is designed to work with the data from a given program > 'x'. Giving the component the ability to find the frame simplifies > the process other programmers will have to go through to configure it. Again, what component? If you're speaking of a java.awt.Component other programmers will probably ask wtf. Use a DATA MODEL and the AWT EVENT API.
Swing widgets mostly cache their data in some 'DATA MODEL' specific to the particular widget under discussion. They recieve notification of changes to the data and send notification of changes to their content through the AWT EVENT API. Your application will have its own DATA MODEL separate from the GUI wiget data models and may use the AWT EVENT API to communicate with the gui data models.
> --------------------------- > > 3) There should be more than one way to skin a cat. There are dozens. Some more effective, efficent, and less stinky than others.
> Maybe I'm crazy, or just ahead of my time, or both... > > but it seems to me that there has to be another reasonably simple way > to do this. Using a system of DATA MODELS and the AWT EVENT API.
> If the constructor method is the only safe way to do it, > what are the bad ways and why. The constructor method, whatever that is, for one.
> Does anyone here know how to ask: > 'is this panel inside a JFrame or an Applet' java.lang.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.JPanel
implements ImageObserver MenuContainer Serializable Accessible
Yes. <http://java.sun.com/javase/6/docs/api/javax/swing/JPanel.html>
> That seems like a darn good question to me. > > -------------------------------- > > Perhaps the solution is to ask the EventQueue what thread is this > component on and what is the JFrame that goes with that thread. Certainly worth a go. Your dead homies may wake with a hangover though.
Can you post here a sensible example making use of the extended features of the following extended JFrame, and extended JComboBox?
public class JFrameEx extends JFrame{
Set<Component> components = new LinkedHashSet<Component>();
JFrameEx() { super(); }
JFrameEx(String title) { super(title); }
public void addComponent (Component component) { components.add(component); }
public Set<Component> getComponentsEx() { return components; } }
public class JComboBoxEx extends JComboBox {
JFrame frame;
JComboBoxEx(JFrame frame) { this.frame = frame; } }
RedGrittyBrick - 15 Feb 2008 10:56 GMT > Does anyone here know how to ask: > > 'is this panel inside a JFrame or an Applet' > > That seems like a darn good question to me. It seems like an X-Y problem to me.
To use your example of a ComboBox of prespecified window sizes, the ComboBox shouldn't care about it's top-level container. Whatever class instantiates the ComboBox should wire it up to do the resizing.
Here's an SSCCE (use Google if you don't know about SSCCE)
---------------------------8<--------------------------------- import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.List;
import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities;
public class WindowSizer {
public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new WindowSizer(); } }); }
WindowSizer() {
final JFrame f = new JFrame("Window Sizer");
List<Dimension> sizes = new ArrayList<Dimension>(); sizes.add(new BoxableDimension(320,240)); sizes.add(new BoxableDimension(640,480)); sizes.add(new BoxableDimension(800,600));
JComboBox box = new JComboBox(sizes.toArray()); box.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { f.setSize((Dimension) e.getItem()); } }});
JPanel p = new JPanel(); p.add(box);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(p); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); }
/* * To make Dimension useful in a JComboBox we override toString() * to return the sort of String we want to see in the JComboBox. */ class BoxableDimension extends Dimension { BoxableDimension(int width, int height) { super(width, height); } public String toString() { return height + " x " + width; } }
} ---------------------------8<---------------------------------
RedGrittyBrick - 15 Feb 2008 11:21 GMT >> Does anyone here know how to ask: >> [quoted text clipped - 9 lines] > > Here's an SSCCE (use Google if you don't know about SSCCE) <snip>
Here's a revised SSCCE that may be closer to your intended usage:
---------------------------8<--------------------------------- import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.List;
import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities;
public class WindowSizer { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new WindowSizer(); } }); }
WindowSizer() {
JFrame f = new JFrame("Window Sizer");
List<Dimension> sizes = new ArrayList<Dimension>(); sizes.add(new BoxableDimension(320,240)); sizes.add(new BoxableDimension(640,480)); sizes.add(new BoxableDimension(800,600));
JPanel p = new JPanel(); p.add(new Resizer(f, sizes).getComboBox());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(p); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); }
/* * Separated out as a reusable component */ class Resizer { private JComboBox box; public Resizer(final JFrame f, List<Dimension> sizes) { box = new JComboBox(sizes.toArray()); box.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { f.setSize((Dimension) e.getItem()); } }}); } public JComboBox getComboBox() { return box; } }
/* * To make Dimension useful in a JComboBox we override toString() * to return the sort of String we want to see in the JComboBox. */ class BoxableDimension extends Dimension { BoxableDimension(int width, int height) { super(width, height); } public String toString() { return height + " x " + width; } }
}
---------------------------8<---------------------------------
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|