Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Modified JTabbedPane not updating on UI

807580Aug 27 2010 — edited Aug 28 2010
Hi all, describing my problem is kind of long winded, so thanks for bearing with me.

I'm in the process of programming a blackjack-like card game. I'm attempting to implement a way the user's cards can be 'split' by using a JTabbedPane. I made a subclass of JTabbedPane (called JHSPanel) so I could keep track of each tab and its contents (stored as JSubPanels, described below)

I also created a subclass of JPanel (called JSubPanel) that, when constructed, stores 2 normal JPanels: one to hold the images of the cards (stored as JLabels) when the player receives them, and another to hold a series of buttons (the buttons control 'Hit', 'Stay', 'Split' functionality) that I want to enable and disable at will.

The idea is that when the player splits their cards, a JHSPanel (which is the subclass of JTabbedPane) would be created with 2 tabs. In each of those tabs, a JSubPanel (the subclass of JPanel) would house the area where the cards appear on the UI and also the buttons that the player can click to hit or stay... it would be the main content area for the tab. The extra subclass methods that I wrote would allow me to add different cards to different tabs and enable or disable different buttons on different tabs by keeping track of which JSubPanel goes with which tab, and then calling methods in the JSubPanel to change its state (and because the JSubPanel is the main content area of the tab, any changed state of the JSubPanel would be reflected in the tab, which the user could see).

For instance, if a player hits on the first of his 2 split cards, I would know he pressed the button on the first tab, so I call JHSPanel.addCard((index) 0, (card object) card). This method would then call the appropriate JSubPanel for the tab at that index, and tell it to add the image of the card to the JPanel housing all the card images. This change of state for the JSubPanel would be reflected for that entire tab (because the JSubPanel is the main content area for the tab), and on the user's screen the card image would show up.

The problem is that whenever I change state for the JSubPanel, the JHSPanel does absolutely nothing on-screen. It shows up on the screen when it's initialized, but after that it might as well be locked up. My program doesn't throw out any errors, the rest of the program works smoothly, and all the states are updating correctly (I know because I have tracers inserted to alert me of the change of states). I tried repainting and revalidating the tabbed panel, the main frame, the main content window, and everything else the tabbed panel is house in, but still the UI for the tabbed panel remains unchanged from it's original initialized state. The following is the source code of both JHSPanel and JSubPanel:
public class JHSPanel extends JTabbedPane{

	private static final long serialVersionUID = 1L;
	protected static int HIT_INDEX = 0;
	protected static int STAY_INDEX = 1;
	protected static int SPLIT_INDEX = 2;
	
	private ArrayList<JSubPanel> tabs;
	
	/**
	 * constructor for the JTabbedPane subclass
	 * @param fragSize	number of tabs to be created
	 */
	public JHSPanel(int fragSize){
		
		// a list of JSubPanels
		tabs = new ArrayList<JSubPanel>();
		
		// create fragSize number of tabs
		for(int i=0; i<fragSize; i++){
			
			// JPanel to hold the states created in JSubPanel. Note that
			// this should not be necessary since JSubPanel IS a JPanel and
			// a JSubPanel should be able to plug directly into a tab
			JPanel main = new JPanel(new GridLayout(2,1));
			
			// creation of a JSubPanel initializes 2 normal JPanels that are stored
			// as fields:
			// 1. a regular JPanel with a FlowLayout to hold JLabels (field name: 'felt')
			// 2. another JPanel with a FlowLayout to hold the Hit, Stay, and Split 
			//    buttons (field name: 'buttons')
			JSubPanel temp = new JSubPanel();
			temp.getFelt().setBackground(Color.green); // the UI reflects this code, unlike in addCard()
			main.add(temp.getFelt());
			main.add(temp.getButtons());
			
			tabs.add(temp);		// stores the new JSubPanel
			
			// this JTabbedPanel creates a tab within itself, holding the JPanel
			// (in a GridLayout) that holds 2 more JPanels (in a FlowLayout)
			addTab("Hand #"+(1+i), main);
		}
	}
	
	/**
	 * sends the Card object to the appropriate JSubPanel, distinguished by fragIndex. Any
	 * change to state works internally (verified by trace statements, not present), however
	 * the UI does not reflect any of these changes, as it should. It's as if I'm updating
	 * correctly and changing correctly an object OTHER than the one present in the UI 
	 * (which does not make sense because, for testing, I have only been using the index 0)
	 * @param c				Card to be added to felt
	 * @param fragIndex		Index of JSubPanel in list of all JSubPanels
	 */
	public void addCard(Card c, int fragIndex){
		
		// adds the card to the JSubPanel
		JSubPanel subPanel = tabs.get(fragIndex);
		subPanel.addCard(c);
		
		// Destroys the current tab and fabricates a new one, in the hopes that
		// the UI will update to reflect the change. This does not work
		this.remove(fragIndex);
		JPanel main = new JPanel(new GridLayout(2,1));
		subPanel.getFelt().setBackground(Color.black);	// UI does NOT reflect this change
		main.add(subPanel.getFelt());
		main.add(subPanel.getButtons());
		tabs.add(subPanel);
		this.insertTab("Hand #"+fragIndex, null, main, null, fragIndex);
	}
}
public class JSubPanel extends JPanel{

	private JPanel buttons;
	private JPanel felt;
	private JButton hit;
	private JButton stay;
	private JButton split;
	
	
	public JSubPanel(){
		buttons = initButtons();
		felt = initFelt();
	}
	
	private JPanel initButtons(){
		JPanel main = new JPanel(new FlowLayout());
		
		hit = new JButton("Hit");
			hit.addActionListener(new HitButtonListener());
			
		stay = new JButton("Stay");
			stay.addActionListener(new StayButtonListener());
			
		split = new JButton("Split");
			split.addActionListener(new SplitButtonListener());
			
		main.add(hit); main.add(stay); main.add(split);
		return main;
	}
	
	private JPanel initFelt(){
		return new JPanel(new FlowLayout());
	}
	
	public void enableButtons(boolean enabled, boolean splitEnabled){
		JButton[] bArray = {hit, stay, split};
		
		for(JButton b: bArray){
			b.setEnabled(enabled);
		}
		if(enabled){
			split.setEnabled(splitEnabled);
		}
	}
	
	public JPanel getButtons(){
		return buttons;
	}
	
	public JPanel getFelt(){
		return felt;
	}
	
	public void addCard(Card c){
		JLabel label = new JLabel(Blackjack.cardData.imageMap.get(c.hashCode));
		felt.setBackground(Color.green);
		felt.add(label);
	}
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Sep 25 2010
Added on Aug 27 2010
2 comments
287 views