Java GUI panel revalidation - java

I am having a main class which controls all the application, including the displaying of all the panels. The method to display the main application panel is:
private void displayMainApplicationPanel() {
String[] columnNames = { "Media ID", "Title", "Pricipal Actors", "Type", "Duration", "Launch Date", "Price",
"Status" };
ResultSet resultSet = databaseLogicController.showMediaInfo();
String[][] data = parseMediaResultSet(resultSet, 8);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
graphicController.showMainApplicationPanel(data, columnNames);
addMainApplicationPanelSearchButtonActionListener();
addMainApplicationPanelSearchTextFieldKeyListener();
addMainApplicationPanelShowMyIdButtonActionListener();
addMainApplicationPanelBorrowMediaButtonActionListener();
addMainApplicationPanelMakeInternetRezervationButtonActionListener();
addMainApplicationPanelShowVHSInformationButtonActionListener();
addMainApplicationPanelShowDVDInformationButtonActionListener();
addMainApplicationPanelShowInternetRezervationsActionListener();
addMainApplicationPanelShowClientsInformationButtonActionListener();
addMainApplicationPanelInsertClientButtonActionListener();
addMainApplicationPanelInsertMovieButtonActionListener();
addMainApplicationPanelInsertVHSButtonActionListener();
addMainApplicationPanelInsertDVDButtonActionListener();
}
});
}
On that main panel, I have a table which shows all the current medias. I want to be able to update that table via a search function.
The code for the search button action listener is:
private void addMainApplicationPanelSearchButtonActionListener() {
graphicController.getMainApplicationPanel().addSearchButtonActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String[] columnNames = { "Media ID", "Title", "Pricipal Actors", "Type", "Duration", "Launch Date", "Price",
"Status" };
String title = graphicController.getMainApplicationPanel().getSearchTextField().getText();
ResultSet resultSet = databaseLogicController.showParticularMediaInfo(title);
String[][] data = parseMediaResultSet(resultSet, 8);
graphicController.getMainApplicationPanel().setMediaTable(new JTable(data, columnNames));
graphicController.getMainApplicationPanel().repaint();
graphicController.getMainApplicationPanel().revalidate();
graphicController.getMainFrame().repaint();
graphicController.getMainFrame().revalidate();
}
});
}
Now, I create a new table in the action listener based on the search criteria and set it in the main application panel, followed by calls to repaint and revalidate on both the main frame and the main panel. Why isn't the new table shown?

Now, I create a new table in the action listener based on the search criteria
Don't create a new table. The easiest approach is to update the existing table with a new TableModel:
table.setModel(...);

I don't recommand you using this line
graphicController.getMainApplicationPanel().setMediaTable(new JTable(data, columnNames));
You can better get that table then ((DefaultTableModel)myTable.getModel()).setRowCount(0); and ((DefaultTableModel)myTable.getModel()).addRow(new Object[]{data1, data2, ...});

Related

Return the value from JOptionPane

I have made a JOptionPane which contains a JPanel. The panel contains one button and one Jtable.
JPanel p = atomicAttack.getPanel(); //make the panel and return it
JOptionPane.showOptionDialog(null, p,"Atomic Attacks",
JOptionPane.DEFAULT_OPTION,JOptionPane.INFORMATION_MESSAGE,
null, new Object[]{}, null);
and inside the JButton i have:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
selectedId=jTable1.getValueAt(jTable1.getSelectedRow(), 0).toString();
}
I need to when the user clicks on the button, the JOption get closed and the selectedId get return from the JOptionPane?
I have seen this, but it is not exactly what i am looking for.
Because the button does not return the value for me.
Focus on the models and things will be easier.
public static void main(String[] args) {
DefaultTableModel tableModel = new DefaultTableModel();
tableModel.addColumn("Selection", new Object[] { "A", "B", "C" });
JTable table = new JTable(tableModel);
ListSelectionModel selectionModel = table.getSelectionModel();
JPanel p = new JPanel(new BorderLayout());
p.add(table, BorderLayout.CENTER);
int option = JOptionPane.showConfirmDialog(null, p, "Atomic Attacks", JOptionPane.OK_CANCEL_OPTION,
JOptionPane.INFORMATION_MESSAGE);
if (JOptionPane.OK_OPTION == option) {
printSelection(selectionModel, tableModel);
} else {
selectionModel.clearSelection();
}
}
private static void printSelection(ListSelectionModel selectionModel, TableModel tableModel) {
for (int i = selectionModel.getMinSelectionIndex(); i <= selectionModel.getMaxSelectionIndex(); i++) {
if (selectionModel.isSelectedIndex(i)) {
Object selectedValue = tableModel.getValueAt(i, 0);
System.out.println(selectedValue);
}
}
}
If you now select multiple rows
and press the ok button the result will be
A
C
If you want a single selection you can just set
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

