Row Delete in table - java

my whole code is this, but my code has one error and not run:
read from file is correctly , but dont delet row.
public class AllUserTable extends AbstractTableModel{
Vector data;
Vector columns;
public AllUserTable() {
String line;
data = new Vector();
columns = new Vector();
try {
FileInputStream fis = new FileInputStream("D:\\AllUserRecords.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
StringTokenizer st1 = new StringTokenizer(br.readLine(), " ");
while (st1.hasMoreTokens())
columns.addElement(st1.nextToken());
while ((line = br.readLine()) != null) {
StringTokenizer st2 = new StringTokenizer(line, " ");
while (st2.hasMoreTokens())
data.addElement(st2.nextToken());
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public int getRowCount() {
return data.size() / getColumnCount();
}
public int getColumnCount() {
return columns.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
return (String) data.elementAt((rowIndex * getColumnCount())
+ columnIndex);
}
public static void main(String[] args){
final AllUserTable aut1=new AllUserTable();
final JFrame frame1=new JFrame();
final JTable table=new JTable();
final JPanel panel=new JPanel();
JButton button1=new JButton("Delete");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel model=new DefaultTableModel(data,columns); //Error!
model.removeRow(table.getSelectedRow());
table.setModel(model);
table.setModel(aut1);
panel.add(table);
}
});
JScrollPane scroolpane=new JScrollPane();
scroolpane.setViewportView(table);
panel.add(scroolpane);
panel.add(button1);
frame1.add(panel);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setBounds(200, 80, 600, 500);
frame1.setVisible(true);
}
}
please repair my code!

This code doesn't compile. You're referencing instance fields (data, columns) from a static method (main). The error message of the compiler should tell you that. And if you don't understand it, googling for the error message should lead you to explanations of the error message.
And even if it did compiler, here's an explanation of each line of the event listener:
DefaultTableModel model=new DefaultTableModel(data,columns);
Create a new table model. Why? Your table already has one. All you need is to modify the existing table model
model.removeRow(table.getSelectedRow());
Remove a row from this new table model. Why modify a new model instead of modifying the existing one?
table.setModel(model);
Replace the old model by a new one. This is very inefficient. The table already has a model. Modify it.
table.setModel(aut1);
Replace the new model by the old one. Why?
panel.add(table);
Add the table to the main panel of the frame. Why? The table is already there and visible. This makes no sense.
You should implement a deleteRow() method in your AbstractTableModel.
Using a List of objects, where each row represents a row, would also be much clearer than using a single list to represent all the rows.
I have the feeling that you're copying and pasting code without understanding at all how it works and what the architecture of Swing is. Read the Swing tutorial. And even before that, read an introductory book about Java, variables and scopes.

Firstly, you never set the table model (aut1) to the table BEFORE your button action.
Secondly, I don't see where data and columns are defined when you construct the new DefaultTableModel in your action handler - the you try and delete a row from this "new" table model and the apply it to the table and then replace to with aut1, which effectively has done....nothing.
When constructing your UI, don't forget to set the table model to the table ... table.setModel(aut1)
Remove the DefaultTableModel from the action handler and use aut1 instead.
Updated with suggestions
You should avoid constructing your UI in the static main method, instead use a class instance instead, it will make you code cleaner and will present less issues into the future
You should only ever construct/manipulate UI/Swing components from within the context of the Event Dispatching Thread, use EventQueue#invokeLater

Related

Why don't revalidate() & repaint() work like I expect?

I expect once combobox has been selected, the JTable will change.
Here is my part of code:
……
chooseAccoutingItemComboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
changeTable();
jScrollpane.revalidate();
jScrollpane. repaint();
}
private void changeTable() {
JTable accountTable2 = new JTable(accountBook.getRowData(startYear, startMonth, endYear, endMonth, (AccountingItem) chooseAccoutingItemComboBox.getSelectedItem()), accountBook.getColumnNames());
accountTable = accountTable2;
}
});
accountTable = new JTable(accountBook.getRowData(startYear, startMonth, endYear, endMonth, accountintItem), accountBook.getColumnNames());
jScrollpane = new JScrollPane(accountTable);
add(jScrollpane, BorderLayout.CENTER);
……
And now when I selected item in combobox, the JTable didn't change. WHY?
Yours is a basic core Java mistake, one which has nothing to do with Swing, revalidate or repaint, and all to do with the core distinction of what is the difference between a Java reference variable and a reference (or object):
Changing the object referenced by a variable will have no effect on the original object. For example, your original displayed JTable object, the one initially referenced by the accountTable variable is completely unchanged by your changing the reference that the accountTable variable holds, and for this reason your GUI will not change. Again understand that it's not the variable that's displayed, but rather the object
To achieve your goal you will instead want to change the state of the displayed JTable. Do this by changing its model.
i.e., by doing something like:
private void changeTable() {
// create a new table model
MyTableModel newModel = new MyTableModel(pertinentParameters);
// use the new model to set the model of the displayed JTable
accountTable.setModel(newModel);
}
Use the parameters that you're currently passing into your new JTable:
accountBook.getRowData(startYear, startMonth, endYear, endMonth,
(AccountingItem) chooseAccoutingItemComboBox.getSelectedItem()),
accountBook.getColumnNames()
to create the new TableModel instead.
In fact you might even be able to create a DefaultTableModel directly with this data, something like:
DefaultTableModel model = new DefaultTableModel(accountBook.getRowData(
startYear, startMonth, endYear, endMonth,
(AccountingItem) chooseAccoutingItemComboBox.getSelectedItem()),
accountBook.getColumnNames());
accountTable.setModel(model);

