Table stops responding to clicks after refresh - java

I have the following code:
retrieveMessages.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent arg0) {
model.resetList();
top.remove(scrollPane);
folder = new getMessages().getMessagesInstance();
folder.initGetMessages();
model = new MessageTableModel().getModelInstance();
table = new JTable(model);
table.setTableHeader(null);
System.out.println("Got to here");
scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(150,150));
top.add(scrollPane, BorderLayout.CENTER);
table.setVisible(true);
dialog.setVisible(true);
}
});
folder = new getMessages().getMessagesInstance();
folder.initGetMessages();
model = new MessageTableModel().getModelInstance();
table = new JTable(model);
table.setTableHeader(null);
scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(150,150));
top.add(scrollPane, BorderLayout.CENTER);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent event) {
MessageTableModel model = new MessageTableModel().getModelInstance();
try {
String message = model.getMessage(table.getSelectedRow()).getMessage().toString();
messageArea.setText(Jsoup.parse(message).text());
System.out.println("Selected!");
} catch (Exception e) {
e.printStackTrace();
}
}
});
There's some code in between the first function and the other two functions, but it doesn't edit any of the data. Here's the problem. When I load the GUI, the table responds fine, just as it should (as in the last function). However, when I activate the retrieveMessages function, it refreshes the table, but clicking on the rows does nothing now. I've tried hard coding print-outs to see if it's even getting there,and it isn't, or it just isn't working.
And yes, I tried fireDataChanged. That did literally nothing besides add an entire block of emails, that were identical to the original emails, on to the bottom of the original table. So I had a double the size table with copies of all emails twice. fireDataRowsDeleted did nothing either.
Help?

Try creating a global public table and add that to your:
table.setModel(your_new_model_goes_here);
//update the global table with a new model`enter code here`
You are creating different table objects currently.

Related

Jtable showing wrong (old) results from DB

I am writing a code which takes as input a word (the name of a board game) or a letter and searches it in my DB.
If there are any entries I'll show them in a table, otherwise I don't want to show the empty table and I want to show a label "No results found" which disappears after 1500ms.
The if statement works properly. For example if I write 't' I'll get all the games starting with 't' in a table.
The else statement sometimes has problems:
if I run my program and I first write as input 'b' (no entries starting with 'b' in my DB) --> it shows the label "no results found" and then it disappears (it works!)
if I run my program and I write as input 't' (it works as said) and then I write 'a' (I have entries with 'a', it works) [.....] and then finally I write as input 'b' (no entries starting with 'b' in my DB) here is the problem: it shows the label "No results found" but it ALSO shows the table with the results of my very first input (i.e. the games starting with 't').
What am I doing wrong? Thanks!
Here the code after clicking the button "Search":
btnCerca.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
/*Connect to DB:*/
Database db = new Database();
Connection connection = null;
try
{
connection = db.connectToDB();
}
catch (SQLException ex)
{
ex.printStackTrace();
}
/*Create a query which search in the DB the word/letter entered by the user*/
Query query = new Query (connection);
query.search(textField.getText()); //execute the query
/*Get results:*/
ResultSet rs = query.getResults();
/* check if rs is empty */
boolean res = false;
try
{
res = rs.isBeforeFirst();
}
catch (SQLException e1)
{
e1.printStackTrace();
}
ListTableModel model = null;
JScrollPane scrollPane = new JScrollPane();
if (res) //there is something in rs
{
try
{
model = ListTableModel.createModelFromResultSet(rs);
}
catch (SQLException e1)
{
e1.getMessage();
}
/*The table which will show the results*/
JTable table_1 = new JTable(model);
scrollPane.setBounds(10, 75, 1200, 300);
panelRicerca.add(scrollPane);
scrollPane.setViewportView(table_1);
}
else //rs is empty
{
JLabel lblNoGiochi = new JLabel("No results found.");
lblNoGiochi.setBounds(448, 30, 400, 14);
panelRicerca.add(lblNoGiochi);
panelRicerca.repaint();
/*...I want the label disappear after 1500ms:*/
int delay = 1500;
ActionListener taskPerformer = new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
panelRicerca.remove(lblNoGiochi);
panelRicerca.repaint();
}
};
new Timer(delay, taskPerformer).start();
}
}
});
------------------------EDIT------------------------
I made a simpler example which is affected by the same problem so you can compile and check quicker.
If I write "hello" I want to display a table.
If I write anything else, I want the table to show a label instead.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JLabel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Test {
private JFrame frame;
private JTextField textField;
private JTable table;
private JLabel lbl;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
lbl = new JLabel("Hey");
lbl.setBounds(378, 236, 46, 14);
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
textField = new JTextField();
textField.setBounds(102, 48, 86, 20);
frame.getContentPane().add(textField);
textField.setColumns(10);
JButton btnOk = new JButton("ok");
btnOk.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(20, 20, 50, 50);
table = new JTable();
if (textField.getText().equals("hello"))
{
System.out.println("I'm in the if statement");
//show the table:
frame.getContentPane().add(scrollPane);
scrollPane.setViewportView(table);
}
else
{
System.out.println("I'm in the else statement");
//don't show the table:
scrollPane.remove(table);
/* Already tried to use:
- revalidate and repaint the scrollPane
- revalidate and repaint the contentPane
- remove the entire scrollPane from the ContentPane
- remove the table from the scrollPane, then remove the scrollPane from the ContentPane
*/
//and show a label instead:
frame.getContentPane().add(lbl);
frame.getContentPane().repaint();
}
}
});
btnOk.setBounds(211, 47, 89, 23);
frame.getContentPane().add(btnOk);
}
}
You add the table to the panel:
panelRicerca.add(scrollPane);
Later you add the label to the panel:
panelRicerca.add(lblNoGiochi);
Nowhere do you remove the table pane from the panel, so it will always be displayed.
You need to either:
remove the table pane before adding the label
Use a CardLayout. The CardLayout allows you to swap components in the same panel so only one is ever visible. Read the Swing tutorial on How to Use CardLayout for more information.
Edit:
Well in my original answer I suggested you need to remove the table from the panel. Actually I meant "scroll pane" since you never add the table to the panel. Notice the code I posted is showed add the "scroll pane" to the panel. You were meant to do the opposite.
In your original code you added and removed the label from the same panel. My suggestion was to add/remove the scroll pane from the same panel.
Again the same concept, you could remove the table from the scroll pane. But again you add the table to the "viewport" of the scrollpane. So if you want to remove it you do the opposite. You remove it from the viewport of the scrollpane, by using setViewportView(null). This won't remove the scroll pane from the panel (which is still the easiest solution) but the table won't display in the scroll pane.
However, neither of the above suggestions will work in you demo code because you keep creating a new JScrollPane in your MouseListener so you don't have a reference to the scrollpane that you added to the frame. So the scroll pane variable needs to be an instance variable and you create the scroll pane in your constructor.
Also, don't use null layouts. Swing was designed to be used with layout managers. So the basic code when do dynamic layout changes is:
panel.remove(...);
panel.add(...);
panel.revalidate(); // to invoke layout manager
panel.repaint(); // repaint changes.
So the basic answer I was trying to give is that if your want to "remove" something, you need to do the opposite of what you did to add the component to the frame.

