Can one Object "Listen" to another Object's "State"

  • (2 Pages)
  • +
  • 1
  • 2

19 Replies - 1159 Views - Last Post: 01 February 2013 - 10:20 AM Rate Topic: -----

#1 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 02:58 PM

I'm not entirely sure the topic is that descriptive so here comes a particularly lengthy explanation.

Problem setup
A 4 x 4 GridLayout arrangement of JButtons within a JPanel. The buttons each have a getState, setState method, wherein the state represents only one of 8 states (stored in an instance field within the subclassed JButton). The states are manipulated by the user with a simple click of a particular Jbutton. States cycle between 0, 1, and 2. States 3 through 7 are special conditions of state 2. By special conditions I mean that in order for a button to possess a state of 3 ~ 7 it must analyze the states of the surrounding buttons, the user can only cycle from 0 ~ 2, program logic/rules determine the remainder states 3 ~ 7.

My less than stellar solution
I would create a 4 x 4 two-dimensional array and place within it the states, passing the entire array through to the actionPerformed method of a particular JButton in order to determine whether it should be given states 3 ~ 7 (according to a set of prescribed rules). However, the limitation here is that a condition can occur wherein changing the state of the button that was clicked can also change the state of one of the 8 (or less if it happens to be at a corner/border) outlying buttons, meaning I would have to make the array an array of these custom JButtons in order to be able to manipulate their values at will. It seems like a lot of memory overhead to me, perhaps I'm wrong.

My hypothetical solution (as I've no idea whether or not it's even possible)
To somehow code a Listener, most likely a PropertyChangeListener that can somehow implement a form of recursion to dynamically update the state of a JButton, even if it wasn't clicked, due to its neighbor being clicked. Essentially creating a "chaining" effect wherein the buttons would update themselves "intelligently."

Conclusion
I realize this is a pretty abstract way of describing the problem. The problem, at least from my viewpoint, is currently more abstract than practical. The logic by which my particular problem description constrains me is less important than the general idea of constraining two or more distinct objects to a set of prescribed rules and making them aware of one another in some regard.

I appreciate any imagination you can spare.

Is This A Good Question/Topic? 0
  • +

Replies To: Can one Object "Listen" to another Object's "State"

#2 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 9484
  • View blog
  • Posts: 35,758
  • Joined: 12-June 08

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:02 PM

Are you trying to make a 'game of life' simulator?
Was This Post Helpful? 0
  • +
  • -

#3 GregBrannon  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2205
  • View blog
  • Posts: 5,239
  • Joined: 10-September 10

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:08 PM

You might consider using an Observer/Observable design pattern. Dick Baldwin's tutorials cover the subject well (#200 on the page) in a non-graphical application, but you can adapt to a GUI. I think it would work well for what you're trying to do (at least as I understand it).

And I agree with modi123_1, what you're describing sounds similar to a GoL simulation. You might Google that to get other ideas.

This post has been edited by GregBrannon: 29 January 2013 - 03:09 PM

Was This Post Helpful? 1
  • +
  • -

#4 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:20 PM

@modi123_1: No it's not a game of life simulator, albeit the logic is somewhat similar to that I suppose. The difference would be that though I used the term "recursion" the effect of altering states would never propagate beyond the 8 or less outlying buttons that are in contact with the one that was clicked. However, those 8 need to be able to change somehow.

@GregBrannon: Thanks for the link.
Was This Post Helpful? 0
  • +
  • -

#5 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 9484
  • View blog
  • Posts: 35,758
  • Joined: 12-June 08

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:22 PM

.... and these buttons - do you really need to click on them or just provide a convenient way to trigger an event?
Was This Post Helpful? 0
  • +
  • -

#6 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:30 PM

The buttons require a click as user interaction is presumed to be through a mouse, yes. Furthermore, the user must be able to affect the state of each button unless one of them happens to have setEnabled(false). In which case its state is locked. This is not a click once and forget sort of effect (like game of life). The button states is/are constantly updated by the user's click events.