Refreshing the java Jtable to show updated data

I am trying to refresh my Jtable shown in the UI whenever I query the mysql database. The idea was to show whatever new data updated in the UI JTable.
The UI class is below.
public class DBView {
private JFrame frame = new JFrame();
private JScrollPane tableScrollPane = new JScrollPane();
private DefaultTableModel dbTable = new DefaultTableModel();
public void setDbTable(DefaultTableModel dbTable) {
this.dbTable = dbTable;
//this.dbTable.repaint();
paintDBTable();
}
public DefaultTableModel getDbTable() {
return dbTable;
}
public DBView() {
initializeFrame();
paintDBTable();
}
private void paintDBTable() {
tableScrollPane.setBounds(20, 350, 400, 80);
frame.getContentPane().add(tableScrollPane);
JTable DBTable = new JTable(dbTable);
tableScrollPane.add(DBTable);
DBTable.setFillsViewportHeight(true);
tableScrollPane.setViewportView(DBTable);
}
/**
* Initialize the contents of the frame.
*/
private void initializeFrame() {
frame.setVisible(true);
frame.setBounds(100, 100, 451, 525);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setTitle("MySQL Database");
}
From another Model class I am calling the setDbTable() method. I input a new Jtable object to the setDbTable() method with data read from the database input into the new Jtable object.
The issue is inside the setDbTable() method, I am using paintDBTable() method again.
I tried using dbTable.fireTableDataChanged() method to refresh the view, didnt work.
The way it is now, it is working. But using the setDbTable() method to refresh seems like a very inefficient way to do it.
Question is Do you see anyway I could use another method defined for use of refreshing Jtables?
P.S. I am very new to java and programming in general. Sorry if the code is messy and the question is unclear. I can give all the code if its helpful. I removed most of the methods and other classes in the original code to make the question clearer.
tableScrollPane.add(DBTable);
JScrollPane isn't designated as container, you have to add child to JViewport
there are two options
a) tableScrollPane = new JScrollPane(myTable);
b) tableScrollPane.setViewportView(myTable);
DefaultTableModel dbTable = new DefaultTableModel();
DefaultTableModel is model that hold value for presentations layer for the JTable
rename this local variable (that make the sence) to dbTableModel instead of dbTable
you have to create a JTables view, f.e. two basics options
a) JTable myTable = new JTable(dbTableModel)
b) myTable.setModel(dbTableModel)
dbTable.fireTableDataChanged() is implemented in DefaultTableModel and correctly, not reason to call this method, nor outside of models definition (class, void, interface that returns XxxTableModel)
more informations in linked Oracle tutorials, ... for working code examples in SSCCE / MCVE form too
refresh data for JTable by
removing all rows in dbTableModel.setRowsCount(0);, then add a new row(s) to dbTableModel.addXxx
re_creating dbTableModel, note then must be added back to JTable e.g. myTable.setModel(dbTableModel)
It is not so confusing to refresh the JTable data and refreshing the UI after that, because:
Swing components implemented MVC and Observer in a very fantastic way. That means whenever you change the data in TableModel, the UI will be notified and repainted as you wanted.
So you should change you code in a way that you keep the JTable variable not the TableModel variable in your class. After that in setDbTable call the setModel method of the JTable, it means:
public class DBView {
private JTable jtable = new JTable();
public void setDbTable(DefaultTableModel dbTable) {
this.jtable.setModel(dbTable);
//this.dbTable.repaint();
//paintDBTable();
}
.
.
.
}
Hope this would be helpful,
Good Luck.

