2017-10-19 7 views
0

それぞれJPanelを含む2つのJInternalFrameがあります。 1つのJPanel(ソース)は、マウスイベントに応答してGUIと一部のデータを更新します。もう一方のJPanel(ターゲット)は、データが変更されたことを示すイベントを受け取り、それに応じて外観を更新します。JInternalFrameがオーバーラップしているJInternalFrameを再描画しないようにする方法

ソースパネルがターゲットパネルと重なっている場合は、ターゲットパネルの再描画によってソースパネルに再描画がトリガーされます。ターゲットパネルに必要な変更がソースパネルによって隠されている場合でも、ターゲットパネルはまだ再ペイントされ、ソースパネルではまだ再描画がトリガーされます。

私の実際のアプリケーションでは、複数のパネルがマウスのドラッグ時に再描画を開始し、ソースパネルに表示する複雑なイメージがあるため、パフォーマンスの問題が発生します。

ターゲットパネルの更新がソースパネルで再描画を引き起こさないようにするにはどうすればよいですか?私が試した

もの:

  • たが、対象パネルの唯一の非オーバーラップビットが再描画される意味再描画するためのパラメータを与えることは、問題を停止しますが、私の場合、私にはわからないどのビット(私はgetVisibleRectとgetClipBoundsを試みましたが、パネル全体のサイズを返します)。実際のアプリケーションでは、ターゲットパネル全体が更新されているだけでなく、そのように再ペイントを制限することもできません。
  • は、既存のInternalFrameDemoに基づいて最小限の例を作成しました。同じ問題です。下記のコードを参照してください。この例では、説明したように2つのパネルがあり、ソースパネル(ドキュメント1と表示されている)をクリックすると、その場所に赤色のボックスが描画され、ターゲットパネル(イベント2)これは、同じ場所に赤いボックスを描画します。ソースpaintComponentメソッドにブレークポイントを設定すると、SourcePanel再描画とTargetPanel再描画の2つの更新があることがわかります。

    public class InternalFrameDemo extends JFrame 
             implements ActionListener { 
    JDesktopPane desktop; 
    DataModel model = new DataModel(); 
    
    public InternalFrameDemo() { 
    super("InternalFrameDemo"); 
    
    //Make the big window be indented 50 pixels from each edge 
    //of the screen. 
    int inset = 50; 
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
    setBounds(inset, inset, 
          screenSize.width - inset*2, 
          screenSize.height - inset*2); 
    
    //Set up the GUI. 
    desktop = new JDesktopPane(); //a specialized layered pane 
    MyInternalFrame frame1 = createFrame(); //create first "window" 
    MyInternalFrame frame2 = createFrame(); 
    setContentPane(desktop); 
    
    SourcePanel sp = new SourcePanel(model); 
    frame1.add(sp); 
    TargetPanel tp = new TargetPanel(model); 
    frame2.add(tp); 
    
    //Make dragging a little faster but perhaps uglier. 
    desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); 
    } 
    
    public void actionPerformed(ActionEvent e) { 
    } 
    
    //Create a new internal frame. 
    protected MyInternalFrame createFrame() { 
        MyInternalFrame frame = new MyInternalFrame(); 
        frame.setVisible(true); //necessary as of 1.3 
        frame.setOpaque(true); 
    
    
    desktop.add(frame); 
        try { 
         frame.setSelected(true); 
        } catch (java.beans.PropertyVetoException e) {} 
        return frame; 
    } 
    
    //Quit the application. 
    protected void quit() { 
        System.exit(0); 
    } 
    
    /** 
    * Create the GUI and show it. For thread safety, 
    * this method should be invoked from the 
    * event-dispatching thread. 
    */ 
    private static void createAndShowGUI() { 
        //Create and set up the window. 
        InternalFrameDemo frame = new InternalFrameDemo(); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    
        //Display the window. 
        frame.setVisible(true); 
    } 
    
    public static void main(String[] args) { 
        //Schedule a job for the event-dispatching thread: 
        //creating and showing this application's GUI. 
        javax.swing.SwingUtilities.invokeLater(new Runnable() { 
         public void run() { 
          createAndShowGUI(); 
         } 
        }); 
    } 
    } 
    

package components; 

    import javax.swing.JInternalFrame; 

    /* Used by InternalFrameDemo.java. */ 
    public class MyInternalFrame extends JInternalFrame { 
    static int openFrameCount = 0; 
    static final int xOffset = 30, yOffset = 30; 

    public MyInternalFrame() { 
     super("Document #" + (++openFrameCount), 
       true, //resizable 
       true, //closable 
       true, //maximizable 
       true);//iconifiable 

     setSize(300,300); 
     setLocation(xOffset*openFrameCount, yOffset*openFrameCount); 
    } 
} 