JTextArea.getText() not returning what it should (SWING)

I have the following code for a JScrollPane witha a JTextArea on it.
The purpose of this is to create a query and send it to a database via JDBC
// create the middle panel components
JTextArea display = new JTextArea(16, 58);
display.setLineWrap(true);
display.setEditable(true); // set textArea editable
JScrollPane scroll = new JScrollPane (display);
scroll.setBounds(19, 21, 487, 294);
scroll.setVerticalScrollBarPolicy (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
middlePanel.add(scroll, BorderLayout.CENTER);
//Add Textarea in to middle panel
middlePanel.add(scroll);
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(middlePanel);
this.setBtnFinishButton(new JButton("FINISH"));
this.getBtnFinishButton().addActionListener(new SaveQueryListener(display.getText(), this));
this.getBtnFinishButton().addFocusListener(new CreateQueryWindowFocusListener(this));
middlePanel.add(btnFinishButton, BorderLayout.SOUTH);
And the code for the listener "SaveQueryListener" is as follows
private String query;
private CreateQueryWindow cqw;
public SaveQueryListener(String query, CreateQueryWindow cqw) {
this.setQuery(query);
this.setCqw(cqw);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("The query is: "+query); //Use this to know what it is returning
new PostgreSQLJDBC(this.query);
}
The JDBC is working fine, as the other querys that I hard-coded are working fine (1 button for each query basically). But I can't get the text from this TextArea.
When I run the program, the console prints:
The query is:
Conecction Successfull
org.postgresql.util.PSQLException: No result from query. //Translated
Any ideas as to why the getText() is not returning what I type into the TextArea?
After looking at your code a second time, this obviously can't work:
this.getBtnFinishButton().addActionListener(new SaveQueryListener(display.getText(), this));
You're setting the text to be whatever value the text area has when you first create it. Obviously that's an empty string.
Something like this is probably needed:
private JTextArea view;
public SaveQueryListener(JTextArea view, CreateQueryWindow cqw) {
this.view = view;
this.setCqw(cqw);
}
#Override
public void actionPerformed(ActionEvent e) {
String query = view.getText();
System.out.println("The query is: "+query); //Use this to know what it is returning
new PostgreSQLJDBC(this.query);
}
And where you init the GUI:
this.getBtnFinishButton().addActionListener(new SaveQueryListener(display, this));

JList with ScrollPane auto-scroll bug

I have a JList with a ScrollPane. When i press a button, a new line is added to the JList.But the problem is that it doesn't scroll to the last element, but the second last element. Here is a portion of code used : There are no erros. Everything works good except this .
DefaultListModel<String> model = new DefaultListModel<String>();
JList<String> list = new JList<String>(model);
JPanel panel = new JPanel(new GridLayout(0,1));
panel.add(list);
scroll = new JScrollPane(panel);
JPanel p = new JPanel(new BorderLayout());
p.add(scroll, BorderLayout.CENTER);
p.add(buttonPanel, BorderLayout.SOUTH); // here are more button's including the one with the action described below
public void actionPerformed(ActionEvent e) {
list.setFont(new Font("Times new Roman", Font.PLAIN, 30));
model.add(list.getModel().getSize(), "Some text randomly"+ i++);
panel.repaint();panel.revalidate();
scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum());
}
I think that the actual repainting happens after this method has ended. Try calling the last line using SwingUtilities.invokeLater() like this:
SwingUtilities.invokeLater(new Runnable() { public void run() {
scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum(‌));
}
});
Beware while copy-pasting this into your IDE: There is a hidden character (zero-width non-joiner) in the HTML that is not allowed in your Java code. Just remove everything between the braces after getMaximum().
(In Java 8 you can use a Lambda expression to make this statement smaller and better readable.)