Java Swing: JTable tableChanged does not work after model is updated

On load, my JTable has 2 columns - . So its a string in the first column and a checkbox in the second column. When I click on the checkbox tableChanged is fired and I can print the row data that was selected.
I need to change the table data when user selects a new category in the dropdown.
When the table data is updated, and I click on the checkbox the tableChanged is no longer fired.
This is what I have:
This is how I am updating the table data:
comboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String t = (String) comboBox.getSelectedItem();
if (t.equals("survey2")) {
String[] columnNames = { "Volume Name", "Select" };
Object[][] data = { { "pt1", false }, { "pt2", false },
{ "pt3", false }, { "pt4", false },
};
model = new DefaultTableModel(data, columnNames);
table.setModel(model);
}
}
});
This is my tableChanged:
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
if ((Boolean)table.getModel().getValueAt(table.getSelectedRow(), 1)) {
System.out.println(">\t"
+ table.getValueAt(table.getSelectedRow(), 0));
} else {
System.out.println(">\t"
+ table.getValueAt(table.getSelectedRow(), 0));
}
}
});
I do not understand why the event is not fired after updating the model. Am I updating the table incorrectly?
You area creating a new TableModel but you added the ChangeListener to the old TableModel.
Don't create a new TableModel!
You can clear the data by using setRowCount(0).
The you can add the new data back to the DefaultTableModel by using:
the setDataVector(...) method, or
by adding data back to the model one row at a time using the addRow(...) method.
So there is no need to create a new TableModel. If you want to create a new TableModel then you also need to add your ChangeListener to this new model.

Garbage value in jtable after adding row dynamically

I have JTable which has few columns.In that I have JComboBox. At program start I want them to be empty.I have one JButton on click action of button i have the code to add row dynamically in table.
But after adding the row i get garbage value in the cell having JComboBox. As shown in below figure :
And here is the code :
Code to add JComboBox in table
// Create columns names
String columnNames[] = { "Item", "Sun Item", "Required Quantity","Price","Gross Amount" };
// Create some data
final String dataValues[][] =
{
{ "", "", "","","", },
};
tableModel = new DefaultTableModel(dataValues, columnNames);
// Create a new table instance
table = new JTable( tableModel );
updateItemCombo();
TableColumn itemColumn = table.getColumnModel().getColumn(0);
itemColumn.setCellEditor(new DefaultCellEditor(comboItem));
public void updateItemCombo(){
Vector<String> s = new Vector<String>();
try{
setConnectin();
String str = "select * from ItemTable";
stmt = conn.createStatement();
rs = stmt.executeQuery(str);
while(rs.next())
{
String nm = rs.getString("Item_Name");
s.add(nm);
}
conn.close();
}catch(Exception e2){
e2.printStackTrace();
}
DefaultComboBoxModel<String> modelData = new DefaultComboBoxModel<String>(s);
comboItem.setModel(modelData);
}
Code to add row dynamically on button click :
btnAddOrder.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tableModel.addRow(dataValues);
tableModel.fireTableDataChanged();
}
});
What should i do to remove this garbage value from table? Please help
The addRow(...) method takes a 1-Dimensional array as a parameter. You are attempting to add a 2-Dimensional array.
Also, do not use:
tableModel.fireTableDataChanged();
it is the job of the TableModel to invoke the appropriate fireXXX() method, which by the way in this case would be fireTableRowsInserted(...).

remove a selected row from jtable on button click