Dynamically updating jTable

My table will change the entire dataset during runtime.
My current code looks like below,
public class gui_test_form extends JFrame{
private JPanel rootpanel;
private JTable testTable;
private JScrollPane testScrollPane;
private JButton testButton;
private String[] columnNames = {"Name", "Color"};
private Object[][] data = { {"John", "Blue"}, {"Oliver", "Green"}, {"Paul", "Red"} };
public gui_test_form() {
super("GUI TEST");
setContentPane(rootpanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
testButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) { // Button Clicked
//Get new values
data[0][0] = "New Value";
//Update table
testTable.setModel(new DefaultTableModel(data, columnNames));
}
});
}
}
The code works as I expected. But I don't think making a new DefaultTableModel everytime is the best way to go. What should I be doing?
I looked briefly into fireTableChanged() method for AbstractTableModel, but couldn't make it work. I expected it would work since DefaultTableModel is inherited from AbstractTableModel.
Any help is appreciated.
-------Edit-------
Forgive me if I wasn't clearer before, but the problem is that I want to update the whole dataset. Even the Column names and the number of columns and rows are going to change.
For example, in the above code I could do this, and it would still work as you'd expect.
//Get new values
columnNames = new String[]{"Country", "Location", "Latitudes"};
data = new Object[][]{ {"John", "Blue", "1"}, {"Oliver", "Green", "4"}};
//Update table
You should be declaring a single table model at the same level where you create your JTable and making changes to that table model as required, rather than declaring it in the event handler.
private JPanel rootpanel;
private JTable testTable;
private DefaultTableModel tableModel;
private JScrollPane testScrollPane;
private JButton testButton;
tableModel = new DefaultTableModel();
testTable = new JTable(tableModel);
Take a look at the Java Tutorial. Pay attention to the section on listening for table data changes
If you come up with your own table model, you need to be sure to fully implement all overridden methods, particularly setValueAt(), and make sure you keep track of your row count properly. One of the most common mistakes involves forgetting to increment your row count after adding data and thinking that the table model is not receiving data.
Add below code in wherever you want to update the model.
model.addRow(new Object[]{txt_title.getText(), txt_name.getText()});
Before, The model and table must also be predefined globally.
DefaultTableModel model = new DefaultTableModel();

Adding to existing JList