addTableModelListener do nothing when I recharge myScrollPane.getViewport()

I load a JScrollPane (with a JTable) when I load the application.
I have a TableModelListener to save changes when table changed.
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent evt) {
// UPDATE SQL into MDB
}
});
The UPDATE into MDB works fine.
So, I've a JTextField and a Jbutton too. When I write a date and I do click Jtable shows only the new records from MDB.
myButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myScroll.getViewport().remove(table); // Remove old table
// New SQL sentence
table = new JTable(data, columnNames);
myScroll.getViewport().add(table); // Load new table
}
});
Then, it works fine. Jtable show only matching record(s) from MDB.
But in this point, I explain my problem.
TableModelListener to save changes when table changed no longer works.
Only works with the initial JTable, but doesn't works with new JTable.
What am I doing wrong?
TableModelListener to save changes when table changed no longer works. Only works with the initial JTable, but doesn't works with new
JTable.
Yes, because you create a new JTable in this line:
#Override
public void actionPerformed(ActionEvent e) {
...
table = new JTable(data, columnNames); // <-- here
...
}
Consequently a new TableModel is created and your listener isn't attached to this new one but the previous one.
IMHO you should reconsider re-create the JTable every time the button is pressed. Generally speaking tables (and their models) are created just once and then developers work adding/deleting/updating the table model.
Take a close read to table model sections, starting with Creating a Table Model, of How to Use Tables tutorial.

JTable won't scroll in JScrollPane

I've been having trouble trying to get the table to scroll; it just won't. I've looked at other stack answers and tried them, but they aren't working; and I'm not sure if I have something conflicting with those solutions.
tableModel = new TableModel(); //Custom Table Model
table = new JTable();
table.setBorder(null);
table.setFillsViewportHeight(true);
table.setModel(tableModel);
JScrollPane tblScrollPane = new JScrollPane(table);
tblScrollPane.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
tblScrollPane.setBounds(245, 17, 560, 425);
frmServerAdministration.getContentPane().add(tblScrollPane);
EDIT: More info
So a window opens, which is the server program. Client programs connect to the server and when they do, a method is triggered in my table model class which adds a new row into the table. (I can see the row) Then at the end of that method it calls another but nothing changes in the ScrollPane. Do I need to do some kind of repainting? -
Server.updateTableScroll();
public static void updateTableScroll() {
System.out.println("Here"); //NOTE: I do see this printed out
int last = table.getModel().getRowCount() - 1;
Rectangle r = table.getCellRect(last, 0, true);
table.scrollRectToVisible(r);
}
EDIT 2: Thoughts
So in Eclipse I use Window Builder to make the GUI, and the following for loop will display the table with the scrollbar! But when I run the same addClient() method at another point, then the scroll bar won't appear.
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Server window = new Server();
window.frmServerAdministration.setVisible(true);
for(int i = 0; i < 20; i++){
tableModel.addClient(i, String.valueOf(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Instead of setBounds(), override getPreferredScrollableViewportSize(), as suggested here, and pack() the enclosing top-level container. Also, the API authors "recommend that you put the component in a JPanel and set the border on the JPanel."
Addendum: As a JTable listens to its TableModel, verify that the correct event is fired from the model. If you extend AbstractTableModel, one of the fireTableXxx() methods will be appropriate.
All I needed to do was call this after I added data (I'm very new to table models :P )
this.fireTableStructureChanged();

Categories