JMenuItems在JLayeredPane中绘制更高的组件

我在JLayeredPane的一层上的JPanel中有一组JMenuItems,在更高层上的JPanel中绘制了一个模拟的游标。 当菜单项重新绘制时,它们会在模拟光标上绘制(不会触发光标图层的重绘)。 有趣的是,如果我用JButtons或JLabel代替菜单项,每次重新绘制菜单项时都会正确绘制光标。

如何确保重新绘制菜单项会导致较高层的受影响区域重新绘制,而不直接在分层窗格上调用repaint()? 我所描述的情况与现实有些简化:菜单项可能深深地嵌套在分层窗格的子项中,并且它们根本不应该知道分层窗格。

这是一段伪代码,说明了我所描述的内容:

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); } 

JComponent有一个包私有的alwaysOnTop()方法,Swing alwaysOnTop()系统使用该方法来确定重新绘制组件是否需要重新绘制其他组件。 默认情况下,此方法返回false ,但JMenuItem会覆盖它以返回true除非菜单项出现在JInternalFrame中。 因此,重新绘制菜单项时, 不会重新绘制出现在JMenuItem上方的组件(除非菜单项位于内部框架中)。

由于alwaysOnTop()是包私有的,因此无法在自定义组件中覆盖它。 似乎唯一的解决方案是

  • 使用不同的组件(例如JButton,JLabel)
  • 将菜单放在内部框架中
  • 使组件透明(即setOpaque(false)

我最终使用后一种解决方案。 由于我实际上并不想要透明的菜单项,因此我使用调用来设置/清除opaque属性来包装paint代码:

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