How Can I Sort JTable With A Button? - java

Example:
I made a table, and I want a search box for each column. I hid the column titles with this code:
table.setTableHeader(null);
And put a textField and Button to each top of columns. Now I can search for each different column, but I can't sort the items.
I want to sort the column items when I click the top button. I tried some thing but it is so complex for a beginner as me.
Is there any way to do it? Or all the thing i tried useless and there is much easy way to do it? I hope explained it right.
Note :
I have found this code.I dont even know if it does what i need. I did try it but getting error.
/** Default sort behaviour, plus every third click removes the sort. */
private final class CustomSorter extends MouseAdapter {
#Override public void mouseClicked(MouseEvent aEvent) {
int columnIdx = fTable.getColumnModel().getColumnIndexAtX(aEvent.getX());
//build a list of sort keys for this column, and pass it to the sorter
//you can build the list to fit your needs here
//for example, you can sort on multiple columns, not just one
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
//cycle through all orders; sort is removed every 3rd click
SortOrder order = SortOrder.values()[fCountClicks % 3];
sortKeys.add(new RowSorter.SortKey(columnIdx, order));
fSorter.setSortKeys(sortKeys);
++fCountClicks;
}
private int fCountClicks;
}
}
And did try this and getting same error.
btnNewButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
table.getRowSorter().toggleSortOrder(1);
}
});
Error:Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
This is the code: Code
This is the what program looks like : Picture

In the ActionListener of your JButton you can try sorting the column with code like:
table.getRowSorter().toggleSortOrder(columnIndex);
This should allow you to click the button to reverse the sort order each time it is clicked.
Edit:
As I said in my comment you need to learn how to solve a NullPointerException.
The stack trace when I run the code states:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at frame1$2.actionPerformed(frame1.java:83)
Line 83 is:
table.getRowSorter().toggleSortOrder(0);
So you have two variables at that statement:
table
table.getRowSorter()
It is up to you to determine which variable is null
So you add debug code before that statement:
System.out.println( table );
System.out.println( table.getRowSorter() );
If you do you will see that table.getRowSorter() returns null.
So now you can ask a proper question like:
"Why does table.getRowSorter() return null?"
The answer is simple you didn't set the properties of the table to do sorting.
This is easily done by adding:
table.setModel(model);
table.setAutoCreateRowSorter(true); // added
In the future do some basic debugging BEFORE asking a question. You can't code if you don't know the basics of debugging code.
My original answered assumed you new how to sort columns in a table when using the table header and you just wanted to know how to use a separate button. That is why a "MRE" should be posted with EVERY question so we don't have to guess what your code is really doing.

Related

JavaFX How to get all values and sum of specific column from Table View by button?

I have a problem with adding functionality to my program. I'm using JavaFX and Table View. I don't know how can I implement a method witch will get data from specific column.
I try to implement solution from this said:
JavaFX How to get all values of one column from TableView?
But I don't understand exactly how should I send initialized TableColumn class to method totalPaidSaving
And: How to get selected TableCell in JavaFX TableView
I Also found a couple of different solutions using getSelectionModel().getSelectedCells() but in this case I need to use button and some sort of code witch will get data from specific column.
Fragment of MainControl class. Place where the method is called :
addButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Operation operation = new Operation();
operation.addRecord(dateTextField, distanceTextField, lpgAmountTextField, lpgPriceTextField,
petrolAmountTextField, petrolPriceTextField, paidLabel, savingLabel, gasEfficiencyLabel,
contentTable, totalSavingsLabel);
operation.totalPaidSaving(contentTable, totalSavingsLabel);
}
});
A fragment of the configuration of my TableView also in the MainControl class.
#SuppressWarnings("unchecked")
public void configurateTable() {
TableColumn<GasRecords, String> savingColumn = new TableColumn<GasRecords, String>(SAVING_COLUMN);
savingColumn.setCellValueFactory(new PropertyValueFactory<>("saving"));
contentTable.getColumns().addAll(dateColumn, distanceColumn, lpgAmountColumn, lpgPriceColumn, petAmountColumn,
petPriceColumn, paidColumn, savingColumn, gasEfficiencyColumn);
}
A fragment of Operation class:
public void totalPaidSaving(TableView<GasRecords> cT, Label tSL) {
String totalSavingValue = "0";
//the code that calculates the sum of the values ​​of a particular column
tSL.setText(String.format("%.2f zł", totalSavingValue));
}
I know that using String instead of double is bad but for now I would like to solve it in this form.
Link of visualization of me application and example of column i want to sum.
https://zapodaj.net/d8fc7ece3f629.jpg.html
My goal is to, after press the "Add" button application shows me the sum of all savings rows from saving column in specific label. Rest of application is working.
In this ways you can calculate the values of a column. you can get cell value by the index of the column. you have to use contentTable.getColumns().get(7).getCellObservableValue(i).getValue() get the cell value of that column Savings.
int totalSavingValue=0;
for (int i= 0;i<tblDispatchHistory.getItems().size();i++){
total = total+Integer.valueOf(String.valueOf(contentTable.getColumns().get(7).getCellObservableValue(i).getValue()));
}
System.out.println(totalSavingValue);
tSL.setText(totalSavingValue);

