I am trying to add file names to my JList but without success. Here is the piece of the code:
DefaultListModel model = new DefaultListModel();
listLayer.setModel(model);
model.addElement(file.getName());
listLayer is a JList into which I would like to add file name. For information, I am writing my GUI application in netBeans so I can not create a new JList object within this code as it was already created automatically when added JList to my layout. Therefore I can just access it through its methods.
Thanks a lot,
Michal.
-------------------------------------------------------------------------
Ok I will try to extend it more:
private void openActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fileChooser = new JFileChooser("C:/");
FileFilter filter1 = new MyCustomFilter();
fileChooser.setFileFilter(filter1);
int returnVal = fileChooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
//String[] tokens = file.getName().split(".");
//String name = tokens[0];
DefaultListModel model = new DefaultListModel();
listLayer.setModel(model);
model.addElement(file.getName());
} else {
System.out.println("File access cancelled by user.");
}
}
and yes, my JList called listLayer is declared in non-modifiable section of the code like this:
private javax.swing.JList listLayer;
Thanks again for any help. Michal
Thanks for posting more code. Now quite possibly we can answer your question. A problem I see is that you're recreating a DefaultListModel each time the button is pressed and setting the JList with this new model effectively removing all data that was previously held by the list. A way to avoid doing this is to simply get the model that the JList already has, which should be a DefaultListModel, and add items to it. You will need to cast the object returned by getModel() since per the API, Java only knows this to be a ListModel object, and ListModel doesn't have the addElement(...) method that DefaultListModel does.
Something perhaps like so:
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
// note the cast since getModel() only returns a ListModel
DefaultListModel model = (DefaultListModel)listLayer.getModel(); // changed**
model.addElement(file.getName());
}
You recommend me to use not DefaultListModel, but ListModel?
I don't know enough about the rest of your program to say. If you have a single, relatively static JList, DefaultListModel may be perfect. If your program models a constantly changing selection of File instances, then you may want to implement ListModel or even a shared model, as shown here. The latter simply forwards some methods to the default implementation.
Related
how do i go do this, based on input in textfield, you get some results inside jlist, after you select option in jlist you then get an action, code examples would be appreciated... this is what i got so far:
final DefaultListModel<String> locations = new DefaultListModel<String>();
getTextFieldSearch().addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(int i=0;i<10;++i) {
locations.add(i, "blah");
}
}
});
JList<String> list_racentRaces = new JList<String>(locations);
Start by taking a look at How to Use Lists, which has lots of awesome code examples.
The basic idea would be to...
When your actionPerformed method is triggered, create a new DefaultListModel, assuming you don't have your own implementation, fill it with all the new items you need and apply it to the instance of list_racentRaces
If you want to maintain what was previously in the list, you should consider starting with a DefaultListModel and simply add the new items to it as you need to...
Then, attach a ListSelectionListener to list_racentRaces and when the valueChanged event is triggered, find the selected item(s) and do what ever you need to based on these result(s)
You can find more details and examples through How to Write a List Selection Listener
I have a JList, where it displays names according to the DB. Associated with these names are IDs. for eg., foodId = 1, foodName = Chinese.
If i click on an item on the JList, i need to capture the foodID associated with the clicked foodName. i know a variable is needed.
when i have that value, I can pass that value into another method to retrieve the relevant food items associated with that foodId. Assume that getters & setters are done.
I have only the following, & am stuck. Please advise thank you.
list_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
//alter text of Label acc to clicked item # JList
JList list = (JList)evt.getSource();
System.out.println (list.getSelectedValue());
//store int value of item clicked # JList
int temp = 0;
temp = ???????????
//populate JPanel
Food food = new Food();
JPanel panel = new JPanel();
panel.setBounds(153, 74, 281, 269);
panel.add(food.populateWithButtons());
contentPane.add(panel);
}
});
list_1.setBorder(new LineBorder(new Color(0, 0, 0), 0));
//populate JList
list_1.setModel(food.populateJList());
public ListModel populateJList()
{
DefaultListModel model = new DefaultListModel();
ResultSet rs = null;
DataAccessObject db = new DataAccessObject();
db.setUp("customer");
String dbQuery = "SELECT store_Owner_Id, food_Category FROM store_owner";
rs = db.readRequest(dbQuery);
try
{
while (rs.next())
{
food_Category = rs.getString("food_Category");
store_Owner_Id = rs.getInt("store_Owner_Id");
model.addElement(food_Category);
System.out.println (store_Owner_Id); //test DB conn & print retrieved items
System.out.println (food_Category);
}
}
catch (Exception e)
{
e.printStackTrace();
}
db.terminate();
return model;
}
Suggestions:
Don't populate the JList with Strings but rather ...
If you populate your JList with objects that contain both the name and the ID, then you're doing well.
You will likely want to give your JList a cell renderer that helps it to show the information from the object that you want the JList to display.
Then getting the ID is simply a matter of getting the selected item from the JList inside whatever listener you're using, casting it to the object type that in fact is, and then calling the getter method, such as getId(), assuming that objects of this type have this method, and then use your ID.
Note though that this tells us nothing useful:
list_1.setModel(food.populateJList());
If my suggestions don't help you answer your question, then please provide more useful information and code, information that will help us to fully understand your problem.
Edit 2
Your latest code shows that you're doing what I recommended that you not do:
while (rs.next())
{
food_Category = rs.getString("food_Category");
store_Owner_Id = rs.getInt("store_Owner_Id");
model.addElement(food_Category); // ****** here
System.out.println (store_Owner_Id);
System.out.println (food_Category);
}
You're adding Strings to your DefaultListModel, and by doing this you lose all the other information that the database gave you.
Again do not add Strings to this model. Create a class that has two or more fields, one for the category String, and one for the owner ID, that has getters, setters, and a constructor that allows you to pass this information into objects of the class, create objects of this class in your while loop above, and add these to the JList model. Then give your JList a custom renderer which is better than giving the custom object a toString() method for this purpose.
Create a custom class, say called FoodInfo
Declare the DefaultListModel as one that accepts objects of this type, DefaultListModel<FoodInfo>
Then add objects of this type to the model:
e.g.,
DefaultListModel<FoodInfo> model = new DefaultListModel<FoodInfo>();
// ... other code to get database info
while (rs.next()) {
String foodCat = rs.getString("food_Category");
int id = rs.getInt("store_Owner_Id");
FoodInfo foodInfo = new FoodInfo(foodCat, id);
model.addElement(foodInfo);
}
Edit 3
As has been noted in comment by #dic19, don't use a MouseListener on the JList but rather use a ListSelectionListener as described in the JList Tutorial.
See Combo Box With Hidden Data. It will show you how to use a custom object without the need for a custom renderer. I know the title is "Combo Box" but the concept is identical for a JList.
When you use a custom renderer you break the default functionality of JList since you will no longer be able to select items using the keyboard. A properly designed GUI should allow the use to use the mouse or keyboard to select an item.
I want to create a DND action from a JList to the OS. My solution for now is to use a TransferHandler. In the method createTransferable I create the Transferable with the files I want to copy. But now there is my Problem: in some cases I have to download the files from a FTP-Server before I can copy the files. The very heavy download operation runs in a JavaSwingWorker (hidden behind the statement d.download(tmpDir);). Now the system trys to copy files which are not downloaded already.
Now i need a mechanism that allows me to create the transferable after I have downloaded the files. Is there a solution for my problem? Please help me!
Thanks!
Here is my method:
public Transferable createTransferable(JComponent c) {
JList list = (JList) c; // we know it's a JList
List<PictureDecorator> selectedPictures = getSelectedValues(list.getModel());
Vector cpFiles = new Vector();
List<Picture> donePictures = new ArrayList<Picture>();
List<Picture> notDonePictures = new ArrayList<Picture>();
String tmpDir = System.getProperty("java.io.tmpdir");
for(PictureDecorator pd : selectedPictures){
if(pd.getPic().getStatus() == PictureStatus.DONE)
donePictures.add(pd.getPic());
else
notDonePictures.add(pd.getPic());
}
Downloader d = new Downloader(parent, loginInformation, sced, donePictures, order);
d.download(tmpDir);
for(Picture p : donePictures){
cpFiles.add(new File(tmpDir + File.separator + p.getPicture().getName()));
}
for(Picture p : notDonePictures) {
cpFiles.add(p.getPicture());
}
TransferableFile tf = new TransferableFile(cpFiles);
return tf;
}
I need something that initiates the drag procedure then I get the path where the drag goes and then I can download the pictures and copy it to the destination path.
EDIT: Or another formulation: How I can find out the drop destination when I drop into the operating system?
To start the drag you need either a TransferHandler on the JList or alternatively a DragSource in combination with a DragGestureListener. Below you can see an example for doing that with a JTextField:
final JTextField textField = new JTextField(50);
DragGestureListener dragListener = new DragGestureListener() {
#Override
public void dragGestureRecognized(DragGestureEvent dge) {
// how the drag cursor should look like
Cursor cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
// the component being dragged
JTextField tf = (JTextField) dge.getComponent();
// Here a Transferable is created directly for a single file name
dge.startDrag(cursor, new TransferableFile(tf.getText()));
}
};
final DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(textField, DnDConstants.ACTION_COPY, dragListener);
You can put the above code inside your window creation procedure.
Your resulting transferable (TransferableFile in your case) should support the DataFlavor.javaFileListFlavor and you should return a List of Files from the getTransferData(DataFlavor flavor) method.
I believe this is also the method where the downloading should take place because that's the last point under your control before JVM-OS take over.
Now regarding the SwingWorker problem you can wait inside the method until the download completes. Perhaps modify your Downloader class to expose a boolean flag so you would be able to do something like while (!downloader.isDone()) { Thread.sleep(millisToSleep) };
[Edit: I must admit I don't like the idea of keeping the EventDispath thread busy but if this solves your current problem perhaps you can investigate later a more elegant solution]
A little warning: Since you don't have access to the drop location you cannot know how many times the getTransferData will be called. It is better to take this into account and create a simple cache (a Map sounds reasonable) with the temp files you have downloaded so far. In case you find the file in the cache you return its corresponding temp file directly and don't download it again.
Hope that helps
This is my first attempt at a decent GUI for a Java app and I needed to use JLists with custom ListModels in order to represent certain structures.
//The 2 below structures implement the ListModel interface, using an internal
//ArrayList, in order to be used as
//a model for 2 different JLists in my GUI.
private PropertyList propertiesList = new PropertyList();
private SelectedProperties selProperties = new SelectedProperties();
//and these are the two JLists they are the models for
private javax.swing.JList Properties_JList;
private javax.swing.JList SelectedProperties_JList;
Here I populate my first JList via a stream:
private void OpenFile_MenuItemActionPerformed(java.awt.event.ActionEvent evt) {
final JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(null);
int returnVal = fc.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
this.Properties_JList.setModel(propertiesList);
this.propertiesList.AddFromFile(file);
} else {
//...
}
}
which happens to be working perfectly fine. I import a few entries by reading the file and they are all displayed as expected in a .toString() representation.
The problem is the second JList:
private void AddToSelected_JButtonActionPerformed(java.awt.event.ActionEvent evt) {
Property p = (Property) this.Properties_JList.getSelectedValue();
this.SelectedProperties_JList.setModel(selProperties);
this.selProperties.InsertProperty(p);
this.SelectedProperties_JList.revalidate();
}
Which appears to be displaying only the very first item I attempt to add to it through the above button event, and I have no idea why. I considered moving both .setModel(...) calls right after the form's initComponents() call but if I do that none of the lists gets populated, at all.
Logging messages made it clear that the internal structures are getting populated, but even though they are both respective ListModels for my JLists, one of them isn't working as expected.
A sufficient portion of the code is generated by Netbeans and I have spent hours looking up the API but still have trouble finding out what I'm doing wrong. Any ideas?
I have a JList which uses a DefaultListModel.
I then add values to the model which then appear in the JList. I have created a MouseListener which (when double clicked) allows the user to edit the current user number of that person they have selected.
I have checked that the actual object of that record is being changed, and it is. The only issue I'm having is getting the actual Jlist to update to show the new values of that object.
Snippets of the current code I have are:
Creating the JList and DefaultTableModel:
m = new DefaultListModel();
m.addListDataListener(this);
jl = new JList(m);
jl.addMouseListener(this);
Updating the object:
String sEditedNumber = JOptionPane.showInputDialog(this, "Edit number for " + name, number);
if (sEditedNumber != null) {
directory.update (name, sEditedNumber);
}
And (when jl is the JList and m is the DefaultTableModel):
public void contentsChanged(ListDataEvent arg0) {
jl.setModel(m);
}
Instead of setModel(), update your existing model using one of the DefaultListModel methods such as setElementAt(), which will fireContentsChanged() for you.
You need to call fireContentsChanged() on the ListModel.
You need to call DefaultListModel.fireContentsChanged(). But since this method is protected (I really wonder why), you can't do that directly. Instead, make a small subclass:
class MinoListModel<T> extends DefaultListModel<T>
{
public void update(int index)
{
fireContentsChanged(this, index, index);
}
}
Use it as your list model:
m = new MinoListModel<>();
jl = new JList(m);
After updating a user number, update the corresponding entry: m.update(theIndex);
Alternatively, if you don't want a subclass, you can just replace the JList element after the user number changed: m.setElementAt(theSameElement, theIndex);. Though this is somewhat cumbersome and having a subclass seems the cleaner approach.