@GregBrannon: What I gather from the Observer/Observable, and please correct me before my brain machinates any further, is that essentially I would be making every button an Observer and an Observable. Wherein, the Observers for a particular button would be its 8 (or less) outlying neighbors?

This post has been edited by grimpirate: 29 January 2013 - 03:34 PM

Was This Post Helpful? 0
  • +
  • -

#7 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 9484
  • View blog
  • Posts: 35,758
  • Joined: 12-June 08

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:32 PM

Curiouser and curiouser.. to what end is the user's interaction? That is to say what is the app for/do? (totally irrelevant to the question.. just being a nosy nelly).
Was This Post Helpful? 0
  • +
  • -

#8 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:43 PM

It's part of the logic behind a puzzle game modi123_1. The user's job is to manipulate the "board" according to deductive reasoning; thusly solving the puzzle.
Was This Post Helpful? 0
  • +
  • -

#9 CasiOo  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1413
  • View blog
  • Posts: 3,133
  • Joined: 05-April 11

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 03:59 PM

Is this what you are calling "memory overhead" ?
public enum PuzzleState {
	state1, state2, state3
}

public MyButton extends JButton {
	private PuzzleState state;
	
	public MyButton() {
		super();
		state = PuzzleState.state1;
	}
	
	public PuzzleState getState() {
		return state;
	}
	
	public void setState(PuzzleState state) {
		this.state = state;
	}
}


Was This Post Helpful? 0
  • +
  • -

#10 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 04:12 PM

Somewhat, though I'm calling a two-dimensional 4 x 4 array, for a total of 16 of those buttons, overhead. The buttons also include custom painting and listeners. Maybe it isn't, just seems like there's a better way, and given what GregBrannon pointed out to me, that seems to be it.
Was This Post Helpful? 0
  • +
  • -

#11 CasiOo  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1413
  • View blog
  • Posts: 3,133
  • Joined: 05-April 11

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 04:20 PM

View Postgrimpirate, on 29 January 2013 - 11:12 PM, said:

Somewhat, though I'm calling a two-dimensional 4 x 4 array, for a total of 16 of those buttons, overhead. The buttons also include custom painting and listeners. Maybe it isn't, just seems like there's a better way, and given what GregBrannon pointed out to me, that seems to be it.


You think you will use less memory by implementing the observer pattern? In this case I do not believe you will save any memory at all
Was This Post Helpful? 0
  • +
  • -

#12 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 04:54 PM

Well without a benchmark of some sort the point is moot. However, at the very least the Observer/Observable pattern seems like it would provide for code that's more readily understood.
Was This Post Helpful? 0
  • +
  • -

#13 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 5900
  • View blog
  • Posts: 12,803
  • Joined: 16-October 07

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 07:33 PM

The trick is not getting all it spagettied up. Make a central location responsible for the communication of messages. Make each object responsible for it's own concerns.

I couldn't think of a really simple example, so I came up with this:
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;

class ButtonState {
	public final int x, y;
	public final boolean status;
	public ButtonState(int x, int y, boolean status) {
		this.x=x; this.y=y; this.status=status;
	}
}

class GameButton extends JButton {
	public final int x, y;
	private boolean status;
	public GameButton(int x, int y) { this.x=x; this.y=y; this.setStatus(false); }
	
	public ButtonState getState() { return new ButtonState(x,y,status); }

	public void setStatus(boolean value) {
		this.status = value;
		this.setBackground(this.status ? Color.YELLOW : Color.BLACK);
	}
	
	public ButtonState toggleState() {
		setStatus(!this.status);
		return getState();
	}

	private boolean isNeightbor(ButtonState bs) {
		if (bs.x==this.x && bs.y==this.y) { return false; }
		return  Math.abs(bs.x-this.x)<2 && Math.abs(bs.y-this.y)<2;
	}
	
	public void notifyButtonStateChange(ButtonState bs) {
		if (isNeightbor(bs)) { setStatus(!this.status); }
	}
}