Why the method of my jtable getSelectedRow() don't work?

this is my first question, so help me please. I try to save the value of the method getStelectedRow in a type int variable(row) to next can use the method getValueAt(row,column). My problem is the value of my variable, it's -1, and this means the row is not selected, but I'm selecting a row.
The error is the next:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
If need more details just say me. Thanks.
EDIT:
My code is:
int row = jTablePersonal.getSelectedRow();
String query = "select * from table where id ='"+jTablePersonal.getValueAt(row,0)+"'";
The error point to the variable "row" when I call the method "getValueAt(row,0)"
Seems like a newbie problem. Given your explanation
"My problem is the value of my variable, it's -1, and this means the row is not selected, but I'm selecting a row."
You do not have this code inside a listener, you have like it your constructor or something. You want to have the code inside the listener. Something like
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
if (row != -1) {
// do something
}
}
});
If you are using the Netbeans GUI Builder tool, you can
From the design view right click the button and go to Events -> Action -> actionPerformed
Go to you source view and you should see some auto-generated code like
jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
}
Write the code there.
You should also take some time to read How to write Event Listeners. GUI Programs are event driven, so you need to learn how to respond to these events by registering listeners
the problem is about getSelectedRow();
getSelectedRow is only work if table is current selected
my suggestion is , make temp variable to get last selectedrow to prevent error ,like
if(table.getSelectedRow()!=-1)
{
int lastselected=table.getSelectedRow();
}

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()}));
}
});

JTextField getText() not working

