Solved

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

Posted on 2009-05-20
28
1,266 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
  • 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 500 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
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 will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

747 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now