3

JLayeredPane の 1 つのレイヤーにある JPanel に一連の JMenuItems があり、上位レイヤーの JPanel にエミュレートされたカーソルが描画されています。メニュー項目が再描画されると、エミュレートされたカーソルの上に描画されます (カーソル レイヤーの再描画はトリガーされません)。興味深いことに、メニュー項目を JButton または JLabels に置き換えると、メニュー項目が再描画されるたびにカーソルが正しく描画されます。

階層化されたペインで 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);
}
4

1 に答える 1

3

JComponent には、alwaysOnTop()コンポーネントの再描画が他のコンポーネントの再描画を必要とするかどうかを判断するために Swing 描画システムが使用する package-private メソッドがあります。デフォルトでは、このメソッドは を返しますが、メニュー項目が JInternalFrame に表示されない限り、falseJMenuItem はそれをオーバーライドして返すようにします。true結果として、JMenuItem の上に表示されるコンポーネントは、メニュー項目が再描画されても再描画されません(メニュー項目が内部フレームにある場合を除く)。

はパッケージ プライベートであるためalwaysOnTop()、カスタム コンポーネントでオーバーライドすることはできません。唯一の解決策は

  • 別のコンポーネントを使用する (例: JButton、JLabel)
  • メニューを内部フレームに配置する
  • コンポーネントを透明にする (つまりsetOpaque(false))

私は後者のソリューションを使用することになりました。実際には透明なメニュー項目が必要なかったので、不透明なプロパティを設定/クリアする呼び出しでペイント コードをラップしました。

@Override
protected void paintComponent(Graphics g)
{ 
   // paint the component as opaque
   setOpaque(true);
   super.paintComponent(g);
   setOpaque(false);
}
于 2011-04-14T21:44:59.763 に答える