I've been looking all over, and i cant find anyone who can solve this problem. I'm making a game, and in that game, i have editable controls. the controls window is a seperate JFrame, and when i click the confirm button, it is supposed to write the items in the JTextFields (holding the controls) to a file. but that wasnt working, so instead i have it print the arraylist that holds the values. here is the code:
public void writeControls() {
ArrayList<String> al = new ArrayList<String>();
al.add(up.getText());
al.add(down.getText());
al.add(left.getText());
al.add(right.getText());
al.add(jump.getText());
al.add(duck.getText());
al.add(attack.getText());
for (int i = 0; i < al.size(); i++) {
System.out.println(al.get(i));
}
System.exit(0);
}
the problem is this: if i change the final JTextField attack or any other one for that matter, and click submit, the system prints out the default controls. for example, if the JTextFields have the values w,a,s,d,r,t,q and i change the value q to i, it prints out q. what am i doing wrong? thanks in advance!
EDIT 1:
code for the textfields, and the FILES.... is simply a string stored in a different class. the class setText() is below the textfields.
up = new JTextField(setText(FILES.controlsFileFinalDir, 1));
down = new JTextField(setText(FILES.controlsFileFinalDir, 2));
left = new JTextField(setText(FILES.controlsFileFinalDir, 3));
right = new JTextField(setText(FILES.controlsFileFinalDir, 4));
jump = new JTextField(setText(FILES.controlsFileFinalDir, 5));
duck = new JTextField(setText(FILES.controlsFileFinalDir, 6));
attack = new JTextField(setText(FILES.controlsFileFinalDir, 7));
public String setText(String fileDir, int lineNum) {
String txt = "";
txt = io.readSpecificLine(fileDir, lineNum);
txt = switchCase(txt);
return txt;
}
switchcase() is only taking what you have written in the text file that these are getting the values from, and translating them. so if the value is 0, it is turned into Space, etc. io.readSpecificLine(); is only to get the line of text from the file. does this help?
EDIT 2:
i just was dinking around and found out that if i set the JTextField text by using setText(""); then use getText(); it works. so the problem is that when i change it manually, and use getText(); it wont work. Why?
To update the text to a currently existing JTextField, I would establish the JTextField as a class variable, and create a setter/getter method to adjust it (which I'm assuming you're doing).
According to your methods, you would use something like:
up.setText(setText(FILES.controlsFileFinalDir, 7));
Edit: **The first setText is the JTextField.setText, the second setText is your public method you posted. I'm assuming your second getText() isn't working because you're probably not setting the text correctly.
Without seeing more code, I can't really give a better guess.
The main possibilities:
(1) The text fields have their editable property set to false.
(2) You are creating multiple copies of the JTextFields, then editing a new one on the screen, but referring to the old one when you get the value.
(3) You have a ValueChanged or LostFocus event handler that is resetting the text fields to their defaults
(4) It is actually JFormattedTextField not a JTextField
If I was you, I would try to debug the programm. You will probably do some Mistake in your code, you won't be able to see, by just checking the code.
For example in which order do you call the functions and so on, maybe you have a fault here, or maybe you have several threads, so you try to read the Textfields without even set them and so on ... It's hard to say without reviewing the whole Code.
So if you use eclipse you can follow this link for an explanation on how to debug: http://www.vogella.com/articles/EclipseDebugging/article.html
Netbeans or any other IDE should support debugging as well.
This may seem like a strange thing to suggest, but I think this is an issue with pointers. If you create a new string before passing it in, JTextField will be able to change it internally and return what you expect when asked for the modified value.
down = new JTextField("" + setText(FILES.controlsFileFinalDir, 2));
// or
down = new JTextField(new String(setText(FILES.controlsFileFinalDir, 2)));
You might want to try the following:
create a class Test.java
import java.util.ArrayList;
import javax.swing.JTextField;
public class Test implements Runnable {
private ArrayList<JTextField> textFields = null;
private ArrayList<String> stringList = null;
public Test(ArrayList<JTextField> textFields, ArrayList<String> stringList) {
this.textFields = textFields;
this.stringList = stringList;
}
#Override
public void run() {
for ( JTextField textField : this.textFields )
this.stringList.add( textField.getText() );
}
}
and then, at the place where you use the "getText() method .. "
do the following...
ArrayList<JTextField> textFields = new ArrayList<JTextField>();
// add all the JTextField to textFields
ArrayList<String> stringList = new ArrayList<String>();
Test test = new Test( textFields, stringList );
SwingUtilities.invokeLater( test );
// check if the stringList is populated.
If this work, then what I believe is that, for some reason, the JTextField hasn't finished
"setting" the text, and before it finishes your getText() was called. I've had similar problems before, and this solved my problem that time, but still, this might not be the perfect solution.
First, you should change your "setText()" method name to something like "getTextFromFile()" it would be more readable
Then, if you are setting and reading the new text in different threads, my bet is that the setText() is taking long to return, because it is accessing the file system, while the method that read the values run instantly
I would try to do run a little test:
public void test(){ // must be run after the JTextFields be initialized
up.setText("TEST")
System.out.println(up.getText());
up.setText(setText(FILES.controlsFileFinalDir, 1));
System.out.println(up.getText());
}
If the test() prints the correct values, then we can assume that if you set and read the new value in the same thread it works fine
The other test I would do is:
public void testThread(){
new Thread(){
public void run(){
while(true){
if(up!=null){
System.out.println(up.getText());
}
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
It will print the value of up each 1 second, so that you can see if after some time you get the new value. If it does, then the answer is: Your setText() is taking long to run and you are reading the value before the new value is set
SOLUTION
none of the above answers were working for me, so i finally decided to just start over with that class. the few things i changed were the way i made the JTextFields. I made them as an array instead of individual objects. Second is the way i put what they say. When i initialized them, i was unable to get them to create WITH the text in the parameters. so i had to do that seperately. i changed some of the method names so as to reduce future confusion, and it worked! so im not sure what was up with that, maybe it was the way i did it, maybe just a fluke. it happens sometimes, so im sorry for the delay and waste of your time! thanks for all the answers anyway!
Try this:
textbox.setText(setFile(args)); // your function for set file

How to handle table which sorting and adding data parallel?

I am facing problem of duplicate rows in the JXTable. If I sort the JXTable data while the new rows are being inserted in JXTable, the final result in JXTable shows duplicate rows that make invalid result in table. Even it also shows correct count of rows that has been inserted but some rows are completely missing whereas some rows are found duplicate in JXTable.
If I sort the JXTable after all data has been inserted successfully then it is showing correct data i.e no duplicate rows and no rows missing.
code example :
I have a method to which I am passing defaultTableModel and here is am adding items in the table
public void addingItems(DefaultTableModel defaultTableModel)
{
for(int i=0;i< numberofItems;i++){
Vector vobject = new Vector();
vobject.add("...");
vobject.add("xxx");
vobject.add("yyy");
...
..
vobject.add("");
defaultTableModel.addRow(vobject);
}
one the other hand I have adding code of sorting at tableHeader actionlistener
tableheader.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
Vector data = defaultTableModel.getDataVector();
Collections.sort(data, new ColumnSorter(colIndex, ascending));
}
});
I have put code in the synchronized block but not getting success.
Please provide a better solution to handle this issue.
I have put code in the synchronized block but not getting success.
Because you have to handle synchronization not only in your sort handler block, but also on each modification operation.
For example:
...
vobject.add("");
synchronized(monitor) {
defaultTableModel.addRow(vobject);
}
}
and
...
Vector data = defaultTableModel.getDataVector();
synchronized(monitor) {
Collections.sort(data, new ColumnSorter(colIndex, ascending));
}
}
In this case your UI could look somewhat unresponsive if you have a lot of data in your table because sort is N^2*logN. If you have somewhat about 200 entries - it wouldn't make a problem for you.

Categories