In my application, I need to display file system files in a JTable. When I click on the JTree node (which is any system folder), the contents of that folder are shown in the JTable.
In the first column of the JTable (where the name of the file or folder icon is shown), the icon is fetched from the system icon and is displayed.
Every thing is working fine. However, the problem is that when the renderer renders icon, the icon of the first file (first row of JTable) is repeated in all rows. I mean the icon does not change in the subsequent rows of the JTable. Here my code is in which a render gets icon and the model displays it in the JTable
class KeyIconCellRenderer extends DefaultTableCellRenderer {
public KeyIconCellRenderer(String ext) {
File file = new File(ext);
Icon icon = FileSystemView.getFileSystemView().getSystemIcon(file);
setIcon(icon);
}
}
and here is code where I am using render to display
private class Selection implements TreeSelectionListener {
public void valueChanged(TreeSelectionEvent e) {
Object[] myData= new Object[6];
TreePath path = e.getPath();
FileUtil util= new FileUtil();
FileMetaData metaData;
Vector<FileMetaData> vList = new Vector<FileMetaData>();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)treeMainView.getLastSelectedPathComponent();
FileInfo info =(FileInfo)node.getUserObject();
File filePath= info.getFilepath();
vList=util.getChildList(filePath);
dtModel.getDataVector().removeAllElements();
for(int i=0;i<vList.size(); i++){
Vector v= new Vector();
metaData=(FileMetaData)vList.get(i);
v.add(metaData.getName());
tblMainView.getColumnModel().getColumn(0).setCellRenderer(new KeyIconCellRenderer(metaData.getClientpath()));
v.add(metaData.getClientpath());
if(metaData.isDirectory()){
v.add("");
}else
{
v.add((FileHelper.getSizeString(metaData.getSize())));
}
if(metaData.isDirectory()){
v.add("");
}else
{
v.add(new Date(metaData.getTime()));
}
if(metaData.isDirectory()){
v.add("Folder");
}else
{
v.add("File");
}
v.add("Pending Upload");
dtModel.insertRow(0, v);
}
tblMainView.repaint();
}
}
as in the attached image, only the icon of the fist file is repeated in all rows,
Please help, it will be a huge favor,
Thanks
[Your surface mistake is to reset the table column's renderer in the loop, each time hard-coding the current icon in the the renderer's constructor. Consequently, the file-icon is used for all.
The basic problem is that you don't seem to fully understand the concept of a renderer: it's there to display the cell data as it is delivered as a parameter in its getXXCellRendererComponent. So that's the place to look-up the icon to use. The way to go is to store the File object in the table cell and query the appropriate icon every time the method is called.
Cheers
Jeanette
Related
This is how the program looks:
This is how I want it to look:
As you can see in the picture I have tried a bit and learned that I need to use ListCellRenderer, but the problem is i have created 2 custom png files
checked.png and
unchecked.png
when I click daily goals #1 it should give state = true and checked.png should appear and stay checked unless I click it again. Unchecked.png could be standard on the jList column.
I also want to place my checkbox 1 cm to the left of the end of the row (padding) not sure hows its done in java sadly. (You'll understand better by looking at the picture)
After looking through some guides I have learned that the only way to add extra stuff to a JList column is by using ListCellRenderer. I have tried quite a while with no success so thought of asking others. Does anyone have any ideas on how to do this?
The thought was to get it to work then display in a JTable by changing the Jtable column to Daily goals and displaying X to indicate the goal was achieved. But I think I should be able to do this, The main question is the custom checkbox implementation.
You can have two types of checkboxes to be used as jlist cell renderers, one for selected cells, another for unselected.
Use ImageIcon to decorate the checkbox with your images.
In your jlist cell render you need to have logic to return the intended checkbox to render that list cell.
Note to override the text in the checkbox to the actual list cell value
public class TestFrame extends JFrame {
ImageIcon iconChecked = new ImageIcon(TestFrame.class.getResource("checked.png"));
ImageIcon iconUnchecked = new ImageIcon(TestFrame.class.getResource("unchecked.png"));
JList jList = new JList(new Object[]{"ABC", "123"});
public TestFrame() {
this.add(jList);
jList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
jList.setCellRenderer(new ListCellRenderer() {
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
for (int i : list.getSelectedIndices()) {
if (index == i) {
JCheckBox checkBoxChecked = new JCheckBox(value.toString(), iconChecked);
return checkBoxChecked;
}
}
JCheckBox checkBoxUnchecked = new JCheckBox(value.toString(), iconUnchecked);
return checkBoxUnchecked;
}
});
}}
I have a problem with my JComboBox.
description:
I create a new file by writing the name of my file in a Textfield. By clicking on a button I create a file with this value and add this into my JComboBox, but I only see the Object value, for example "[Ljava.io.FIle;#1b1428d" and that's the problem. The user doesn't even know what this value means so I need my filename. I searched for a long time and Yes the toString() doesn't work :D
My Code looks like this: JComboBox TxtDoc = new JComboBox(create());
public File[] create(){
FileSystemView SYSTEM = FileSystemView.getFileSystemView();
String user = System.getProperty("user.home")+"\\notes";
File userdir = new File(user);
File[] fileList = SYSTEM.getFiles(userdir, true);
return fileList;
}
newTxt.addMouseListener(new MouseAdapter() {
#SuppressWarnings("unchecked")
public void mouseClicked(MouseEvent event){
new Documents().createTxtDoc(); // <-- this just open a new frame with my textfield and a button.
TxtDoc.addItem(create());
}
});
thank you for your help
regards Blank
iterate over it:
for (File f : fileList) {
TxtDoc.addItem(f);
}
You're add an array Files as a single element of the combobox (that's what addItem does, adds A (single) item)
There's a few ways you might be able to do this, one might be to simply reset the combo box's model...
TxtDoc.setModel(new DefaultComboBoxModel(create());
This has the the nice side effect of removing all the previous elements first
Having said that, you might not like the results...
You may want to consider providing a custom cell render to render just the name of the file. See How to Use Combo Boxes and Concepts: Editors and Renderers for more details
I have been trying to determine why my JComboBox is displaying the 1st item in the list through numerous Google searches, but I'm struggling to find relevant help. It could be that I don't know the correct terminology (hence the overly specific title of this question) and thus not finding the information that would explain my issue. I checked out the JComboBox API, and few of the listeners and models that it uses, but they did not seem likely candidates.
The JComboBox in question is inside a JTable, so I am not aware if that changes the default behaviour of it. The code I am using is as below:
//row and col are final due to usage inside anonymous inner class
public TableCellEditor getCellEditor(final int row, final int col)
{
String[] listItems = new String[arrayList.getSize()];
int i = -1;
for(String s : arrayList)
{
i++;
listItems[i] = s;
}
JComboBox<String> box = new JComboBox<>(listItems);
box.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
if(e.getItem().equals("Add/Edit Projectile"))
{
//Where Editor is a JFrame that will be opened
new Editor();
}
}
}
});
DefaultCellEditor list = new DefaultCellEditor(box);
}
Please note that the Arraylist in my program does not contain Strings, but instead a more complicated set of custom objects that I believe would distract from the main issue.
I haven't included a Renderer for JComboBox's in the JTable as I was happy enough with the way it appeared, and figured that my problem was more going to be something I have neglected to implement in the model/implemented wrong.
I've also provided a couple of screenshots to better portray my problem. The first image is when the JComboBox is not selected, and simply displaying the currently selected item.
The second image is when I have just clicked the JComboBox to bring up the list. As depicted, it will immediately bring up that first item, no matter what it is.
If anyone has any suggestions as to where to look/solutions, I would be very grateful.
EDIT
My particular table has two columns, where the left column is a variable name, and the right column is the value associated with the variable. The tables role is to display the properties of a selected object, where each value for different variable for different objects are likely to not be the same.
In this particular case, the cell displays a JComboBox with all the available Projectiles in the game we are making. Each enemy has a different type of projectile it defaults to. So when I click on a different enemy in our game area, the table will display all of their current properties (defaults if they have not been changed).
Enemies do have a getter for the Projectile, so I could determine what the currently selected enemy is, get it's projectile, do a toString() to find how it is to be represented in the list, and do a setValueAt().
The only problem is at the moment it is always selecting the first item in the list when the list is expanded.
Unless the values for the JComboBox are dynamically generated for each row, you should be able to just prepare the CellEditor ahead of time, for example...
JComboBox cb = new JComboBox(new String[]{"1", "2", "3", "4"});
DefaultCellEditor editor = new DefaultCellEditor(cb);
JTable table = new JTable(new DefaultTableModel(5, 1));
table.getColumnModel().getColumn(0).setCellEditor(editor);
This will set the selected value of the editor to the value of the cell when the editing process starts
Updated
In the case where the combobox values are dynamically generate per row, you could do something more like...
JComboBox cb = new JComboBox();
DefaultCellEditor editor = new DefaultCellEditor(cb) {
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JComboBox editor = (JComboBox) getComponent();
String[] listItems = new String[arrayList.getSize()];
int i = -1;
for (String s : arrayList) {
i++;
listItems[i] = s;
}
DefaultComboBoxModel model = new DefaultComboBoxModel(listItems);
editor.setModel(model);
editor.setSelectedItem(value);
return editor;
}
};
JTable table = new JTable(new DefaultTableModel(5, 1));
table.getColumnModel().getColumn(0).setCellEditor(editor);
Note the use of editor.setSelectedItem(value);, this will set the selected value to the cells current value...
You could also re-use the model, clearing it each time and re-filling it with new values. You might find this more efficient if you have a large number of rows as you won't need to constantly create a new model each time a cell is edited
Thow this is an oldie...
Your problem is most likely you don't implement "equals" in the class used in the combo.
The Combo needs to select the current item when it is being prepared and does so by iterating through the elements of the model and selects the first one that is equal to the value in the cell. If none is encountered then it leaves the combo as is (either first element or the last used element in a previous cell edit)
This is how you should default to the previously selected element:
//...
Object selectedItem = box.getSelectedItem();
//Add some elements to the jComboBox
box.setSelectedItem(selectedItem);
I need to do something every time the user tries to drag a CheckBox and paste it from one panel to another.
I know Java offers drag and drop API but I don't exactly want the check box to be dragged from one panel to another.
What I want is to give the user an illusion of drag and drop and behind the scenes I want my code running and performing certain operations. How should I do that ??
Now when I drag and drop the check Box image1 from panelleft to panel_right I want certain code to run in the background on that drag and drop action of the user
for(ResourceListObject currentImage : imageList ){
imageOnRepositoryCheckBox[checkBoxNumber] = new JCheckBox(currentImage.getName());
imageOnRepositoryCheckBox[checkBoxNumber].setBounds(6, gapping+checkBoxNumber*26, 368, 23);
imageOnRepositoryCheckBox[checkBoxNumber].setTransferHandler(new FromTransferHandler());
if(imagesToBeImported != null){
if(imagesToBeImported.contains(currentImage)){
imageOnRepositoryCheckBox[checkBoxNumber].setForeground(Color.GRAY);
imageOnRepositoryCheckBox[checkBoxNumber].setToolTipText("This image is already on the list of images to be imported and can't be selected again.");
}
}
panel.add(imageOnRepositoryCheckBox[checkBoxNumber]);
checkBoxNumber++;
}
and the second piece of code that would run is
for(JCheckBox currentCheckBox : imageOnRepositoryCheckBox){
if(currentCheckBox.isSelected()){
Iterator itr = imagesOfCurrentRepository.iterator();
while(itr.hasNext()) {
ResourceListObject iteratedImage = (ResourceListObject)itr.next();
if(iteratedImage.getName().equals(currentCheckBox.getText())){
boolean isAdded = imagesToBeImported.add(iteratedImage);
descriptionPanel.updateDescription("The image selected for importing is "+currentCheckBox.getText());
if(isAdded){
currentCheckBox.setForeground(Color.GRAY);
currentCheckBox.setToolTipText("This image is already on the list of images to be imported and can't be selected again.");
}
}
}
updateImagesToBeImportedPanel(panel_1, imagesToBeImported);
}
checkBoxNumber++;
}
So I want the user to think of it as drag and drop but in the backend I would be doing my own thing .
I'm trying to do something pretty simple. I want to place an icon in a column for a particular row in a table. If it's a folder, display a folder icon. If it's a file, display a file icon.
Does anyone know how to do this in JavaFX 2?
I've tried so many things and this seems like it should be pretty simple or at least an example somewhere.
Okay so I had a huge dummy moment. Turns out that I had my image url path wrong.
I did find a site that provides a great example for adding elements for table. This helped me understand everything.
Now if the 4 different ways I tried before would've worked, I don't know because my image url path was wrong. But anyway here is the link and a code snippet.
Bottom line was that you need to have the CellValueFactory and the CellFactory. I was attempting to use either or. The updateItem template method in TableCell relies on the value dervied from CellValueFactory.
http://blog.ngopal.com.np/2011/10/01/tableview-cell-modifiy-in-javafx/
TableColumn albumArt = new TableColumn("Album Art");
albumArt.setCellValueFactory(new PropertyValueFactory("album"));
albumArt.setPrefWidth(200);
// SETTING THE CELL FACTORY FOR THE ALBUM ART
albumArt.setCellFactory(new Callback<TableColumn<Music,Album>,TableCell<Music,Album>>(){
#Override
public TableCell<Music, Album> call(TableColumn<Music, Album> param) {
TableCell<Music, Album> cell = new TableCell<Music, Album>(){
#Override
public void updateItem(Album item, boolean empty) {
if(item!=null){
HBox box= new HBox();
box.setSpacing(10) ;
VBox vbox = new VBox();
vbox.getChildren().add(new Label(item.getArtist()));
vbox.getChildren().add(new Label(item.getAlbum()));
ImageView imageview = new ImageView();
imageview.setFitHeight(50);
imageview.setFitWidth(50);
imageview.setImage(new Image(MusicTable.class.getResource("img").toString()+"/"+item.getFilename()));
box.getChildren().addAll(imageview,vbox);
//SETTING ALL THE GRAPHICS COMPONENT FOR CELL
setGraphic(box);
}
}
};
System.out.println(cell.getIndex());
return cell;
}
});
In case the provided answers did not work for you (like it didn't for me), this was the solution I found (Of course you still needs to create the tableView and add the columns to it):
//Create your column that will hold the image
private final TreeTableColumn<YourObjectClass,ImageView> columnImage= new TreeTableColumn<YourObjectClass,ImageView>("Image");
public void start() {
//Set your cellValueFactory to a SimpleObjectProperty
//Provided that your class has a method "getImage()" this will work beautifully!
columnImage.setCellValueFactory(c-> new SimpleObjectProperty<ImageView>(new ImageView(c.getValue().getValue().getImage())));
}