Java swing help needed

dropadrop

Gawd
Joined
Feb 28, 2001
Messages
569
I have a software project I'm doing for university, and I just can't figure out how I could get one part of the user-interface to work. The program consists of a server, and several clients that contact the server. The clients are actually people who want to take a break from work, and the server should coordinate that enough people are working all the time.

So the program transpheres a file over the network to the server which updates an int field which tells the client program if he can go on break or not. (if there are too many people on break he ends up in a que). The idea is that an image on the interface refreshes after each connection, and the image that comes up is dependent on the status... (I hope I'm not explaining this in a complicated way) This code is quite messy as It's still under work.

Code:
/**
 * The user interface of the program
 **/

import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;

public class KLiittyma  {	
	
	public static void main(String[] args) {

			Raamit frame = new Raamit();
	        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        frame.show();
	}
}

/**
 * Frame with a panel
 **/

class Raamit extends JFrame {
	
	public Raamit() {
		
		setTitle("Tauko");
		setSize(120, 400);
		
		// add the panel
		TilannePanel panel = new TilannePanel();
		Container contentPane = getContentPane();
		contentPane.add(panel);
	}
	
	/** 
    * set up the panel
    **/
    
    class TilannePanel extends JPanel  {
	
	public TilannePanel() {
		
		Moottori yhteys = new Moottori();
		
		// an image that should update when the status changes
		jono = new JLabel(yhteys.annaIkoni(), JLabel.CENTER);
		otsikko = new JLabel("Jonotilanne");
		// an empty gif to give space
		gap = new JLabel(yhteys.annaRako());
		JButton taukoNappi = new JButton("Tauko");
			
		// add the components
		add(jono);
		add(otsikko);
		add(gap);
		add(taukoNappi);
		
		// actions...
		ToggleAction taukoToimintaa = new ToggleAction(yhteys, 1);
		
		taukoNappi.addActionListener(taukoToimintaa);
	}
	
	// panel components
	private JLabel jono;
	private JLabel otsikko;
	private JLabel gap;
	private Image image;
	private Image image2;
	
	// reacting to events
	private class ToggleAction implements ActionListener {
		public ToggleAction(Moottori yhteys, int nappi) {
			
			moottori = yhteys;
			pyynto = nappi;
		}
		
		// asks for permission to leave for a break or return
		public void actionPerformed(ActionEvent event) {
			
			// if status is ready
			if (moottori.annaStatus() < 2) {
				moottori.siirra(1);
			}
                        // allready on break, return to work
			else
			moottori.siirra(2);

		}
		
		private Moottori moottori;
		private int pyynto;
	}
   }
 }

I'm quite aware that I'll probably have to change the code quite alot... Most of the real action is taken care of by the class Moottori. Moottori both loads the images from the disk (and returns them as needed) and takes care of the network connections ect.

During all the java courses I've taken we've used AWT, but for this project I decided to use swing (as awt is quite old). I just can't seem to get my head around all the details (in time atleast).
:(
 
The user-interface includes a JLabel with an image, and the idea would be to have the image change refresh everytime a certain value in the other class updates.

When you push the button on the interface it causes the engine behind to connect to the server and try to change the status of the client. Currently when you push the button the server side works fine, and it updates this value. The server also returns the package correctly changing the clients status. What I can't get it to do is to refresh the image on the JLabel.

Code:
jono = new JLabel(yhteys.annaIkoni(), JLabel.CENTER);

This is the line that creates the icon. The icon that is returned depends on the status. So basicly it's working fine, I would just need this to be done everytime the button has been pressed. (and possibly if I put a timer then everytime the timer has updated data at the server)

While we are at it I would like the text on the JButton to change depending on the status too. When the client is not on a break it could say "break" and when he's on break it could read "return" (or something similar...) The principle is the same as with the JLabel though.

I updated the code a bit, should be slightly clearer
 
intelbrain said:
i got confused by your word choices so gave up.
Oh come on, that's what makes it fun :p

As for me, here's my best guess.

A simple answer is to add a method to the class TilannePanel, such as:

Code:
//** Added method in the Class TilannePanel
private void switchState(int state)
{
	// Here you take your components and change their values. Such as:
	switch (state)
	{
	case 1:
		taukoNappi.setLabel("This is the text in the JButton for state 1");
		break;
	case 2:
		taukoNappi.setLabel("This is the text in the JButton for state 2");
		break;
	}
	/* And so you change any and all components you want to during a
	 * state change.
	 */
}

All you have to add afterwards is something in ToggleAction's actionPerformed method.

Code:
//asks for permission to leave for a break or return
public void actionPerformed(ActionEvent event)
{
//if status is ready
	if (moottori.annaStatus() < 2)
	{
		moottori.siirra(1);
		//** Here is a little bit of code added
		switchState(1);
	}
	// allready on break, return to work
	else
	{
		moottori.siirra(2);
		//** Here is a little bit of code added
		switchState(2);
	}
}

Hopefully this will help a bit. If there are any more questions feel free to ask away.
 
intelbrain said:
i got confused by your word choices so gave up.

Sorry, english is my third language, and the program is written mainly to be clear in finnish... I translated the comments though! :)

Nemezer said:
Hopefully this will help a bit. If there are any more questions feel free to ask away.

Thanks! This would work, but there is one problem. When the client machine asks for permission to go on a break he might not get it. If the amount of workers on break is too high he will end up in a que.

So basicly there are three states, "ready", "on break" or "in que for a break". This solution would assume that by pressing the button you can allways leave for a break...

The user interface creates a class that we could call the Engine() (Moottori()). This creates a class that contains the clients username, status ect. If the status is ready and he presses the button he will be requesting to go on a break. At the servers end it checks the situation and either lets him go for a coffee or puts him in the que. Once the instance with the user information is returned, the method should somehow update this.

unless...

If I made the method return an int value:

Code:
//asks for permission to leave for a break or return
public void actionPerformed(ActionEvent event)
{

int temp;

//if status is ready
	if (moottori.annaStatus() < 2)
	{
		temp = moottori.siirra(1);
		//** Here is a little bit of code added
		switchState(temp);
	}
	// allready on break, return to work
	else
	{
		temp = moottori.siirra(2);
		//** Here is a little bit of code added
		switchState(temp);
	}
}

Would that work? The method returns the result... :eek:
 
I can dig it.

There are two solutions to this problem. The easy way is, you create your third state "in queue" which starts a Timer on the client side. The Timer makes a query to the server every 30 seconds to ask if he can be on break now. Then there's the harder solution, which is to make the server communicate to the client to tell him he's now on break.

I assume you'll take the easy way out ;)

Code:
private void inQueue()
{
	new Timer(30000, new ActionListener()
	{
		public void actionPerformed(ActionEvent event)
		{
			/*
			 * Add code here that will make the client ask the server
			 * again if he can take a break.
			 */

			boolean hurrayICanGoOnABreakNow = // fill in the blank.

			if (hurrayICanGoOnABreakNow)
				((Timer) event.getSource()).stop();
			else
				; //Do absolutely nothing. The Timer will be back here in 30 seconds.
		}
	}).start();
}

Here's a method that you may want to put in your TilannePanel class. The method is rather empty but hopefully you can fill in the blanks. In the case that the user clicks for a break and gets to go in the queue, you should call this method. It will create a Timer object that will allow you to call the server every 30000 milliseconds (30 seconds).

Note that if you wish to pursue this path, you would do well to allow the user the option to remove himself from the queue. Yet another feature I guess...

Anyway depending on how you built your engine, you may not want to go down that path. So the question is, can the server communicate to the client or is only the client able to initiate contact with the server?

As always, I'm ready to help.
 
Thanks alot, your help has been of great assistance!

I have the button working now apart from the timer. I was thinking of adding a field that shows the current situation on the servers side. Apart from the client software being able to ask for a break or return to work, I also have methods ready to just check the amount of free places in the que. The idea would be that the client does this every 2 - 5 minutes automatically. At the same time as it would update the image with the servers status, it would also check if there is a change in the clients status. (from que to break, or if I have time to implement it the server could kick out idleing clients)

I still have a problem with the user interface though. The method for the button was very handy, but I could'nt find something similar for updating the icon on the JLabel. I went through the JLabels API description, and did'nt see anything like "updateImage(icon new);"

I tried adding this method to the panel:

Code:
	private void switchImage() {
		
		jono = new JLabel(yhteys.annaIkoni(), JLabel.CENTER);
	}

yhteys.annaIkoni() contacts the "engine" which returns an icon depending on the status. I also added this to the actionlistener:

Code:
		public void actionPerformed(ActionEvent event) {
			
			int temp;
			
			// jos valmiina tai eka yhteys
			if (moottori.annaStatus() < 2) {
				temp = moottori.siirra(1);
				switchState(temp);
				switchImage();
			}
			else
			temp = moottori.siirra(2);
			switchState(temp);
			switchImage();

Should I be using something else then the JLabel class for the image, or is there a way to update the image?

edit: Found something called ImageObserver and imageUpdate, will look into it.

edit2: Wow, it was alot easier then I thought!

Code:
	private void switchImage() {
		
		jono.setIcon(yhteys.annaIkoni());
	}

Code:
		public void actionPerformed(ActionEvent event) {
			
			int temp;
			
			// jos valmiina tai eka yhteys
			if (moottori.annaStatus() < 2) {
				temp = moottori.siirra(1);
				switchState(temp);
				switchImage();
			}
			else
			temp = moottori.siirra(2);
			switchState(temp);
			switchImage();

		}
 
Back
Top