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:
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:
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!!!