Swing - Ensuring the UI responds and updates...
I have an application that is not responding (as quickly as I'd like it to) after events occur.
One example is a JButton that calls for a JDialog to be displayed. When the JDialog is closed, the Application hesitates before repainting itself, leaving a gray area as an outline of where the JDialog was visible.
Tracing the events...
When the JDialog OK Button is pressed, a task is performed and then the JDialog is set to close.
In the InputDialog.java file I have the actionPerformed method:
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == okButton)
{
String input = textField.getText();
applicaion.addInputToJTable(input);
setVisible(false);
this.dispose();
}
}
When the JDialog closes, there is a gray area that that is not repainted right away. Well, sometimes it is, sometimes it isn't.
How do I ensure this is always repainted quickly when the JDialog is closed.
I modified the code in the call to the application addInputToJTable() method to be handled on a separate thread to do any busy work, although it's not really any hard work. And added the SwingUtilities.invokeLater() method to this separate thread to ensure the adding to the JTable was inoked on the EventQueue.
In the Application.java file I have the following method:
public void addInputToJTable(String input)
{
Thread t = new Thread(new Runnable()
{
public void run()
{
if (accept(input))
{
Vector<Object> rowData = new Vector<Object>();
rowData.add(input);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
myTableModel.addRow(rowData);
}
});
}
}
});
t.start();
}
I still get the gray area. ny ideas?
[1931 byte] By [
-Deba] at [2007-11-26 23:15:23]

# 1
It's pointless to start a new thread and then hook back onto the EDT in your "addInputToJTable()" method - unless your "accept()" method is time-consuming.
# 2
The accept method has a call to a Native method which I think might tie up the UI. The native call involves checking contents and properties in a File -- and depending on the File properties there may be 2 or 3 additional calls to Native methods before returning from the accept().
How time consuming should a method be to start a new thread anyway?
I guess if I'm not sure of the length of time to execute a method, I've separated it from the EDT.
Can you help with the JDialog showing the gray -- or getting it to not show the gray in between?
I have quite a few JDialogs that are shown when a menu item is selected or a button is pressed... and I'd like to try and "clean" that up a bit, if I can.
There are delays in displaying the JDialog -- sometimes I doubt whether or not I clicked the button because it takes longer than I would think to display it. Not sure how to fix that either..
Then there's the showing the gray in the main application as the JDialog is closed.
Any advice would be great... :o)
-Deba at 2007-7-10 14:15:06 >

# 3
I can't see anything obvious from that code that will cause problems - you're right in performing the "accept()" call away from the EDT if it involves file access. Might be an idea to give the method a name that gives a better hint as to its implications though - eg "verifyFile()" or something.
All I can offer at the moment is the statement that a grey area like you're seeing is nearly always a time-consuming piece of code being executed on the EDT, holding off a repaint until it's complete. If you read between the lines there, it may not even be one of your bits of code that's doing it - it's possible that some internal Swing code is just taking a bit of time.
# 4
Thanks for responding..
If I'm correct the actionPerformed() occurs in the EDT, the addInputToJTable() is set off into a sepearate thread, so the setVisible() and dispose() should occur right away.
Not sure what would be tieing up the EDT though... Sometimes the JDialog closes and there's no issue, other times, it's an just an obvious delay...
Thanks again...
-Deba at 2007-7-10 14:15:06 >

# 5
If I'm correct the actionPerformed() occurs in the EDT, the addInputToJTable() is set off into a sepearate thread, so the setVisible() and dispose() should occur right away.
That's pretty much correct, the caveat being that firing the new thread firstly incurs a slight cost but also may result in some of the new thread being executed before returning - but, in practical terms, you're right.
However, the bit you're worried about isn't the delay before setVisible() and dispose(), but the delay between those calls and the subsequent repaint of the parent frame.
# 6
Is it a matter of reversing the calls...
Then perhaps if I reverse the two lines --addInputToJTable() and setVisible(false) -- the JDialog would not be visible, the repaint() would be called, then the Thread would be launched before the JDialog is disposed of...
Would setting off a new Thread be enough to cause this?
I have other methods doing somewhat of the same handling ... do you have any advice of what should be set to a new Thread to be handled and what is unnecessary?
I'm not really happy with the way the application is displaying JDialogs, and returning....
Should creating the JDialog be done on the EDT each time... would it help if I created the JDialog on a separate thread and then called it to be setVisible from the EDT?
-Deba at 2007-7-10 14:15:06 >

# 7
More help needed...
I'cannot seem to get the gray rectangle to go away. There are quite a few
places where I have similiar code, but the most "sluggish" is as follows:
The main application is a JFrame with a JTable and a JButton (amongst other
things). The actionPerformed() for this JButton displays a JDialog
containing a JTable with data.
Basically what I am doing is pressing a button on the main application
to display a dialog containing a table with data populated from a
database. There is one column in this table and it contains rows of
Strings. I can then select a row from it to add to the main table.
This SearchDialog stays visible so I can go back and forth selecting
one row at a time to be added to the main JTable.
There are 3 files:
Application.java, SearchDialog.java, InputNameDialog.java
The Application has the following code for handling the button
events. It creates the searchDialog.
[Application.java]
public void actionPerformed(ActionEvent e){
if (e.getSource() == displaySearchDialogButton)
{
searchDialog = new SearchDialog(this);
}
}
When you select a row from the JTable in the SearchDialog, the
MouseListener responds to the event.
[SearchDialog.java]
public void mousePressed(MouseEvent e){
int rowIndex = table.getSelectedRow();
int columnIndex = table.getSelectedColumn();
Object selectedItem = table.getModel().getValueAt(rowIndex, columnIndex);
application.handleSelectedItem(selectedItem);
}
The application is then passed the selectedItem to be handled. If a name
is required, the InputNameDialog is displayed to obtain this information.
Otherwise the Application adds the selectedItem to its JTable.
There is some processing to do with the selectedItem which could be
time consuming so I'll shorten that to doBusyWork.
[Application.java]
public void handleSelectedItem(Object selectedItem){
if (requiresName)
{
InputNameDialog dialog = new InputNameDialog(this, selectedItem);
}
else
{
// Add data to table without a name specified.
Vector<Object> rowData = new Vector<Object>();
rowData.add("");
rowData.add(selectedItem);
((DefaultTableModel)mainTable.getModel()).addRow(rowData);
Thread t = new Thread(new Runnable()
{
doBusyWork(selectedItem);
});
t.start();
}
}
The InputNameDialog contains a JTextField where the I can enter
a Name, and click Ok or Cancel.
If I enter a name and select the Ok button, both the name and
selectedItem are passed to the application to be handled.
Cancel, simple disposes of the InputNameDialog and neither the name
nor the selectedItem are handled.
[InputNameDialog.java]
public void actionPerformed(ActionEvent e){
if (e.getSource() == okButton)
{
String name = textfield.getText();
application.handleNameAndSelectedItem(name, selectedItem);
}
dispose();
}
The Application then adds the data to its JTable, and brings the
SearchDialog back to the front so I can select another row.
Again there is some processing to do with the selectedItem which
could be time.
[Application.java]
public void handleNameAndSelectedItem(String name, Object selectedItem){
Vector<Object> rowData = new Vector<Object>();
rowData.add(name);
rowData.add(selectedItem);
((DefaultTableModel)mainTable.getModel()).addRow(rowData);
searchDialog.textfield.requestFocus();
searchDialog.setVisible(true);
Thread t = new Thread(new Runnable()
{
doBusyWork(selectedItem);
});
t.start();
}
The SearchDialog is displayed. I can select a row and add it
to the table if no name is required. The focus stays on the
SearchDialog and there's no repaining issues.
However, if I need to display the InputNameDialog, when I
select the Ok button, there is a gray rectangle behind the
closing InputNameDialog -- and as the SearchDialog comes back
to the front, the SearchDialog isn't repainted immediately.
You can see a gray/tan color on the area of the SearchDialog that
was covered by the Application.
I don't see anything that is holding up the EventQueue and I
need this to update smoother.
Help ?
-Deba at 2007-7-10 14:15:06 >