public class ButtonStateShare extends JFrame {
	private final int ROWS = 5, COLS = 5;
	private final GameButton [] cells;

	public ButtonStateShare() {
		cells = new GameButton[ROWS * COLS];
		setLayout(new GridLayout(ROWS,COLS,0,0));
		setBackground(Color.green);
		ButtonListener bl = new ButtonListener();
		int i = 0;
		for(int row=0; row<ROWS; row++) {
			for(int col=0; col<COLS; col++) {
				GameButton b = new GameButton(row, col);
				b.addActionListener(bl);
				this.cells[i++] = b;
				this.add(B)/>;
			}
		}
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(500,500);
	}
	
	private void setButtonState(int x, int y, boolean value) {
		this.cells[x * ROWS + y].setStatus(value);
	}
	
	private void notifyCells(ButtonState ba) {
		for(GameButton b : this.cells) {
			b.notifyButtonStateChange(ba);
		}
	}

	public class ButtonListener implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			GameButton b = (GameButton)e.getSource();
			notifyCells(b.toggleState());
		}
	}
}



Basically, each button tells the form about its click, the form just tells every button about that click, without worrying about it itself. It's up to the button to decide what to do with that information.

It's actually kind of fun to plink on.

Don't know if this helps, but it was amusing.
Was This Post Helpful? 3
  • +
  • -

#14 CasiOo  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1413
  • View blog
  • Posts: 3,133
  • Joined: 05-April 11

Re: Can one Object "Listen" to another Object's "State"

Posted 29 January 2013 - 09:13 PM

Looking at baavgai's code makes me want to make an observer version of it
While thinking about the implementation I wondered why Oracle never made the observer interface generic
I hate casting the pushed object, it is ugly and (sometimes) unsafe

So! I know this is kinda off-topic, but all this talk about observers in here made me wanna make a generic observer implementation
I'm also interested in the solution grimpirate comes up with, since he is also gonna use observers (from the looks of it)

/**
 * 
 * @author CasiOo @ dreamincode.net
 *
 * @param <T> Sender type
 * @param <E> Data type
 */
public interface GenericObserver<T, E> {
	public void update(T sender, E data);
}



import java.util.ArrayList;

/**
 * 
 * @author CasiOo @ dreamincode.net
 *
 * @param <T> Observer type
 * @param <K> Sender type
 * @param <E> Data type
 */
public class GenericObservable<T extends GenericObserver<K, E>, K, E> {
	private ArrayList<T> observers = new ArrayList<T>();
	
	public void addObserver(T observer) {
		observers.add(observer);
	}
	
	public void removeObserver(T observer) {
		observers.remove(observer);
	}
	
	public void notifyObservers(K sender, E data) {
		for (T observer : observers)
			observer.update(sender, data);
	}
}



Testing to see if it works

public class Test {

	public static void main(String[] args) {
		new Test();
	}
	
	public Test() {
		GenericObservable<MyObserver, Test, String> observable = new GenericObservable<MyObserver, Test, String>();
		MyObserver observer = new MyObserver();
		observable.addObserver(observer);
		
		observable.notifyObservers(this, "Hello World");
	}
	
	@Override
	public String toString() {
		return "Test class";
	}
	
	public class MyObserver implements GenericObserver<Test, String> {
		public void update(Test sender, String data) {
			System.out.println("[Sender:" + sender + "]");
			System.out.println("[Data:" + data + "]");
		}
	}
}



Was This Post Helpful? 1
  • +
  • -

#15 grimpirate  Icon User is offline

  • Pirate King
  • member icon

Reputation: 149
  • View blog
  • Posts: 714
  • Joined: 03-August 06

Re: Can one Object "Listen" to another Object's "State"

Posted 30 January 2013 - 08:37 AM

@baavgai: Just wanted to make sure I'm understanding a couple of aspects of the code you posted. As I understand it when the user clicks one of the buttons you basically notify the whole board of the click, and then each button on the board checks itself to see if it is in fact a neighbor of the one that was clicked?
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2