?
Solved

Java GUI with repaint problems... should be simple.

Posted on 2009-05-20
28
Medium Priority
?
1,280 Views
Last Modified: 2013-12-22
ok, I am running into a very stupid problem, and most likely because I am a bit rusty with Java.

I have two forms, both designed in NetBeans...

first one have a JList and a combo box. the combo box, on properties change, triggers a method call, which then would go to a ODBC connector, asking for information and add those information to the JList box.

i have another button on this form, basically, it is an edit button, which allows me to select items from the JList box and edit them.

Due to the complexity, the edit button pops up a new Jframe, with its own input boxes. At the end of the day, there is a 'DONE" button on this new JFrame, and when pushed, it updates the Database via ODBC.

Now the problem arises, for some strange reasons, I cannot update the jList box on my first form.

I have passed the frame along and called it localCopyMainWindow
and i've called it to repaint(), I've even attempted to call the method.

(A side note, if I leave an JOptionPane.showMessageBox in the method, it works nicely, just an annoying popup)

any thoughts?
0
Comment
Question by:SamsonChung
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 15
  • 13
28 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 24431505
You need to update gui components on the EDT. Use the well-documented SwingWorker
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 2000 total points
ID: 24431512
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24431714
Ok, I am a bit confused...

that's an underlying thread right?

so it is a Thread that updates the SWING?

So I can't force an update like I was doing?
0
Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

 
LVL 6

Author Comment

by:SamsonChung
ID: 24431735
Oh, as a side note, I didn't need it to be 'multithreaded' yet.

I am just wondering if I am forgetting something, to update the JList object.

it is just some strange reasons that the GUI portion would not 'refresh'
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24432307
>>Oh, as a side note, I didn't need it to be 'multithreaded' yet.

You do i'm afraid, or it almost certainly won't work properly

The odbc bit should be done on the worker thread and one of its methods would do the gui update
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24432841
i see..

So Java's GUI side is better done with underlying threads then actual Events triggers.

While Events are good, for data manipulation, would you suggest that all semi-automatic tasks be done via background threads?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24433369
>>While Events are good, for data manipulation,

Actually they're mainly good for visual stuff.


>>would you suggest that all semi-automatic tasks be done via background threads?

Processing, particularly intensive processing, should be done in background threads. This means they should never be done *directly* in event handlers - you would start the background thread there only
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24434484
Ok, CEHJ

I have tried this...

Added a thread, the thread goes in and do the SQL db stuff, then it is paused.
When the second form is disposed, it re-activate the thread with a 120 millisec delay.

There is no change. the main window did not get refresh, nor did the JList got refreshed.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24434596
OK. Please post your new SwingWorker code and i'll see what we can do
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24434620
Its not 'swingworker' per se...

 I just went with an normal Thread.....

if you suggest that I should construct a SwingWorker, I'll attempt that.


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package webctcrosslister;
 
import java.sql.Connection;
 
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import webctcrosslister.gui.MainWindow;
 
/**
 *
 * @author Samson Chung
 */
public class mwListUpdateThread extends Thread {
 
	public mwListUpdateThread(MainWindow aThis){
		this.localCopyMW = aThis;
		this.killSwitch = true;
		this.active = true;
		this.sleepMillis = 0;
	}
 
	@Override
	public void run(){
		while (killSwitch){
			while (active){
				try {
					this.sleep(this.sleepMillis);
				} catch (InterruptedException ex) {
					Logger.getLogger(mwListUpdateThread.class.getName()).log(Level.SEVERE, null, ex);
				}
				String selectedTerm = this.localCopyMW.getSelectedItem();
				try{
					Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
					Connection c = DriverManager.getConnection( "jdbc:odbc:webctCrosslister", "", "" );
					Statement stmnt = c.createStatement();
					String query = "SELECT * FROM CrossedCourses WHERE Term = '" + selectedTerm + "';";
					//JOptionPane.showMessageDialog(this, query);
					ResultSet rs = stmnt.executeQuery( query );
					Vector test1 = new Vector();
					while( rs.next() ){
						String temp =  rs.getString("xlistCode")  + "  [" + rs.getString("Results") + "]  " + rs.getString("CourseName");
						test1.add(temp);
					}
					//String tempArray[] = (String[]) test1.toArray();
					this.localCopyMW.setLstDisplay(test1);
 
					c.close();
					//rs.close();
					stmnt.close();
				}catch(Exception e){
					e.printStackTrace();
				}
				this.localCopyMW.repaint();
				this.active = false;
				this.sleepMillis = 0;
			}
		}
	}
	
	/***************************************************************************
	 * input Secs, method will times it by 60
	 * 
	 **************************************************************************/
	public void setSleepMillis(int sec){
		this.sleepMillis = sec * 60;
	}
 
	public void setEnabled(boolean in){
		this.active = in;
	}
	public void endThread(){
		this.active = false;
		this.killSwitch = false;
	}
 
