Dynamic Visible Row Count In JList - java

I have JList that grows in size along with the JFrame. I have the following code:
defaultListModel = new DefaultListModel<SData>();
for (String string: listOfStrings) {
defaultListModel.addElement(string);
}
jList = new JList<String>(defaultListModel);
jList.setCellRenderer(jListCellRenderer);
jList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent arg0) {
//codes to go
}
});
jList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
jList.setLayoutOrientation(JList.VERTICAL_WRAP);
scrollPane = new JScrollPane(jList);
If I set some value for setVisibleRowCount method, the row number becomes fixed and If I don't set value, default value of 8 comes to play. I want to have this value dynamically changing.

I just found that jList.setVisibleRowCount(0) makes it self adjustable, when resizing JList.

Echoing #kleopatras's comment, it's not clear what controls setVisibleRowCount(). This example grows the enclosing Window as rows are added, up to a predefined limit, then the scrollbar takes over. It might give you some ideas, or you can use it as the basis of your sscce as #Andrew suggests.
Addendum: If the size of JList will control the count, I'd start with half of the model's size(). Then add one visible row for every n added to the model, in a fixed ratio that is pinned to a predefined limit. To maintain a reliable count, you'll have to implement your own ListModel or override the mutators in DefaultListModel.

Related

Java SWT: Clear all items in a table before writing

How do I clear a table before writing all the rows? The data will be completely different every time I hit this code:
graphicsMemoryTable.setRedraw(false);
int count = 0;
for(int i=0; i<graphicsMemory.size() && count<1000; i+=8,count++)
{
TableItem item = new TableItem(graphicsMemoryTable, SWT.NONE);
item.setText(graphicsMemory.get(i).toString());
item.setText(1,graphicsMemory.get(i+1).toString());
item.setText(2,graphicsMemory.get(i+2).toString());
item.setText(3,graphicsMemory.get(i+3).toString());
item.setText(4,graphicsMemory.get(i+4).toString());
item.setText(5,graphicsMemory.get(i+5).toString());
item.setText(6,graphicsMemory.get(i+6).toString());
item.setText(7,graphicsMemory.get(i+7).toString());
}
graphicsMemoryTable.setRedraw(true);
EDIT:
For reference, calling removeAll() worked for me, calling clearAll did not
removeAll() method of Table will remove all elements in the table. Here is the javadoc;
public void removeAll()
Removes all of the items from the receiver.
You can use table.clearAll();
Clears all the items in the receiver. The text, icon and other
attributes of the items are set to their default values. If the table
was created with the SWT.VIRTUAL style, these attributes
are requested again as needed.

Setting Unselected Items in a JList table to setEnable(false)

I'm having difficulty changing unselected options in a JList table to set them to setEnable(false). The method that is receiving the values is an ActionListener button method that, once pressed, receives the selected values from the JList. Here is the method and the buildEnemySelectionPanel() method is creating the JList with the appropriate JPanel for later placement:
private String[] enemies = {"Goblin", "Skeleton"};
private void buildEnemySelectionPanel()
{
enemyPanel = new JPanel();
enemyListPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
enemyListPanel.setPreferredSize(new Dimension(180, 85));
enemyListPanel.setBackground(Color.WHITE);
enemyPanel.setLayout(new BoxLayout(enemyPanel, BoxLayout.Y_AXIS));
enemyList = new JList(enemies);
enemyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
enemyList.addListSelectionListener(new EnemyListListener());
enemyListPanel.add(enemyList);
enemyPanel.add(enemyListPanel);
}
public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("Select Enemy"))
{
indexEnemy = enemyList.getSelectedIndex();
indexEnemyWeapon = weaponList.getSelectedIndex();
/*
here is where I'm having problems
*/
}
}
So far I've tried to take all of the items from the JList and, matching them with the references from the original String[] list items that I sent to the JList, parsed the indexes and if they didn't match set to false. Unfortunately as you are all probably well aware, compilation errors came up as result due to the fact that the JList is not actually a list. Here is a sample of my for loop that I tried to use in my method above:
for(int x = 1; x < enemyList.length(); x++)
{
if (!(enemies[x] == indexEnemy))
{
enemyList[x].setEnable(false);
}
}
I've read the http://docs.oracle.com/javase/8/docs/api/ , (tried to link 'setEnable') among some examples but don't seem to be making the connection.
Ideally, what I wish to happen is that when the ActionEvent of my button is triggered, all non-selected options in my JList will be disabled. I understand that the end-user will still be able to change his/her mind and make a different selection. But I'd like to still receive some help on how I can set the non-selected items in my JList to false if they are not the indexEnemy from my method above.

