I'm using Java Swing (Eclipse) to create a GUI and want to be able to display a continuously changing list in a panel. In my code this is a LinkedList of Objects and it will automatically reorder and change without any need for user interaction. What are the options for displaying this kind of list in the GUI? Thanks
One option, which I personally have used, is to have a method on the object containing this list, which, when called, modifies the data in the list, and then calls updateUI() which causes the UI to update without any user interaction. In order to detect whenever this list's data changes (I'm assuming you're looking at something external to the program) I would poll using another thread. The method you'd have on the object containing the list would have to be synchronized of course.
I hope this helps...
A Swing JList can take 3 types of collections as input.
An Object array - public JList(Object[] listData)
A Vector - public JList(Vector listData)
A ListModel - public JList(ListModel model)
You're going to have to convert your LinkedList into one of these 3 collections.
My recommendation is the ListModel. You can use a DefaultListModel, extend the AbstractListModel, or write your own class using the ListModel interface.
It is a very popular task when designing UI. To achieve your goals you need to follow next principles
Update your data in list
Send notification to UI Thread for update UI, here is a link to good tutorial
When to much data updates you need to limit amount of UI updates to acceptable (1 per 100 mills or smth), otherwise UI will suffer
Related
I have two different and independent JFrame windows:
DataFrame
GraphFrame
The first one is for the user to manipulate, with the input of different values and patterns to display on a graph presented in 2). The 1) sends specific values to 2) (array with doubles) so that "GraphFrame" can create the graph.
I invoke the "main " method from GraphFrame in the "main" method of DataFrame so that they both run at the same time and are both visible during the whole process.
I want these frames to be completely independent, which means that the mission for 1) is to send values and the mission for 2) is to check when values are recieved and then create the graph.
I also prefer to keep most of the methods private, so that they can't be accessed from external sources.
My problem, is that I don't know which is the best way to implement this data exchange. What is the best way for Frame 2) keep "listening" for the values it needs to recieve?
Should I create getters/setters on 2) and with the help of an Observer https://sourcemaking.com/design_patterns/observer ?
Or should I use threads?
Or even the creation of a traditional loop that keeps waiting for values, like:
while(array.isEmpty()) {
//stuck here
}
//create the graph from the values in array
At the moment I am receiving the values in 2) from setter methods, but I am uncapable, so far, of performing the code I desire only after I get the values.
What do you think is the best way to implement this?
P.S.: Should I consider not invoking GraphFrame main from DataFrame and run these 2 separately?
From what I understood, you're trying to run both JFrames in the same application. Conceptually this is rather one UI split into two windows than running two Frames as you put it.
Swing requires all UI elements to be updated by one thread - the AWT-Thread. Also interaction with the UI will run in the AWT-Thread. You need to take this into account.
Also it is best practice to separate data model and view. To solve your problem you could create a model for the GraphFrame that is manipulated by changes on the DataFrame. These changes could e.g. be picked up by a listener on the model that uses SwingUtils.invokeLater() to update the GraphFrame.
Of course there is a number of Issues you might need to care for additionally and depending on your requirements you might need to further decouple the two parts.
You could try having the GraphFrame initialize and then stop, but have a (static/nonstatic) method in GraphFrame that DataFrame can call to update the graph. Afterwards, repaint GraphFrame.
Is this what you're looking for?
I am relatively new in Java. In one of my project I have three jframes. They are Menuframe,that has list of menus; LoadDatafromExcelframe, that is use to select and read data from Excel file; and ShowDataFrame, that is use to display data that I read in LoadDatafromExcelframe. Actually its part of a big project. not the whole project! At the beginning of my project I am reading Excel file and load all the data in arraylist. Till this point I am good. Now I want to click the ShowDataFrame from the menulist to display the data that I have read in the LoadDatafromExcelframe. If I can access the arraylist then I think I can move forward. My question is "How can I access arraylist from one jframe (ShowDataFrame) to another frame(LoadDatafromExcelframe)?"I am using Netbeans IDE.
private void jMenuItemShowDataActionPerformed(java.awt.event.ActionEvent evt) {
showDataFrame.setVisible(true);
}
The key issue has little to do with JFrames or Swing in fact, but is simply one of passing information from one object to another. The only way Swing gets involved is if you want to pass this information in response to an event of one sort or another.
The solution is usually one of simply giving your classes appropriate getter and setter methods, of separating out your "model", the logical portion of your program, from your "view", the GUI portion of your program, and of using some sort of listener or observer type interface (such as can be obtained via Swing event listeners) to notify one class when the other is ready to push or pull information.
More general recommendations:
Avoid making anything static that does not need to be static. That is a quick solution that usually causes more pain in the long run as it makes your code very hard to enhance later and to test.
Avoid using lots of JFrames. Most professional GUI's have but one master window, one "JFrame" if you will. Often it is better to swap views in this JFrame such as with a CardLayout or with tabbed panes if needed. Also information that needs to be obtained in another window in a modal fashion can be displayed in a modal dialog.
Get a good book on OOPs basics as it applies to Java programming, such as Bruce Eckel's "Thinking in Java".
And get a good book on use of design patterns with Java such as Head First Design Patterns. These two concepts are key to moving ahead in Java.
Avoid using code generation utilities such as NetBean's form creation utility as it shields you from learning Swing specifics, and hinders your ability to learn to create complex Swing GUI's. Sure, use these tools once your a Swing journeyman, but until then, use the Swing tutorials to learn the library and code by hand.
For more specific advice, you will need to provide more details and provide more code.
Edit 2
More advice based on your post:
In one of my project I have three jframes. They are Menuframe,that has list of menus; LoadDatafromExcelframe, that is use to select and read data from Excel file; and ShowDataFrame, that is use to display data that I read in LoadDatafromExcelframe.
This looks to be better implemented creating 3 JPanels and not 3 JFrames. Then you could display the JPanels as needed in a single JFrame using a CardLayout to help you swap them.
Actually its part of a big project. not the whole project! At the beginning of my project I am reading Excel file and load all the data in arraylist.
This ArrayList should not be "read into a JFrame" but rather the data belongs in a non-GUI class, one of your "model" classes to be exact. Then the view classes, your GUI code can ask the model for this data whenever necessary. Read up on Model-View-Control program design on this site to learn more about this useful pattern.
Till this point I am good. Now I want to click the ShowDataFrame from the menulist to display the data that I have read in the LoadDatafromExcelframe.
Here using MVC structure, one of your "view" classes, the one holding the "menulist" should notify the "control" class that your code needs the ArrayList data held by the "model" class. This could all be done by having the Control class hold references to both "model" and "view" and having the "view" class hold references to the control thus allowing communication between classes.
You can change your ArrayList in static an public in the properties of the object then just call the name of te class who contains de ArrayList and call the ArrayList and use it wherever you want.
Something like this:
JFrame1.ArrayList1.add("some stuff");
Obviously doing this in the JFrame2 class where you want to call the ArrayList
I am building an application which is basically just a GUI for displaying and editing one single object. Since the class for this object was created with JAXB, it is basically a tree with many Strings and integers as children, but there are also some List<E>s. For each simple child JAXB provides a getter and a setter, but for all lists only a getter is provided, since it gives a reference to the internal list, which can now be modified.
Since I need to display every child (and branch for that matter) in a separate swing GUI component, I need these views to handle some data. According to my current knowledge about the model view controller design pattern, I should strictly separate the model from the view. Following this, it would be a bad idea to let a JList operate directly on an internal list of my base object. (Actually doing so would be a pretty easy solution to my specific use case, but since additional functionality might be added later on, I think I should refrain from this idea.)
Then I started thinking: If I do not let the components work on the list directly, I have to make them use a copy of the original. But since I cannot set the original list to a new one returned by my GUI component, I have to copy the items another time when saving the view data to my model. Also, it would not be wise to hand out references to internal lists of a custom ListModel, which would mean, that depending on the depth of the GUI structure, the list may be copied additional times.
Since I also want my application to be efficient, this does also not seem like the correct approach. How do I build this "correctly"?
Summary:
The List<E> from the original object is a reference to an internal list of
the object.
The JList displaying the list should not get this reference,
hence it must copy the list.
Getting the list from the JListshould not yield in a
reference to the internal list either, hence it must be copied again.
Saving the list to the original object must copy the list a third
time, because the original object does not have a setter method for the list. (see
above for details)
Is my grasp on this correct? How do I build this properly and make it efficient?
P.S: Adding setter methods to the original class structure is not an option!
was created with JAXB, it is basically a tree with many Strings and
integers as children, but there are also some List<E>s. For each
simple child JAXB provides a getter and a setter, but for all lists
only a getter is provided, since it gives a reference to the internal
list, which can now be modified.
see
JTreeTable
JList (unmodifiable), better could be JTable (with / without JTableHeader) in JTree
All of the components suggested by #mKorbel provide some kind of selection listener that will allow you to loosely couple a selection in one panel to the selected item's display in another. FileBrowser illustrates a TreeSelectionListener; Outline can have a ListSelectionListener, shown here; etc.
Addendum: In this related example, DisplayPanel listens to an adjacent TableModel, which it can query to update a model in one of it's own components. Note that each model is loosely coupled to its respective view. Common notification mechanisms are mentioned here.
When I edit the quantity of an object in a list and the toString changes, how do I get the list to update with the new toString?
Example, when I change nodes in my JTree, I use nodeChanged(node) what do I do when I change a list item?
AbstractListModel#fireContentsChanged if you extend from AbstractListModel.
It is the same principle as for the JTree of your previous question. The AbstractListModel does not know when some internal property of your objects is changed. So when you make a change, you must call that particular method indicating the object is changed. The list model will fire the correct event which is received by the JList, which will update/repaint (whatever you want to call it).
Personally I prefer to create ListModels which are self-contained, e.g. if the objects you use fire events when they change the ListModel can listen for those changes and fire the appropriate events itself instead of having to call this method externally.
Edit
Just noticed that that particular method is protected, so you need to create the model as I suggested and you cannot call that method externally (which is a good thing)
List.updateUI() will do it, although I'm told this has some overhead.
I'm currently working on a ZK screen with a Listbox that contains groups. Since you can't (as far as I know) use DataBinder to set the model with a GroupsModel, I'm manually creating one and calling setModel. To configure the Listgroups and Listitems I need to create a ListitemRenderer, which I've done.
The problem is that whenever you open or close a group on the screen, it communicates with the server to set the group as being open, and calls the ListitemRenderer again for every visible row. This results in a laggy interface for the user.
Is it possible to get ZK to cache the contents of the Listgroups and Listitems on the client such that opening/closing groups will not talk to the server and doesn't render every row again? With this system, the contents of the rows will not change until the user performs another search, or if they drag/drop items.
Edit:
I ended up just building the Listgroups and Listitems myself and adding them with appendChild. No need for a model or renderer, so everything is done on the client meaning it's very snappy. It'd still be nice to know how it could be done with a model/renderer though.
I suggest you can use renderall() method.
e,g
myListbox.getItemRenderer().renderAll()
IMO, if your model contains a lot of data, this action will maybe slower than default action.