	private MainWindow localCopyMW;
	private boolean active;
	private boolean killSwitch;
	private int sleepMillis;
}

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24434724
>>this.localCopyMW.setLstDisplay(test1);

I assume that's you updating the gui? If so, you're updating it on the wrong thread. That's why it's better to use a SwingWorker ;-)
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24434757
o_O??

localCopyMW.setLstDisplay(Vector vect); is a method in MainWindow Class.....

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24434814
>>is a method in MainWindow Class.....

...which does this?:

>>Now the problem arises, for some strange reasons, I cannot update the jList box on my first form.
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24434825
yep.

the method then goes in and say

this.jListbox.setDataList(test1);
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24434835
er, I meant setListData...
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24434862
That's why i said:

>>I assume that's you updating the gui?

- because that's what you/re doing. You need to update the gui on the EDT. SwingWorker is specifically designed to make that easier and to coordinate threads
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24435570
Ok,

I'll give SwingWorker a quick try....

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24435590
If you wanted to do it in the code you've got you could call EventQueue.invokeLater, but that's messier
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24444712
Ok,

Now I've recoded the thread class in SwingWorker.

do I have to create a new one everyone I want to 'execute()' it?
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package webctcrosslister;
 
import java.sql.Connection;
 
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Vector;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;
import webctcrosslister.gui.MainWindow;
 
/**
 *
 * @author Samson Chung
 */
public class mwListUpdateThread extends SwingWorker<Vector, Integer> {
 
	public mwListUpdateThread(MainWindow aThis){
		this.localCopyMW = aThis;
		this.killSwitch = true;
		this.active = true;
		this.sleepMillis = 0;
	}
 
	@Override
	public Vector doInBackground(){
		String selectedTerm = this.localCopyMW.getSelectedItem();
		Vector test1 = new Vector();
		try{
			Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
			Connection c = DriverManager.getConnection( "jdbc:odbc:webctCrosslister", "", "" );
			Statement stmnt = c.createStatement();
			String query = "SELECT * FROM CrossedCourses WHERE Term = '" + selectedTerm + "';";
			//JOptionPane.showMessageDialog(this, query);
			ResultSet rs = stmnt.executeQuery( query );
 
			while( rs.next() ){
				String temp =  rs.getString("xlistCode")  + "  [" + rs.getString("Results") + "]  " + rs.getString("CourseName");
				test1.add(temp);
			}
			c.close();
			//rs.close();
			stmnt.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		return test1;
	}
		
	@Override
	public void done(){
		try {
			this.localCopyMW.setLstDisplay(get());
		} catch (InterruptedException ex) {
			Logger.getLogger(mwListUpdateThread.class.getName()).log(Level.SEVERE, null, ex);
		} catch (ExecutionException ex) {
			Logger.getLogger(mwListUpdateThread.class.getName()).log(Level.SEVERE, null, ex);
		}
	}
 
	private MainWindow localCopyMW;
	private boolean active;
	private boolean killSwitch;
	private int sleepMillis;
}

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24444807
That looks good. Yes, create a new one every time you want to do an upate. Is it working?
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24444938
same problem.

When the second form is disposed, it calls the first form's method which launches the SwingWorker thread..

but no change whatsoever on the gui side.
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24444950
Here is a snippet from MainWindow class....

I got a feeling i am doing something REALLY Stupid ;)

(* A small note, if i were to generate a POP up box, it will actually refresh the GUI)
public class MainWindow extends javax.swing.JFrame {
 
    /** Creates new form MainWindow */
    public MainWindow() {
        initComponents();
		this.updateForm();
    }
 
	public String getSelectedItem() {
		return this.cmbTerm.getSelectedItem().toString();
	}
 
	public void setLstDisplay(Vector test1) {
		this.lstDisplay.setListData(test1);
	}
	public void updateForm() {
		(new mwListUpdateThread(this)).execute();
	}

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24444978
You should be setting a new ListModel on the List with that Vector - is that what you're doing?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24444996
IOW, what does this do:

>>setListData(test1);

and is it getting called?
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24445179
For some strange reasons, the Data is not updated.

Vector test1's data is old data.

Would that have something to do with JDBC connector to ODBC being 'not fast enough' ?

ie, I just did an update before doing this select, on the same table. Should I give it some time for the DATA to be updated?
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24445239
Thanks,

 I found out why..

I forgot to close the Query driver..... of course the Data will be updated, only after the method have completely finished and resources released.

However, since we are already doing a secondary Select, it never got the updated information.

HAHAHAHAHA <- Went insane....
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24445484
OK. :-)
0
 
LVL 6

Author Comment

by:SamsonChung
ID: 24449887
stupid cursors!!!!
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand column That will then direct you to their download page. From that p…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses
Course of the Month10 days, 23 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question