JMenuItems Color Higher Components in JLayeredPane

I have a set of JMenuItems in JPanel at the same level as JLayeredPane and an emulated cursor written in JPanel at a higher level. When menu items are redrawn, they draw over the emulated cursor (without causing the cursor layer to redraw). Interestingly, if I replaced JButtons or JLabels for menu items, the cursor will be correctly colored every time the menu items are redrawn.

How can I guarantee that redrawing menu items will redraw the affected areas of higher layers without directly calling repaint () on the layered panel? The described situation is somewhat simplified from reality: menu items can be deeply embedded in the child layer of the layered panel, and they should not know about the multilevel panel at all.

Here is a snippet of pseudo code illustrating what I described:

public void initGui(Dimension size) { JLayeredPane layeredPane = new JLayeredPane(); layeredPane.setSize(size); menuPanel = new JPanel(); menuPanel.setSize(size); layeredPane.add(menuPanel, BOTTOM_LAYER); JPanel cursorPanel = new CursorPanel(); cursorPanel.setSize(size); layeredPane.add(cursorPanel, TOP_LAYER); } public void showMenu(Component[] menuItems) { JPanel menu = new JPanel(); for (Component c: menuItems) menu.add(c); menuPanel.add(menu); } 
+3
source share
1 answer

JComponent has a private-private alwaysOnTop() method, which is used by the Swing paint system to determine if a component can repaint another component. By default, this method returns false , but JMenuItem overrides it to return true if the menu item does not appear in the JInternalFrame. As a result, the components that appear above the JMenuItem will not be redrawn when the menu item is repainted (except when the menu item is in the internal frame).

Since alwaysOnTop() is a private package, it cannot be overridden in the user component. It seems that the only solutions are

  • use another component (e.g. JButton, JLabel)
  • put the menu in the inner frame
  • make components transparent (i.e. setOpaque(false) )

In the end, I used the last solution. Since I really did not need transparent menu items, I wrapped the paint code with calls to set / clear the opaque property:

 @Override protected void paintComponent(Graphics g) { // paint the component as opaque setOpaque(true); super.paintComponent(g); setOpaque(false); } 
+3
source

All Articles