Displaying selected items in one jlist to another in java

I am using 4 JLists that is an array,
JList jlst = new JList[4];
Then I am adding first list items from array of objects,
jlst[0].setListData(getObjAL());
Here the function getObjAL() function will give the array of objects.
I want to display selected item of first list(jlst[0]) into second list(jlst[1]).
For that I am writing the code,
jlstPrimitives[i].addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent listevt) {
Jlist objLstTemp = (Jlist) listevt.getSource();
jlst[1].setListData(objLstTemp.getSelectedValue()));
}
});
But it is not displaying in list[1].
Please any one help me...
I can think of a dozen things that might be going wrong, none of which would affect you. For better support in the future, post a runnable example that demonstrates your problem. Pasting code out of context doesn't help (alot).
From your code, getObjAL() seems to be returning a Object[] array (single dimension), yet when you select a value, you seem to be assuming that the selected value is actually an array, which I'm pretty sure it isn't.
JList#setListData is expected either a object array (Object[]) or Vector.
Try something like this instead.
jlstPrimitives[i].addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent listevt) {
Jlist objLstTemp = (Jlist) listevt.getSource();
jlst[1].setListData(new Object[]{objLstTemp.getSelectedValue()}));
}
});

Displaying large amount of data with JList?

I have a JList, wich must display more than 3000 items. I wish to have "visible" around 100 items in the list, and when you scroll and getting close to the end (or begining) of the "visible" items the next portion (around 50) must be loaded in the list. Is there any simple way of doing this?
The list is rendering only the visible part. So there is no overhead from this point of view. If you want lazy loading - use custom models.
From this page :
You can write your own class that extends AbstractListModel or AbstractTableModel so that you can provide the needed data when necessary. The following example shows the usage of AbstractTableModel.
no there are no simple way for that, you have to implements Pagination(s)
easiest job when is managed by Databases engine, most of then support paginations directly
in the Model, but I never seen workaround for XxxListModel, use JTable with one Colum instead, there are some good workaround for Pagination for JTable
I have a JList, wich must display more than 3000 items.
Huh. You make that sound like a big number. Here is a list holding (and displaying just fine), more than 30 thousand items.
import javax.swing.*;
class BigList {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int bigNumber = 30001;
String[] bigData = new String[bigNumber];
for (int ii=0; ii<bigNumber; ii++) {
bigData[ii] = "String " + (ii+1);
}
JList list = new JList(bigData);
list.setVisibleRowCount(5);
JOptionPane.showMessageDialog(null, new JScrollPane(list));
}
});
}
}

Preserve JTable selection across TableModel change