package components; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 

import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class SourcePanel extends JPanel { 

    int boxX, boxY; 
    int boxWidth = 10; 
    int boxHeight = 10; 

    public SourcePanel(DataModel data) { 

     addMouseListener(new MouseAdapter() 
     { 
      @Override 
      public void mousePressed(MouseEvent evt) 
      { 
      if (!SwingUtilities.isRightMouseButton(evt)) 
      { 
       boxX = evt.getX(); 
       boxY = evt.getY(); 
       data.update(boxX,boxY); 
       repaint(); 
      } 
      } 
     }); 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     g.setColor(Color.RED); 
     int x = Math.min(boxX, this.getWidth()-boxWidth); 
     int y = Math.min(boxY, this.getHeight()-boxHeight); 
     g.drawRect(x, y, boxWidth, boxHeight); 
     g.drawRect(x + 1, y + 1, boxWidth - 2, boxHeight - 2); 
    } 
} 

package components; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.JPanel; 

public class TargetPanel extends JPanel implements PropertyChangeListener { 

    int boxX, boxY; 
    int boxWidth = 10; 
    int boxHeight = 10; 

    public TargetPanel(DataModel data) { 
     data.addPropertyChangeListener(this); 
    } 

    @Override 
    public void propertyChange(PropertyChangeEvent evt) 
    { 
     //draw something in response to the data change 
     boxX = ((int[])evt.getNewValue())[0]; 
     boxY = ((int[])evt.getNewValue())[1]; 
     repaint(); 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     g.setColor(Color.BLUE); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     g.setColor(Color.RED); 
     int x = Math.min(boxX, this.getWidth()-boxWidth); 
     int y = Math.min(boxY, this.getHeight()-boxHeight); 
     g.fillRect(x, y, boxWidth, boxHeight); 
    } 
} 

package components; 

import java.beans.PropertyChangeListener; 
import java.beans.PropertyChangeSupport; 

public class DataModel { 

    int datax = 10; 
    int datay = 10; 

    public DataModel() 
    { 
    } 

    public void update(int x, int y) 
    { 
     int[] olddata = new int[]{datax,datay}; 
     datax = x; 
     datay = y; 
     int[] newdata = new int[]{datax,datay}; 
     changeSupport.firePropertyChange("DataChange", olddata, newdata); 
    } 

    protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
       this); 

    public void addPropertyChangeListener(PropertyChangeListener listener) 
    { 
     changeSupport.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener) 
    { 
     changeSupport.removePropertyChangeListener(listener); 
    } 

} 

(元のJInternalFrameのサンプルコードのための著作権:)

/* 
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions 
* are met: 
* 
* - Redistributions of source code must retain the above copyright 
*  notice, this list of conditions and the following disclaimer. 
* 
* - Redistributions in binary form must reproduce the above copyright 
*  notice, this list of conditions and the following disclaimer in the 
*  documentation and/or other materials provided with the distribution. 
* 
* - Neither the name of Oracle or the names of its 
*  contributors may be used to endorse or promote products derived 
*  from this software without specific prior written permission. 
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
*/ 
+1

それぞれの 'paintComponent'メソッドは、何かをする前に' super.paintComponent(g); 'を呼び出さなければなりません。 https://docs.oracle.com/javase/tutorial/uiswing/painting/を参照してください。 – VGR

+0

@VGR ok、それを追加しました - しかし、私の問題には何の違いもありません。 – smiley

答えて

1

あなたは、マウスの変更をキャッシュし、間隔で、またはマウスの追跡最後にそれらを行うことができます。

最も簡単なのは、延期された再描画を試すことです。

@Override 
public void propertyChange(PropertyChangeEvent evt) 
{ 
    //draw something in response to the data change 
    boxX = ((int[])evt.getNewValue())[0]; 
    boxY = ((int[])evt.getNewValue())[1]; 
    repaint(200L); 
} 

実際にいくつかの呼び出しがrepaint(200L);にコールされた後に再ペイントします。 (私の気持ちでは、5秒という高い値を選んでいます)

+0

興味深い提案をありがとう、私はこれが再描画のオプションであることを知らなかった。実際のコードでさまざまな値で試してみましたが、パフォーマンスにはあまり役立ちません。 – smiley

+0

@smiley私はそれを恐れていました。他のすべては仕事です。ターゲットパネル上のマウスリスナー、ターゲットパネル上の反復的な変更を対象とするいくつかの変更を引き起こす1つの変更など、変更イベントのサイクルをチェックすることを希望します(実際には確信しています)。複雑なペイントコード。 –

関連する問題