I need some help about adding items to JList. I work on some "library" kind of project. And I need to add readers to already existing JList. But when I try to add it, JList just resets, removes all the readers and starts adding readers to a new blank JList. But I don't need it to make new list but add it to the already existing one.
I know it's something about creating new model after adding, but i don't know where to fix it.
panelHorni = new JPanel();
listModel = new DefaultListModel();
listCtenaru = new JList(listModel);
FileInputStream fis = new FileInputStream("myjlist.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
listCtenaru = (JList)ois.readObject();
listScroll = new JScrollPane();
listScroll.add(listCtenaru);
listCtenaru.setPreferredSize(new Dimension(350, 417));
listCtenaru.setBackground(new Color(238,238,238));
panelHorni.add(listCtenaru);
listener
public void actionPerformed(ActionEvent e) {
String jmeno = pole1.getText();
String prijmeni = pole2.getText();
listModel.addElement(jmeno +" "+ prijmeni);
listCtenaru.setModel(listModel);
pole1.setText("");
pole2.setText("");
pole1.requestFocus();
listModel.addElement(jmeno +" "+ prijmeni);
//listCtenaru.setModel(listModel);
There is no need to use the setModel() method if you are trying to update the existing model. The fact that you are trying to do this would seen to indicate you are creating a new model instead of updating the existing model.
See the Swing tutorial on How to Use Lists for a working example that updates the existing model.
The default model of JList is ListModel you must firstly change it inside the constructor to DefaultListModel. That solves your problem:
private JList list ;
private DefaultListModel model;
public ListModelTest(){//default constructor
//....
list = new JList();
model = new DefaultListModel();
list.setModel(model);
//....
}
public void actionPerformed(ActionEvent ev){
model.addElement("element");
//....
}

How to load already instantiated JComboBox with data in Java?

I have a Swings GUI which contains a JComboBox and I want to load data into it from the database.
I have retrieved the data from the database in a String Array. Now how can I populate this String array into the JComboBox
EDITED====================================================================
In actual, the JComboBox is already instantiated when the java GUI is shown to the user. So I can't pass the Array as a paramter to the constructor.
How can I populate the already instantiated JComboBox?
The following is the code that is Nebeans generated code.
jComboBox15 = new javax.swing.JComboBox();
jComboBox15.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "12" }));
jComboBox15.setName("jComboBox15");
Can I set another ComboBoxModel to the above jComboBox?
Ah, the combo box is already instantiated.... In that case just clear the contents and add the new array item by item:
comboBox.removeAllItems();
for(String str : strArray) {
comboBox.addItem(str);
}
Make sure this is done from the EDT!
Here's an excellent article about it: How to use Combo Boxes ( The Java Tutorial )
Basically:
String[] dbData = dateFromDb();
JComboBox dbCombo = new JComboBox(dbData);
You'll need to know other things like
Using an Uneditable Combo Box
Handling Events on a Combo Box
Using an Editable Combo Box
Providing a Custom Renderer
The Combo Box API
Examples that Use Combo Boxes
That article contains information about it.
EDIT
Yeap, you can either do what you show in your edited post, or keep a reference to the combo model:
DefaultComboBoxModel dcm = new DefaultComboBoxModel();
combo.setModel( dcm );
....
for( String newRow : dataFetched ) {
dcm.addElement( newRow )
}
new JComboBox(stringArray);
A useful tip - when you know what class you are working with, check its javadoc. It most often contains the information you need.
Edit: after your update, use:
for (String string : stringArray) {
comboBox.addItem(string);
}
(my tip still applies)
I think that what NetBeans does is what you need.
From wherever you want, you can create a DefaultComboBoxModel object and then invoke comboBox.setModel(defaultComboBox);
Here is a very small example of what I think you want to do: when the user clicks the button "Change data" the comboBox is filled with data from an array (method actionPerformed).
public class TestJComboBox extends JFrame {
private JComboBox comboBox = new JComboBox();
public TestJComboBox() {
JButton changeComboBoxData = new JButton("Change data");
changeComboBoxData.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultComboBoxModel cbm = new DefaultComboBoxModel(
new String[] { "hola", "adios" });
comboBox.setModel(cbm);
}
});
super.setLayout(new BorderLayout(10, 10));
super.setSize(100, 100);
super.add(changeComboBoxData, BorderLayout.NORTH);
super.add(comboBox, BorderLayout.SOUTH);
}
public static void main(String[] args) {
new TestJComboBox().setVisible(true);
}
}
JComboBox jComboOperator = new JComboBox();
arrOperatorName = new String []{"Visa", "MasterCard", "American Express"};
jComboOperator.setModel(new DefaultComboBoxModel(arrOperatorName));

Categories