I need to implement "paging" for my application's FlexTable widget:
Here is my initial code where it renders a Product into a 3 column cell:
public void renderProducts(Map<Long, Product> mp) {
int i = 0;
int j = 0;
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
Product product = (Product) pairs.getValue();
ProductWidget pw = productInstance.get();
pw.setTitle(product.getName());
pw.setImageUrl(product.getImageUrl());
pw.setContent(product.getInfo());
pw.setUrl(product.getUrl()); // "More" button anchor
List<String> feats = product.getFeatures();
for (String f : feats){
pw.addFeature(f);
}
flextable.setWidget(i, j, pw);
j++;
if (j == 3){
i++;
j = 0;
}
it.remove(); // avoids a ConcurrentModificationException
}
}
Need to do paging in N pages for this. My initial idea is to split the Map into a List of Map...
I mean, is there any "data source" for FlexTable?
If you really need to use the FlexTable and provide paging you had better do it using a cell table so older question. The simple pager implements all the functionality you want either way.
If you want to go with the FlexTable you have to provide with your own implementation of a pager. This can be done in varous ways, with next and previous button or Labels adding the on click handler and doing the iterations.
The map is also not the way to go as the items are not ordered in any way. I would add all the items to a List and use said list as my data source.
You also need a way to save the current page and the items/page ( maybe a static variable if you want it saved even after the page has changed )
Related
I have an ArrayList which holds employee record details from data inputted into JTextFields. I have displayed this with a showMessageDialog box to confirm that they are being added to the list correctly.
The employees are created and added to the list correctly but how do I cycle through the ArrayList one record at a time and have the information displayed in the JTextFields?
Edited as below:
I don't think I have asked the question properly. I have a button that enables me to show the contents of the first element of my array list to the GUI. See below:
nField.setText(nameList.get(0).getName());
bField.setText(nameList.get(0).getBirth());
jField.setText(nameList.get(0).getID());
What I need is something to show the next element.
I have a list iterator that I am trying to use but I simply can’t get it to work.
I have tried this but it results in the last element being shown:
for (int i = 0; i < nameList.size(); i++) {
nameList.get(i);
nField.setText(nameList.get(i).getName());
bField.setText(nameList.get(i).getBirth());
jfield.setText(nameList.get(i).getID()); }
There are different options, but the short of it is, you'll have to tie your employee record to the JTextField somehow. One way to do this is by creating a simple object to hold the relation:
public class EmployeeRecordToJTextfield {
private EmployeeRecord employeeRecord;
private JTextField jTextField;
public EmployeeRecordToJTextfield(EmployeeRecord employeeRecord, JTextField jTextField) {
this.employeeRecord = employeeRecord;
this.jTextField = jTextField;
}
public EmployeeRecord getEmployeeRecord() {
return employeeRecord;
}
public JTextField getJTextField() {
return jTextField;
}
}
Instead of the EmployeeRecord, you stick instances of this class in the list:
List<EmployeeRecordToJTextfield> list = new ArrayList<>();
list.add(new EmployeeRecordToJTextfield(employeeRecord, jTextField));
When you iterate over this list, you can transfer the data you choose:
for (EmployeeRecordToJTextfield e : list) {
JTextField textField = e.getJTextField();
EmployeeRecord record = e.getEmployeeRecord();
textField.setText(record.getName());
}
Another option, maybe simpler, is by converting your list to a map and map EmployeeRecords to their JTextField.
Update based on the Question update
I hope I now understand what you're asking, but if so, I'd just do this:
Store the index of the 'current' shown item in a variable or hidden GUI field.
private int currentIndex = 0; // Start with the first item.
When you want to show the next item (perhaps through a Next or Previous button), get the next value. Compensate for list length:
int nextIndex = currentIndex+1;
if (nextIndex >= nameList.size()) nextIndex = 0;
if (nextIndex < 0) nextIndex = nameList.size()-1;
Now you can use nextIndex to fetch the correct entry from your list:
nField.setText(nameList.get(nextIndex).getName());
bField.setText(nameList.get(nextIndex).getBirth());
jfield.setText(nameList.get(nextIndex).getID());
And don't forget to update the currentIndex:
this.currentIndex = nextIndex;
Use for loop:
for(JTextField a : your_list){
do_something();
}
I have a JSP that has a list of DVDs and want to send list of the selected (checkboxes) to a second page for processing. In the second page I have used :
String selected[] = request.getParameterValues("checkboxGroup");
to get the list of selected checkboxes. I would like to get either the key OR value (bse I am building a table) of the selected index. eg; if the user selected the first checkbox, -> I want to be able to access either Pirates or 299.
I converted a 2d array into a map as below thinking that if I am able to get the index of the map I would be able to access either the key or value as below:
String [ ][ ] myArray = {
{"Pirates", "299"},
{"Travellers", "145"},
{"Zoopy", "89"},
{"Farewell", "67"},
{"Junies", "98"},
{"WakUp", "55"},
{"Space", "100"},
{"Solar", "199"},
{"Strom", "200"},
{"Wind", "200"}
};
final Map<String, String> map = new HashMap<String, String>(myArray.length);
for (String[] mapping : myArray) {
map.put(mapping[0], mapping[1]);
}
I am however stuck and don't know where to go from here and would appreciate suggestions from those more experienced.
Maps don't have indexes, so you'll have to abandon that idea.
You need to use an indexed data structure, such as a List or an array. Perhaps a List of custom objects, containing the string and integer values would be appropriate?
The Key-/Value-/Entry-Sets of a map are (as you notice) sets, that means unordered lists. So you actually can parse them to lists with indexes, however the index of lements wont be consistent.
Finally..This is what I used instead;
TreeMap dvdstree = new TreeMap();
// Add some dvds.
dvdstree.put("Pirates", 5);dvdstree.put("Solar",124);
dvdstree.put("Travellers",145);dvdstree.put("Zoopy", 89);
dvdstree.put("Farewell", 67);
//Get a set of the entries
Set set = dvdstree.entrySet();
// Get an iterator
Iterator iterator = set.iterator();
//Used a count keep track of iteration -> compare with name of checkbox
int count = 0;
//Printing into html table
out.print("<table>");
//Gets the selected checkboxes from previous page
String selected[] = request.getParameterValues("checkboxGroup");
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
//used a count to keep a track of where I am in the List
count++;
for(int i=0; i<selected.length; i++){
if(count == Integer.parseInt(selected[i])){
out.print("<tr><td>"+ me.getKey()+ "<td>"+me.getValue()+"<td/></tr>");
//Used this to get value of checkbox so that I could perform arithmetic in my class
String value= (me.getValue()).toString();
double valueDouble = Double.parseDouble(value);
myBean.addPrice(test2);
}
}
}
out.print("<tr><td>Total</td><td>"+myBean.getTotal()+"</td>");
out.print("</table>");
I have two classes, Image and Channel.Image has an imageId and Channel has a channelId which uniquely identify an Image and Channel object.Some other attributes are also present.
Image class also has a channelId, using which I determine to which channel the image has been assigned to.
I have a two ArrayLists of Image and Channel respectively.
List<Image> imageList = getItemist("image");
List<Image> channelList = getItemList("channel");
Now, I would like to remove all those image objects from the image list which contain channelId which are present in the channel objects of the channelList.
As of now, I am iterating the two lists and then comparing the channelId, putting the Image objects in a TreeSet and finally returning a list.Can you please help me with a solution that is simpler or more efficient ?
This sounds like a good use-case for a ListIterator:
ListIterator iter = imageList.listIterator();
Image curr = null;
while (iter.hasNext){
curr = iter.next();
for (Image img : chanelList){
if (img.chanelId == curr.chanelId){ //assuming chanelId is a primitive
iter.remove(curr); //remove curr
break; //break from the for loop to go on to the next image in imageList
}
//implicit: else continue; (i.e. go on to check the next image in chanelList)
}
}
Note that this is an O(n^2) algorithm that won't scale well for large list sizes. There are ways to optimize it further (see #dasblinkenlight's comment, for one), but for purposes of conceptual clarity, I'll limit the scope of this answer to this.
Inserting n elements to a TreeSet requires O(n*log(n)) time. However you don't need the Set to be ordered. A HashSet should be faster in the average case (of course you can still be unlucky with the hash codes).
You can then modify the list based on the set:
HashSet<Integer> channelIds = new HashSet<>();
for (Image channel : channelList) {
channelIds.add(channel.channelId);
}
// following removal code is specialized for lists that
// allow random access, like ArrayList
final int size = imageList.size();
int j = 0;
for (int i = 0; i < size; i++) {
Image image = imageList.get(i);
if (!channelIds.contains(image.channelId)) {
imageList.set(j++, image);
}
}
if (j < size) {
imageList.subList(j, size).clear();
}
I have my method which sorts all the movies in the array (dArray) of class dvd. now i need to sort available movies (setAvailable == true) ONLY. the array is dynamically filled in by customers entering movies from the menu. my code currently searches through the array and sorts all movies from A to B but now i want it to search and sort only the movies whereby d.setAvailable(true)... Thanks for your help. much appreciated
here is the sorted list of all the movies in the array:
if(e.getSource() == sortMovBtn)
{
if(dArray[0]==null)
{
JOptionPane.showMessageDialog(null,"No movies, please enter\na movie from the main menu","Error",JOptionPane.ERROR_MESSAGE);
}
else
{
BtnPanel.setVisible(false);
imgPnl.setVisible(false);
btnBackDvd.setVisible(true);
txtAreaSortDvd.setVisible(true);
sortDvdPnl.setVisible(true);
Dvd tmp;
for (int i = 0; i < manyDvd; i++)
{
for (int j = 0; j < (manyDvd - 1 - i); j++)
{
if (dArray[j].getTitle().compareTo(dArray[j+1].getTitle()) > 0)
{
tmp = dArray[j];
dArray[j] = dArray[j+1];
dArray[j+1] = tmp;
}
}
}
a = "";
for (int k = 0; k <manyDvd /*dArray.length*/; k++)
a += (dArray[k]);
txtAreaSortDvd.setText(a);
txtAreaSortDvd.setVisible(true);
txtAreaSortDvd.setEditable(false);
//Set font of text area
txtAreaSortDvd.setFont(new Font("Arial", Font.BOLD, 12));
//Initialize JScrollPane
JScrollPane pane1 = new JScrollPane(txtAreaSortDvd);
//Enable user to use wheel on mouse to scroll
pane1.setWheelScrollingEnabled(true);
//Set the scrollbar to always show
pane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//Add ScrollPane to Panel
sortDvdPnl.add(pane1);
//Add panel to frame
add(sortDvdPnl);
}
}
First, you shouldn't have code to work with your model (data) mixed in with UI code.
Second, you should not be sorting the data on the UI thread. Do the work on a background worker thread.
Third, you should not be coding up the sort yourself, especially not like that. Your sort is O(n^2). There are good options for sorting in java.util.Arrays for arrays or java.util.Collections for the collection classes.
There are two basic ways to go about sorting just the items that meet a certain criterion. You could sort the entire data set with a custom Comparator, matching first by the criterion and second by the rest of your sort criteria. Then your results would be at the start of the data, and you would only show the results until the first item that does not meet the criterion.
This has the advantage that it uses no extra space beyond what is already required to store your data.
A cleaner way would be to make a copy of just that portion of the data that meets the criterion, and then sort that. It would also be much easier to work with if the data was in a List instead of an array, since you would not need make two passes over the data: one to find out how many items match the criterion, and one to filter out the matching items. (In between, you would allocate an array to hold them.)
Suppose your data was in a List. You could get the available movies like this:
public List<Movie> getAvailable(List<Movie> movies) {
List<Movie> avail = new ArrayList<Movie>();
for (Movie movie : movies) {
if (movie.isAvailable()) {
avail.add(movie);
}
}
return avail;
}
You could then sort these movies (in their natural sort order) like this:
List<Movie> availOnly = getAvailable(movies);
Collections.sort(availOnly);
P.S. In Java 8 you will be able to do something like:
Iterable<Movie> avail = movies.filter(Movie::isAvailable).sorted();
use comparator http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html
Vector<String> totalProducts = Products.getProductNames();
Vector<String> selectedProducts = Products.getSelectedProductNames();
The selectedProducts vector is a subvector of totalProducts (meaning that selectedProducts contains one, more or all of the elements from totalProducts). What I want is to combine these two vectors and make a single JList, which contains all the elements from totalProducts, and with the elements of selectedProducts already selected.
What I tried:
Vector<Integer> indices = new Vector<Integer>();
JList prdList = new JList(totalProducts);
for(int i = 0; i < totalProducts.size(); i++)
{
for(String name : selectedProducts)
{
if(totalProducts.contains(name)) indices.add(i);
}
}
Object [] objIndices = indices.toArray();
//... Cast from Object [] to int [] ....
prdList.setSelectedIndices(intIndices);
...but this selects all the elements in the final JList.
Previously I tried:
JList prdList = new JList(totalProducts);
for(String tName : totalProducts)
{
for(String sName : selectedProducts)
{
if(totalProducts.contains(sName)) prdList.setSelectedValue(sName, false);
}
}
...but this one selected only the last element from the selectedProducts.
Can you please help me to do it right?
Your attempt that selects all items does so because you're iterating over each item, and if any item from the selectedProducts list is in the total list, adds the iteration item's index to the final selection list. Try changing your loop to something like this:
for(int i = 0; i < totalProducts.size(); i++)
{
String name = totalProducts.get(i);
if(selectedProducts.contains(name)) indices.add(i);
}
in debugging your first attempt (which looks like it should work, what was the contents of your intIndices array? because that looks like it should work, presuming your array conversion works.
however, since selectedproducts is guaranteed to be less items than total, you might want to iterate over that instead?
List<Integer> indices = new ArrayList<Integer>(selectedProducts.size());
for(String name : selectedProducts)
{
int index = totalProducts.indexOf(name);
if (index != -1)
indices.add(index);
}
although, since indexOf is a linear search through a list, it probably doesn't make much of a difference either way.
as for your second attempt, the ListSelectionModel has methods for adding a selected index (addSelectionInterval(int index0, int index1))
, you're using the one that sets (overwrites) the selection.
see http://download.oracle.com/javase/6/docs/api/javax/swing/ListSelectionModel.html
aside: you might want to use List<> instead of Vector<>, as vector has a lot of unecessary synchronization overhead. Unless you need the synchronization....
edit fixed copy+paste of add(i) with add(index)