に埋め込んだ大きな「キャンバスのような」CAD コンポーネントにナビゲーション ウィンドウを提供するために、ここJScrollNavigator
で説明するコンポーネントを使用しています。JScrollPane
JScrollNavigator
ユーザーに追加のコンテキストを提供するために、キャンバスのサムネイル画像を描画するように を適応させようとしました。ただし、これを実行すると、アプリケーションのメイン フレームのレンダリングが破損します。具体的にはpaint(Graphics)
、ビューポート コンポーネント (つまり、私のメイン キャンバス)を呼び出し、Graphics
によって作成されたオブジェクトを渡すアクションがBufferedImage
、その後の表示の破損を引き起こします。この行をコメントアウトすると、すべて正常に動作します。
以下は、JScrollNavigator
オーバーライドされたpaintComponent
メソッドです。
@Override
protected void paintComponent(Graphics g) {
Component view = jScrollPane.getViewport().getView();
BufferedImage img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
// Paint JScrollPane view to off-screen image and then scale.
// It is this action that causes the display corruption!
view.paint(g2d);
g2d.drawImage(img, 0, 0, null);
Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);
super.paintComponent(g);
g.drawImage(scaled, 0, 0, null);
}
破損の原因について何か提案はありますか? オフスクリーン イメージへのペイントは、既存のペイント操作に影響を与えるべきではないと考えていたでしょう。
編集
追加の詳細を提供するには:JScrollNavigator
は、 の左側にサブパネルを形成しJSplitPane
ます。ナビゲーターにJScrollPane
関連付けられている は右側にあります。「破損」により、スプリッターがレンダリングされなくなり、スクロールバーが表示されなくなります (白く表示されます)。のサイズを変更するJFrame
と、JMenu
セクションも白くなります。ナビゲーターを使用したり、スクロールバーを操作しようとすると、それらは表示されますが、スプリッターは白のままです。さまざまなコンポーネントの不透明な設定が、ビューポート ビューをオフスクリーン イメージにレンダリングすることによって影響を受けているかのようです。
また、 をJScrollNavigator
完全に別の に表示させるとJDialog
、すべてが正しく機能します。
編集2
以下を実行することで、一貫して問題を再現できます。
JMenuBar
に aを追加mFrame
:
JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);
置換のmain()
方法では:JScrollNavigator
jsp.setViewportView(textArea);
... と:
jsp.setViewportView(new JPanel() {
{
setBackground(Color.GREEN);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
}
});
が別個の として表示されるのではなく、JScrollNavigator
内にパネルとして埋め込まれていることを確認します。mFrame
JDialog
mFrame.add(jsp, BorderLayout.CENTER);
mFrame.add(nav, BorderLayout.NORTH);
アプリケーションを実行すると、JMenuBar
は表示されなくなります。によって返されるにビュー (つまり、JPanel
太い黒の境界線を持つ緑) をペイントする行為は、実際には、おそらく JFrame の左上隅から、画面上にレンダリングしているように見えます。そのため、他のコンポーネントが見えなくなります。これは、 がビューポート ビューとして使用され、、 などの別のコンポーネントが使用されていない場合にのみ発生するようです。Graphics2D
BufferedImage.createGraphics()
JPanel
JTextArea
JTable
編集3
この人が同じ問題を抱えていたようです (解決策は投稿されていません): http://www.javaworld.com/community/node/2894/
編集4
編集 2 で説明されている再現可能なエラーが発生するメソッドmain
とメソッドは次のとおりです。paintComponent
public static void main(String[] args) {
JScrollPane jsp = new JScrollPane();
jsp.setViewportView(new JPanel() {
{
setBackground(Color.GREEN);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
}
});
JScrollNavigator nav = new JScrollNavigator();
nav.setJScrollPane(jsp);
JFrame mFrame = new JFrame();
JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);
mFrame.setTitle("JScrollNavigator Test");
mFrame.setSize(800, 600);
mFrame.setLayout(new GridLayout(1, 2));
mFrame.add(jsp);
mFrame.add(nav);
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
mFrame.setLocation((screenDim.width - mFrame.getSize().width) / 2, (screenDim.height - mFrame.getSize().height) / 2);
mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mFrame.setVisible(true);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Component view = jScrollPane.getViewport().getView();
if (img == null) {
GraphicsConfiguration gfConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2d = img.createGraphics();
view.paint(g2d);
Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);
g.drawImage(scaled, 0, 0, null);
}
編集5
他の人が正確な問題を再現するのに苦労しているようです。ここに貼り付けたコードを実行してもらいたいと思います。この例を最初に実行すると、次のように表示されます。
JScrollNavigator も JMenuBar も描画されていません。これらのフレーム領域は透明です。
サイズ変更後、次のように表示されます。
はJMenuBar
まだペイントされておらずJPanel
、ある時点で (0,0) (あるJMenuBar
べき場所) でレンダリングされたようです。内部のview.paint
呼び出しpaintComponent
は、これの直接の原因です。