JMenuItems在JLayeredPane中绘制更高的组件 [英] JMenuItems painting over higher components in JLayeredPane

查看:110
本文介绍了JMenuItems在JLayeredPane中绘制更高的组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a set of JMenuItems in a JPanel on one layer of a JLayeredPane, and an emulated cursor painted in a JPanel on a higher layer. When the menu items repaint, they paint over the emulated cursor (without triggering a repaint of the cursor layer). Interestingly, if I substitute JButtons or JLabels for the menu items, the cursor is correctly painted each time the menu items repaint.

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

How can I ensure that repainting the menu items will cause the affected regions of the higher layers to repaint as well, without directly calling repaint() on the layered pane? The situation I've described is somewhat simplified from reality: the menu items may be deeply nested in a child of the layered pane, and they should not know about the layered pane at all.

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

Here's a snippet of pseudo-code illustrating what I've 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);
}


推荐答案

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

JComponent has a package-private alwaysOnTop() method that the Swing painting system uses to determine whether repainting a component may necessitate repainting other components. By default this method returns false, but JMenuItem overrides it to return true unless the menu item appears in a JInternalFrame. As a consequence, components that appear above a JMenuItem will not be repainted when the menu item is repainted (except when the menu item is in an internal frame).

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

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


  • 使用不同的组件(例如JButton,JLabel)

  • 将菜单放在内部框架中

  • 使组件透明(即 setOpaque(false)

  • use a different component (e.g. JButton, JLabel)
  • place the menu in an internal frame
  • make the components transparent (i.e. setOpaque(false))

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

I ended up using the latter solution. Since I didn't actually want 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);
}

这篇关于JMenuItems在JLayeredPane中绘制更高的组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