【问题标题】:JMenuItems painting over higher components in JLayeredPaneJMenuItems 在 JLayeredPane 中的更高组件上绘制
【发布时间】:2011-08-05 20:08:05
【问题描述】:

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

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

这是一个伪代码的 sn-p,说明了我所描述的内容:

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

【问题讨论】:

  • 好的,但请说明问题是什么。 :) 加上代码将有助于了解您的意思。

标签: java swing jlayeredpane jmenuitem


【解决方案1】:

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

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

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

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

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

【讨论】:

  • +1 很高兴您与我们分享了您的问题的解决方案。这是我会采用的解决方案。
猜你喜欢
  • 2011-10-12
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
相关资源
最近更新 更多