We're seeing JTable selection get cleared when we do a fireTableDataChanged() or fireTableRowsUpdated() from the TableModel.
Is this expected, or are we doing something wrong? I didn't see any property on the JTable (or other related classes) about clearing/preserving selection on model updates.
If this is default behavior, is there a good way to prevent this? Maybe some way to "lock" the selection before the update and unlock after?
The developer has been experimenting with saving the selection before the update and re-applying it. It's a little slow.
This is Java 1.4.2 on Windows XP, if that matters. We're limited to that version based on some vendor code we use.
You need to preserve the selection and then re-apply it.
First of all you will need to get a list of all the selected cells.
Then when you re-load the JTable with the new data you need to programmatically re-apply those same selections.
The other point I want to make is, if the number or rows or columns in your table are increasing or decreasing after each table model reload, then please don't bother preserving the selection.
The user could have selected row 2 column 1 having a value say "Duck", before model updation. But after model updation that same data can now occur in row 4 column 1, and your original cell row 2 column 1 could have new data such as "Pig". Now if you forcibly set the selection to what it was before the model updation, this may not be what the user wanted.
So programmatically selecting cells could be a double edged sword. Don't do it, if you are not sure.
You can automatically preserve a table's selection if the STRUCTURE of that table hasn't changed (i.e. if you haven't add/removed any columns/rows) as follows.
If you've written your own implementation of TableModel, you can simply override the fireTableDataChanged() method:
#Override
public void fireTableDataChanged() {
fireTableChanged(new TableModelEvent(this, //tableModel
0, //firstRow
getRowCount() - 1, //lastRow
TableModelEvent.ALL_COLUMNS, //column
TableModelEvent.UPDATE)); //changeType
}
and this should ensure that your selection is maintained provided that only the data and not the structure of the table has changed. The only difference between this, and what would be called if this method weren't overridden is that getRowCount() - 1 is passed for the lastRow argument instead of Integer.MAX_VALUE, the latter of which acts a signifier that not only has all the data in the table changed but that the number of rows may have as well.
I had the same issue in an application. In my case the model in the table was a list of objects, where the object properties where mapped to columns. In that case, when the list was modified, I retrieved the selected index and stored the object that was selected before updating the list. After the list is modified and before the table is updated, I would calculate the position of the selected object. If it was still present after the modification, then I would set the selection to the new index.
Just setting the selected index in the table after the modification will not work, because the object may change position in the list.
As a side note, I found that working with GlazedLists makes life much easier when dealing with tables.
This is default behavior. If you call fireTableDataChanged() the entire table is rebuild from scratch as you set entirely new model. In this case the selection is, naturally, lost. If you call fireTableRowsUpdated() the selection is also cleared in general cases. The only way is to remember selection and then set this. Unfortunately there is no guarantee that the selection will be still valid. Be careful if restoring selection.
for reference, as #Swapnonil Mukherjee stated, this did the trick with a table with selectable rows:
// preserve selection calling fireTableDataChanged()
final int[] sel = table.getSelectedRows();
fireTableDataChanged();
for (int i=0; i<sel.length; i++)
table.getSelectionModel().addSelectionInterval(sel[i], sel[i]);
If I recall correctly, saving selection and re-applying it is what we have done too...
I was facing same issue and when tried to search the reason I got this question but it seems a bug in Java SDK. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4276786
WORK AROUND
A temporary work-around is available. It should be removed once this bug is fixed as it's suitability has NOT been tested against fixed releases.
Use this subclass of JTable.
Note: This is for the MetalLookAndFeel. If using other look and feels, the inner FixedTableUI subclass will have to extend the TableUI subclass for that look and feel.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
public class FixedTable extends JTable {
private boolean isControlDownInDrag;
public FixedTable(TableModel model) {
super(model);
setUI(new FixedTableUI());
}
private class FixedTableUI extends BasicTableUI {
private MouseInputHandler handler = new MouseInputHandler() {
public void mouseDragged(MouseEvent e) {
if (e.isControlDown()) {
isControlDownInDrag = true;
}
super.mouseDragged(e);
}
public void mousePressed(MouseEvent e) {
isControlDownInDrag = false;
super.mousePressed(e);
}
public void mouseReleased(MouseEvent e) {
isControlDownInDrag = false;
super.mouseReleased(e);
}
};
protected MouseInputListener createMouseInputListener() {
return handler;
}
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if (isControlDownInDrag) {
ListSelectionModel rsm = getSelectionModel();
ListSelectionModel csm = getColumnModel().getSelectionModel();
int anchorRow = rsm.getAnchorSelectionIndex();
int anchorCol = csm.getAnchorSelectionIndex();
boolean anchorSelected = isCellSelected(anchorRow, anchorCol);
if (anchorSelected) {
rsm.addSelectionInterval(anchorRow, rowIndex);
csm.addSelectionInterval(anchorCol, columnIndex);
} else {
rsm.removeSelectionInterval(anchorRow, rowIndex);
csm.removeSelectionInterval(anchorCol, columnIndex);
}
if (getAutoscrolls()) {
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
if (cellRect != null) {
scrollRectToVisible(cellRect);
}
}
} else {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
}
}
Note Curtsey to http://bugs.sun.com

Categories