I want to remove a Selected row from a table in java.
The event should be performed on button click.
I will be thank full if someone helps...
For example there is a table named sub_table with 3 columns i.e sub_id, sub_name,class.
when I select one of the rows from that table and click delete button that particular row should be deleted..
It's very simple.
Add ActionListener on button.
Remove selected row from the model attached to table.
Sample code: (table having 2 columns)
Object[][] data = { { "1", "Book1" }, { "2", "Book2" }, { "3", "Book3" },
{ "4", "Book4" } };
String[] columnNames = { "ID", "Name" };
final DefaultTableModel model = new DefaultTableModel(data, columnNames);
final JTable table = new JTable(model);
table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
JButton button = new JButton("delete");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// check for selected row first
if (table.getSelectedRow() != -1) {
// remove selected row from the model
model.removeRow(table.getSelectedRow());
}
}
});

Java update jtable row from another thread

I have a multi threaded program and I'm trying to use a JTable to view the progress of each thread. Each thread is a row the JTable. I have posted a simplified and relevant code of what I have now. Each time I press start a new thread is started and the row is added to the JTable. But how do I update the "Column 2" which of the row which belongs to that thread from the running thread?
In main this is what I have
JTable table = new JTable(new DefaultTableModel(new Object[]{"Thread Name", "Progress"}, 0));
btnBegin.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
Thread newThread = new Thread(new MyThreadClass(country, category));
newThread.start();
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.addRow(new Object[]{"Thread " + threadNumber, "Column 2"});
}
});
If you can add a field tableModel to MyThreadClass (field+constructor argument), from this class, you can invoke the code #sedran was mentioning.
Example:
public class T {
static int threadNumber = 0;
public static void main(String[] args) throws Exception {
final JTable table = new JTable(new DefaultTableModel(new Object[] { "Thread Name", "Progress" }, 0));
JButton btnBegin = new JButton("Begin");
btnBegin.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
MyThreadClass newThread = new MyThreadClass(model, threadNumber++);
newThread.start();
model.addRow(new Object[] { "Thread " + threadNumber, "Column 2" });
}
});
JFrame frame = new JFrame();
frame.add(btnBegin, BorderLayout.NORTH);
frame.add(table);
frame.setSize(400, 400);
frame.setVisible(true);
}
static class MyThreadClass extends Thread {
private final DefaultTableModel model;
private final int threadNumber;
public MyThreadClass(DefaultTableModel model, int threadNumber) {
super();
this.model = model;
this.threadNumber = threadNumber;
}
#Override
public void run() {
for (int i = 0; i <= 5; i++) {
final int index = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
model.setValueAt(index * 20, threadNumber, 1);
}
});
}
}
}
}
Please note that the use of SwingUtilities.invokeLater is important as the view MUST be refreshed in the EDT.
if you want to update the column at runtime and if you know in which row you want to update, you can use it this way:
int row; // row number you want to update.
int column = 1; // You want to update the first row.
DefaultTableModel model = (DefaultTableModel)table.getModel();
Object value = "New Value Of This Cell";
model.setValueAt(value, row, column);
You can pass or set your table, and the row in which the thread is showing to the MyThreadClass, so it can update its row by itself.
You can write a method insie MyThreadClass like this:
public void setTableAndRow(int row, JTable table) {
this.table = table;
this.row = row;
}
You can pass those arguments while creating the thread:
btnBegin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
DefaultTableModel model = (DefaultTableModel) table.getModel();
MyThreadClass myThread = new MyThreadClass(country, category);
Thread newThread = new Thread(myThread);
/**
* We know, if there is n rows starting from 0,
* index of the row that we're adding is n.
*/
int row = model.getRowCount();
myThread.setTableAndRow(row, table);
// Now we add the row before starting the thread, because it
// will try to reach that row, we don't want any exceptions.
model.addRow(new Object[]{"Thread " + threadNumber, "Column 2"});
newThread.start();
}
});
Suggestions:
Use a SwingWorker object to create your background thread.
One way to get updates from the SwingWorker is by using its publish/process method pair. This allows the background thread to pass data to the Swing application on the Swing event thread. This will allow the background process to "push" data onto the GUI.
The other way to get updates is to add a PropertyChangeListener to the SwingWorker and have the SwingWorker update bound properties. Either will work fine. This will allow data to be "pulled" from the background process onto the GUI.
To update the data in a specific data row, you'll need to somehow connect a row of the model with the thread you're following. You could always iterate through the cells of the a certain column of the table model using getValueAt(...) until you've found one that contains data that matches that of the thread, perhaps a field of the watched class. Then you can update the data held by a different column of that row using JTable's setValueAt(...)
I think SwingUtilies.invokeLater() is what you are looking for, so you can access event dispatch thread.

Categories