Results 1 to 4 of 4
  1. #1
    LittleRave is offline Member
    Join Date
    Dec 2009
    Location
    germany
    Posts
    15
    Rep Power
    0

    Default problem: lightweight component still being painted after remove

    Hi!

    I'm pretty new to swing and started writing an applet few weeks ago, so far everything worked fine but now I've run into a problem I can't find a solution for, or even find out what causes this behavior.

    I've written a menu extending from JPanel with a BoxLayout that consists of a vertical strut if i want distance to the button above, a button and any number of boxes you want to add. When adding a Box to the menu I put another menu of the same class into it so I can add as many buttons I want and have the ability to give every menu item its own sub-menu, sub-sub-menu, sub-sub-sub-menu and so on. and everything with one single class :)

    So far the button extended from JComponent only consists of a text so it's nothing strange. Later I'll be adding more to it but first I have to get rid of my problem.

    I've added a MouseListener to the menu that activates or deactivates the sub-menus and later it'll change the appearance of the button.

    And here's the problem: When I click on a button, the sub-menus get activated and the buttons are shown, all the buttons below the one i clicked are pushed downwards below the sub-menu (as intended) but the text of this button below the one I clicked still appears on its initial position (like a background of the new sub-menu button), its not responding to the mouse so I guess its just because of Swing not clearing the content of already drawn lightweight components. I've tried to find a how to but didn't succeed in that. graphics.clearRect(...) is no solution because I want the button's background to be fully transparent and the clearRect function only overpaints the content with a rectangle in the background color, I tried removing the sub-menu boxes from the layout, same problem and I also tried setting the sub-menu boxes visibility to false but still, same problem. :( The repaint() function unfortunately does not clear the content of lightweight components (why? whyyyyyy? :mad:) and so I'm running out of ideas.

    Now here's the relevant code:
    The button class:
    Java Code:
    public class TButton extends JComponent {
    	private static final Color FONT_COLOR_INACTIVE = TApplet.BLACK;
    	private static final Color FONT_COLOR_HOVERED = TApplet.MAGENTA;
    	private static final Color FONT_COLOR_ACTIVE = Color.WHITE;
    	
    	private static final Dimension SIZE = new Dimension(TLayout.MENU_WIDTH, 20);
    	
    	private String menuItem;
    	private Font buttonFont = TApplet.BUTTON_FONT;
    	private int indent = 0;
    	
    	public boolean hovered = false;
    	public boolean active = false;
    	
    	private BoxLayout layout = new BoxLayout(this, BoxLayout.X_AXIS);
    
    	public TButton() {
    		this.menuItem = "";
    		setMaximumSize(new Dimension((int)SIZE.getWidth(), 0));
    		setMinimumSize(new Dimension((int)SIZE.getWidth(), 0));
    	}
    
    	public TButton(String menuItem) {
    		setLayout(this.layout);
    		
    		this.menuItem = menuItem;
    
    		setMaximumSize(SIZE);
    		setMinimumSize(SIZE);
    	}
    
    	@Override
    	public void paintComponent(Graphics graphics) {
    		if (this.active) {
    			graphics.setColor(FONT_COLOR_ACTIVE);
    			graphics.setFont(TApplet.BUTTON_FONT);
    		}
    		if (this.hovered) {
    			graphics.setColor(FONT_COLOR_HOVERED);
    			graphics.setFont(this.buttonFont);
    		} else {
    			graphics.setColor(FONT_COLOR_INACTIVE);
    			graphics.setFont(this.buttonFont);
    		}
    		
    		graphics.drawString(this.menuItem, this.indent, ((int)SIZE.getHeight() + (int)graphics.getFontMetrics().getLineMetrics(this.menuItem, graphics).getAscent() - (int)graphics.getFontMetrics().getLineMetrics(this.menuItem, graphics).getDescent()) / 2);
    	}
    	
    	public void deactivate() {
    		this.active = false;
    		
    		repaint();
    	}
    	
    	public void activate() {
    		this.active = true;
    
    		repaint();
    	}
    	
    	public boolean isActive() {
    		return this.active;
    	}
    	
    	public void setMenuItemName(String menuItem) {
    		this.menuItem = menuItem;
    		repaint();
    	}
    	
    	public String getMenuItemName() {
    		return this.menuItem;
    	}
    	
    	public void setFont(Font font) {
    		this.buttonFont = font;
    	}
    	
    	public void setIndent(int indent) {
    		this.indent = indent;
    	}
    }
    and the attributes and relevant functions of the menu class:
    Java Code:
    	public static final int TOP = 1;
    	public static final int BOTTOM = 2;
    	public static final int CENTER = 4;
    	
    	private BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS);
    	
    	private TButton button;
    	private boolean isActive = false;
    	
    	private int indent = 10;
    	
    	private boolean showDividingLine = true;
    	private int linePosition = TOP;
    	
    	public TMenu(String menuItemTitle, int headline) {
    		setLayout(this.layout);
    		this.button = new TButton(menuItemTitle);
    		
    		if (headline <= 0) {
    			this.linePosition = 0;
    		}
    		
    		add(Box.createVerticalStrut(headline));
    		add(this.button);
    		
    		this.button.addMouseListener(this);
    	}
    
    	public void addMenuItem(TMenu subMenu) {
    		subMenu.setIndent(subMenu.getIndent() + this.indent);
    		
    		Box containerItem = Box.createVerticalBox();
    		
    		containerItem.add(subMenu);
    		add(containerItem);
    		containerItem.setVisible(false);
    	}
    
    	public void activate() {
    		for (int iterator = 0; iterator < getComponentCount(); iterator++) {
    			if (getComponent(iterator) instanceof Box) {
    				getComponent(iterator).setVisible(true);
    			}
    		}
    		this.isActive = true;
    	}
    
    	public void deactivate() {
    		for (int iterator = 0; iterator < getComponentCount(); iterator++) {
    			if (getComponent(iterator) instanceof Box) {
    				((TMenu)((Box)getComponent(iterator)).getComponent(0)).deactivate();
    				getComponent(iterator).setVisible(false);
    			}
    		}
    		this.isActive = false;
    	}
    
    // this function only draws one or more grey lines between the menus
    	@Override
    	public void paintComponent(Graphics graphics) {
    		if (this.showDividingLine) {
    			graphics.setColor(TApplet.LIGHT_GREY);
    			for (int iterator = 0; iterator < getComponentCount(); iterator++) {
    				if (getComponent(iterator) instanceof Box.Filler) {
    					if ((this.linePosition & 1) != 0) {
    						graphics.drawLine(0, (int)getComponent(iterator).getLocation().getY(), (int)getComponent(iterator).getSize().getWidth(), (int)getComponent(iterator).getLocation().getY());
    					} if ((this.linePosition & 2) != 0) {
    						graphics.drawLine(0, (int)getComponent(iterator).getLocation().getY() + (int)getComponent(iterator).getSize().getHeight() - 1, (int)getComponent(iterator).getSize().getWidth(), (int)getComponent(iterator).getLocation().getY() + (int)getComponent(iterator).getSize().getHeight() - 1);
    					} if ((this.linePosition & 4) != 0) {
    						graphics.drawLine(0, (((int)getComponent(iterator).getLocation().getY() + (int)getComponent(iterator).getSize().getHeight()) / 2) - 1, (int)getComponent(iterator).getSize().getWidth(), (((int)getComponent(iterator).getLocation().getY() + (int)getComponent(iterator).getSize().getHeight()) / 2) - 1);
    					}
    				}
    			}
    		}
    	}
    
    	@Override
    	public void mouseClicked(MouseEvent e) {
    		if (this.isActive) {
    			deactivate();
    		} else {
    			activate();
    		}
    	}
    
    	@Override
    	public void mouseEntered(MouseEvent e) {
    		this.button.hovered = true;
    		setCursor(new Cursor(Cursor.HAND_CURSOR));
    		
    		this.button.repaint();
    	}
    
    	@Override
    	public void mouseExited(MouseEvent e) {
    		this.button.hovered = false;
    		setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    		
    		this.button.repaint();
    	}
    Any help or idea is very appreciated!!!

  2. #2
    zweibieren is offline Senior Member
    Join Date
    Aug 2009
    Location
    Pittsburgh, PA
    Posts
    284
    Rep Power
    5

    Default

    Sadly I cannot parse the description of the problem.
    It seems something is appearing when it should not.
    I do note that Tbutton.paintComponent() unconditionally paints menuItem.
    Perhaps the problem can be fixed by adding an 'if' before painting the menuItem.

  3. #3
    LittleRave is offline Member
    Join Date
    Dec 2009
    Location
    germany
    Posts
    15
    Rep Power
    0

    Default

    I found a solution but it's a pretty bad one, so I'm still up to hearing some ideas.

    I accidentally found out that the mispainted buttons disappear when I resize my applet so I took a look into what the resize function did. I first wanted to resize the applet with the size it already had so no size changes happen but then also no repainting happened so I thought to repaint the whole background and everything on it and so the buttons got overpainted. (stupid overpainting :mad:)

    I've added an observable to my menu and an observer to my applet, and when I click a button I send a message to the applet which then calls the whole content pane to repaint.
    I'm absolutely not satisfied with this solution and I can't imagine that this is the only way, but at least it is one.

  4. #4
    LittleRave is offline Member
    Join Date
    Dec 2009
    Location
    germany
    Posts
    15
    Rep Power
    0

    Default

    Sadly I cannot parse the description of the problem.
    It seems something is appearing when it should not.
    I do note that Tbutton.paintComponent() unconditionally paints menuItem.
    Perhaps the problem can be fixed by adding an 'if' before painting the menuItem.
    Well, yes. Let's keep it the simplest. I have a text, and when I click the text, I want it to move to another position. So I click on it and it does as intended but it additionally stays where it was before, so I have now two text parts. one at the desired position and one at the initial position, the moved one is still clickable but the other one is not (it's like a background image).

    Your suggestion does not work. I already had an image as background for the button, that was only drawn if the button was active. Once I activated the button it got drawn but when I deactivated the button it did not disappear either. I only removed everything up to the simplest for finding the cause of the problem before I posted in here.
    But thanks for the suggestion.
    Last edited by LittleRave; 12-10-2009 at 03:14 PM.

Similar Threads

  1. how to remove component from panel
    By itaipee in forum AWT / Swing
    Replies: 3
    Last Post: 04-28-2009, 12:50 PM
  2. JSF message component problem
    By Jothi in forum JavaServer Faces (JSF)
    Replies: 0
    Last Post: 06-04-2008, 02:39 PM
  3. how to remove all component in container(Jpanel)
    By SaYuNaRa in forum New To Java
    Replies: 3
    Last Post: 04-17-2008, 04:22 AM
  4. Replies: 0
    Last Post: 04-09-2008, 06:42 PM
  5. how to remove an old version of JDK
    By tommy in forum New To Java
    Replies: 2
    Last Post: 07-30-2007, 08:59 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •