I'm building a program that gathers a couple lists of files that match a particular set of criteria and manipulates them as it appropriate depending on the source, type of file, etc... My hope is that it will find the files and display them in a list that is easy to read. The user will select which files are going to be processed from the list, then hit a button that "starts the commotion," if you will.
Right now, I've made a class called DrawingFile that looks like:
class DrawingFile {
private static String fileName, fileType;
private static boolean actionable;
private static Path filePath;
public DrawingFile (Path path){
setFilePath(path);
setFileName(stripExtension(path));
setFileType(getExtension(path));
setActionable(true);
}
...(methods omitted to save time)...
My plan, initially was to create a JTable that populates based on a List of DrawingFiles with each of the fields in the objects being a column in the table, except the Path, which would not be displayed on the table. From there, the user would click a checkbox which would determine whether or not a file is going to be manipulated.
My issues stem first and foremost from my being relatively new to programming. This is the first program I've written that people are going to use, that also has any sort of UI.
As such my questions are:
Does my plan above make any sense at all?
Would it make more sense to leave the table out of it and create a series of JPanels inside a container? (this seems like it wouldn't be best practice)
If I do go with the table, should I scrap the DrawingFile class and store the data in the TableModel?
3a. If so, is there a way I can hide the Path in the table?
How do I go about changing the actionable boolean when it is (un)checked on the table?
On a scale of 1-10, how badly am I overthinking this?
If I understand correctly, you have a list of DrawingFile objects, and want to display this list as a JTable, where each row represents an object of the list. Yes, that makes perfect sense.
No. A table is perfect for that.
No. You should create a custom DrawingFileTableModel class, extending AsbtractTableModel, and using the list of objects as the source to implement the method. Google for "Java tutorial JTable", and you'll find an example in the official tutorial.
By making sure that isCellEditable() returns true for that column and row, and by implementing the setValueAt() and getColumnClass() methods correctly. The javadoc and the tutorial are your friends here. setValueAt(), when called with the index of the boolean column, should set its new value in the DrawingFile stored at the given row index in the backing list. getColumnClass(), when called with the index of the boolean column, should return Boolean.class.
Related
I am building a JTreeTable. I found some starter code and have come pretty far. In the end my goal is to be able to have different data at different levels like a hierarchical list.
Currently, I have it working with data at different levels. However, I am running up against a wall when it comes to changing the columns as a next goal. From where I currently stand I have 3 more milestones:
Show different set of columns for different levels
Ability to adjust column widths for different levels
Ensure the JTree part of the table always stays to left
I am getting close to closing out this task but again stuck at the first of these 3.
Since creating a JTreeTable is complex, the minimum example leverages several class listed below in the image:
I am happy to post the code to any of those classes but I also did not want clog the question with useless code. First let me show the functionality I want.
The first image is when the top level is selected and the second image is when the second level is selected. Notice how the columns are different. That is what I want to happen in my application.
Top level selected:
Second level selected:
So one way I tried to solve this problem, is when the list selection is changed inside this section of code:
ListSelectionListener listener = (ListSelectionEvent e) -> {
TreeTableModelAdapter adapter = (TreeTableModelAdapter) JTreeTable.this.getModel();
//Need to see why this breaks.
JTreeTable.this.getTableHeader().setColumnModel(adapter.getColumnModel());
};
this.getSelectionModel().addListSelectionListener(listener);
This code is in the initialization of the JTreeTable. I have tried setting the column model on both the TableHeader and the table as well. Below is what happens then when I select a row:
The columns just disappear on me. The creation of the column model is happening in the TreeTableModelAdapter class with the following method:
public TableColumnModel getColumnModel(){
DefaultTableColumnModel model = new DefaultTableColumnModel();
for(int i=0;i<getColumnCount();i++){
TableColumn column = new TableColumn();
column.setIdentifier(getColumnName(i));
model.addColumn(column);
}
return model;
}
Any direction would be very helpful. Again happy to post any code you think could be helpful to answer the question. Just put a comment in and I will add it right away.
I will add the milestones as I find them in case this helps others, but for now this question is answered.
Milestone 1
I was actually able to solve the first milestone. The key is to trigger the creation of the columns of the column model, not to create a new column model. Below is the code for when the row selection is changed:
//Change columns depending on row
ListSelectionListener listener = (ListSelectionEvent e) -> {
createDefaultColumnsFromModel();
};
this.getSelectionModel().addListSelectionListener(listener);
This code creates the columns based on the row selected in the JTree part of the JTreeTable. The TreeTableModelAdapter implements the getColumnCount() and getColumnName() methods by also passing the selected row in the JTree to the JTreeTableModel so that the columns and their names are dynamically retrieved based on a particular node in the JTree. The key for this for me was trigger those to be called again to update the JTreeTable.
Milestone 2
Adjusting column widths based on the data level proved to be much more difficult than I had originally anticipated. In order to retain the cells state when the column model changed I had to disconnect the painting of the cells from it. This is a hairy process because this is done inside BasicTableUI and the method that gets the rectangle of the cell is private. So I had to subclass it, overload the paint() method and create my own methods that get called inside the paint method. There was a lot of copy pasting so that I could call normally private methods. I just renamed them and referenced these methods instead. The way the ui class was designed did not make it very flexible. Below is 2 images where I am selecting different levels and the columns are obviously different widths at different levels.
Milestone 3
I was able to make this work by keeping track of the view in the model. This seems very dirty to me as the model should separated from the view. Since the tree column's class is unique, I just returned the right class if that column was the first in the view.
The one problem I have with this technique is that I get unexpected behavior where the value returned is not consistent. I attempted to resolve this by overriding JTree.covertValueToText(). Since a JTree only expects 1 value and depending on the sequence of columns in the view this value could change. So in overriding this method I check the stored index for the JTree column's value. Again this causes the unexpected behavior. I will update the post if I find the fix.
I am trying to select an item from the jList in one form (Home), and extract the data from the ArrayList and output the data to separate jTextFields in a different form (Details). Below is the method I'm trying to use to do this (not a lot there I know!).
public void passObjectData()
{
int i = proObjList.getSelectedIndex();
}
I know once the method is complete, I can just call it on the form load method in the next form, but I'm stuck on how to get the method correct.
I don't know what other code, if any, will be needed for your help.
I have hardcoded data into an ArrayList and have output a name to a jList. Now I want to get all of the data of one person that is stored
in the ArrayList (name, address, tel num etc) and put this information
into jTextFields.
As I understand your question this ArrayList is the undelying data structure used to fill the ListModel and you want to get the selected index from the JList to retrieve the correct object stored in that array list. In this case you can:
Have a domain class called Person to hold the person's data (name, address, etc)
Add Person objects to the ListModel.
Provide an appropriate ListCellRenderer to display the person's name.
Use JList#getSelectedValue() to get the selected Person.
Pass this selected Person object to the text field's form and update those accordingly.
Optional: attach a ListSelectionListener to the JList in order to listen for user's selection changes and do the previous step automatically.
See the first 3 points of this approach exemplified here (note: the example is using JComboBox but the same applies to JList as well).
Suggested readings
Creating a Model
Selecting Items in a List
Writing a Custom Renderer
Side note
Not sure if by forms you mean JFrames but just in case: please note that we should avoid using multiple JFrames. See this topic: The Use of Multiple JFrames, Good/Bad Practice?
I have some JDialogs displaying JTables.
When the header columns are clicked a sort occurs on that column.
My question is : how can I know when a column header has been clicked and thus made a sort active.
When the sort is active, I know I should user the .convertRowIndexToModel method.
But how do I detect that a column is sorting in order not to mess the correct index if no sort is active?
Generally speaking, you should ALWAYS uses the convertRowIndexToModel when you take an index value from the view (JTable) and try and look up some value within the model. The JTable does this automatically when you use it's methods, but incase you're not, you need to take care of it yourself.
There's no need to know if the view is sorted or not...
If you "really" want to know when a table is sorted, you could attach a RowSorterListener to the TableRowSorter used by the table.
You could also use the TableRowSorter#getSortKeys to see which columns are included in the sort...
I have used it for my selection table. When the auto order is activated (setAutoCreateRowSorter(true))
the indices of the model table and the visual change, so you have to tell it to look for it within the model with respect to the one you are seeing.
((CustomTable)form.getAvailListView().getModel()).data.get(form.getListView().convertRowIndexToModel(i))
I've been trying to freshen up on my Java knowledge and I've been building a small GUI program and I've been running into a bit of a problem.
Basically, I have a JList which I'm currently populating with strings from an object from one of my classes which implement AbstractListModel which we can call my ItemList class. It contains an ArrayList of objects of the type Item which implements Serializable.
But, what I'd like to do is rather than populate my JList with a bunch of strings I'd like to populate it with some kind of string + JTextField combination so I can see one property of each Item object while also being able to update another property by changing the JTextField.
Now, what I'm looking for is the simplest possible way of doing this, and I am assuming there is a (relatively) simple way to do this since it's such a common thing to want to do in a GUI application (although I wouldn't put it past Java and Swing to make it convoluted and complicated).
So, what is the correct way of doing this?
No need to ever use String objects. Instead:
Put Item objects in the JList.
Add a ListCellRenderer to the list, to show the Item object the most user friendly way.
When the user selects an item, show the details in a different place (I'm thinking a panel with 2 columns of labels and text fields, and two rows - one for each attribute, and perhaps a button to Save)
The edit controls would best be encapsulated in a panel that can then hidden when not required, & put in a variety of places, e.g.
Below the list
In the main part of the GUI
displayed in a JOptionPane or a (modal or not) JDialog
Here is an example of placing the 'view/edit panel' (the file details) below the selection component (the table).
Could somebody give me a suggestion on how to simply and effectively make GUI representation of directories which are contained inside the database. Now, getting information using SQL queries is one thing. I can do that.
In fact using separate small examples I can put a file inside the database along with his information and I can get the file out of the database. The thing is I was just doing this without GUI, just to test does it work.
Now I need a GUI of this and I really don't know where to start. DO I use JTable, JList or something third? Also, I think I need an multidimensional array because I have, for example, id of a file, name_of_file and size.
So I need different types to put them in: int, String and int.
Also, I need to obviously hide the id of a file from the user yet keep it at the same time in order to be able to reference it.
How do I hide it in a GUI component?
So, let's say that I have a database table for files with these columns:
id, name, size, binary_of_file.
My real table has a bit more of columns like, id of a parent directory, id of a owner, etc. but for now this is not important.
So, I tell database to give me all info about the file (except it's binary because I just want to list the files):
...
ResultSet rs = statementObject.executeQuery("SELECT id, name, size FROM Files;");
while(rs.next()){
//Where do I store the values in? Which GUI component and how?
...
I guess I need an JPanel that will contain this component that will show my files from the database. What component? Please help!
It sounds like you want to use a JTable, it has a TableModel interface that you can implement to adapt to your resultset.
Also follow the link at the top of the docs. to Creating a Table Model.
Perhaps a combined JList/JTable component would fit this need.
That is a screen shot of the GUI of FileBro.
My idea is that the JTree on the left would represent the 'directories' and table (names) of the DB. The JTable on the right would contain the data of the selected table. Change the Locate Open Edit Print buttons for Create Update Delete and the panel below that to show details of records, and it would be the start of a DB CRUD component.