クライアント領域と、常にクライアント領域の上に表示されるツール パレットの 2 つの JFrame で構成される基本的な UI を持つ Java アプリケーションがあります。これを実現するために、ツール パレットは alwaysOnTop(true) に設定されます。これは、Windows 専用のものを除いて、すべての場合で非常にうまく機能します。モーダル JDialog がポップされると、クライアント領域および/またはパレット (両方ともブロックされている) により、パレットがクライアント領域の後ろに落ちます。モーダル ダイアログを閉じると、パレットが再び表示されますが、「常に最上位」は失われています。クライアント領域をクリックすると、パレットが見えなくなります。
以下は、最小限の単一ソース ファイルのデモです。
// FloatingPaletteExample.java
// 4/11/2012 sorghumking
//
// Demo of a Windows-only issue that has me puzzled: When a modal dialog is
// opened, and user clicks in blocked JFrames (sequence depends on ownership of
// modal dialog: follow the instructions in modal dialog to see the problem
// behavior), the floating tool palette loses its "always on top-ness".
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class FloatingPaletteExample {
public static void main( String [] args ) {
final JFrame clientAreaJFrame = new JFrame( "client JFrame" );
clientAreaJFrame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent windowevent ) {
clientAreaJFrame.dispose();
System.exit( 0 );
}
});
clientAreaJFrame.setSize( 800, 600 );
clientAreaJFrame.setVisible( true );
final JFrame floatingToolFrame = new JFrame("tool JFrame");
final JCheckBox ownerCheckbox = new JCheckBox("Owned by tool frame (otherwise, null owner)");
JButton popModalButton = new JButton("Open Modal Dialog");
popModalButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame owner = ownerCheckbox.isSelected() ? floatingToolFrame : null;
JDialog modalDialog = new JDialog(owner, "Modal Dialog", true);
final String labelText = ownerCheckbox.isSelected() ? "Click anywhere in the client JFrame." :
"Click the tool JFrame, then anywhere in the client JFrame";
modalDialog.add(new JLabel(labelText));
modalDialog.pack();
modalDialog.setLocation(100, 100);
modalDialog.setVisible(true);
}
});
floatingToolFrame.add(popModalButton, BorderLayout.NORTH);
floatingToolFrame.add(ownerCheckbox, BorderLayout.SOUTH);
floatingToolFrame.pack();
floatingToolFrame.setLocationRelativeTo(clientAreaJFrame);
floatingToolFrame.setAlwaysOnTop(true);
floatingToolFrame.setVisible(true);
}
}
ドキュメントによると、 「アプリケーションがフローティング パレットまたはツールバーとして使用されるウィンドウを AWT に識別するための標準メカニズム」ですが、動作は同じままです。
回避策を見つけました: モーダル ダイアログをポップする前に floatingToolFrame.setAlwaysOnTop(false) を呼び出し、閉じた後に floatingToolFrame.setAlwaysOnTop(true) を呼び出します。ただし、モーダル ダイアログが開かれるたびにこのラッピングを要求するのはばかげているようです。はい、JDialog をサブクラス化し、そのサブクラスからすべてのダイアログを派生させて、舞台裏でこれを行うことができますが、なぜこれが必要なのですか?
回避策なしでこれを解決する方法についてのアイデアはありますか? 常に最上位のパレットを作成する私のアプローチは完全に見当違いですか? (もう 1 つ注意: これは、ここで説明されている問題とは逆のようです: Java 6、JFrame が alwaysontop にスタックする)。
どんな考えでも大歓迎です!