2017-10-19 4 views
0

을 다시 그리기에서 JInternalFrame를 방지합니다. 하나의 JPanel (소스)은 마우스 이벤트에 대한 응답으로 GUI와 일부 데이터를 업데이트합니다. 다른 JPanel (대상)은 데이터가 변경되었음을 나타내는 이벤트를 수신하고 그에 따라 모양을 업데이트합니다. 소스 패널이 대상 패널을 겹치는 경우는 어떻게이 한 JInternalFrame JPanel과를 포함하는 각이 중복 JInternalFrame를

은 대상 패널에서 다시 그리기는 소스 패널에서 다시 그리기를 트리거합니다. 타겟 패널에 요구되는 변화는 소스 패널 가려 또한하더라도 타겟 패널은 여전히 ​​다시 표시 여전히 소스 패널에 재 렌더링을 트리거한다. 여러 패널은 마우스 드래그에 다시 그리기를 트리거하고, 소스 패널을 표시하는 복잡한 이미지가 나의 실생활의 응용 프로그램에서

,이, 성능 문제를 만듭니다.

나는 소스 패널에서 다시 그리기를 트리거에서 대상 패널 업데이트를 방지 할 수있는 방법 ? 내가 해봤

것들 :

  • 하는 대상 패널의 비 중복 비트가 다시 그려 의미 칠 매개 변수를 제공하여 문제를 중지하지만 내 경우에는 내가 모르는 어떤 비트 (getVisibleRect 및 getClipBounds 시도했지만 전체 패널 크기를 반환합니다). 내 실제 응용 프로그램에서는 전체 대상 패널이 업데이트되고 일부만 업데이트되지 않으므로 다시 그리기를 제한 할 수 없습니다.
  • 기존 InternalFrameDemo에 기초하여 최소한의 생성 예 : 동일한 문제 아래 코드를 참조. 이 예제에는 필자가 설명한대로 두 개의 패널이 있는데, 소스 패널 (문서 1이라는 레이블이 붙어 있음)을 클릭하면 해당 위치에 빨간색 상자가 그려지고 대상 패널에서 가져온 이벤트 (Document 2라고 함)가 발생하는 DataModel 객체가 업데이트됩니다. 이것은 같은 위치에 빨간색 상자를 그립니다. 원본 paintComponent 메서드에 중단 점을 설정하면 SourcePanel 다시 그리기와 TargetPanel 다시 그리기의 두 가지 업데이트가 있음을 알 수 있습니다.

    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); 
    } 
} 

원래 JInternalFrame의 예제 코드에 대한 17,451,515,

(저작권 :

/* 
* 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 좋아, 그게 추가되었습니다 -하지만 내 문제에 아무런 영향을주지 않습니다. – smiley

답변

1

마우스의 변화를 캐시와 간격을 수행하거나 마우스 추적 끝에 수 있습니다.

아마도 가장 쉬운 방법은 연기 된 다시 칠을 시도하는 것입니다.

실제로 여러 번 호출 한 후 실제로 다시 칠하는 경우는 repaint(200L);입니다. (제 느낌으로는 5 초의 높은 값을 선택했습니다.)

+0

재미있는 제안 주셔서 감사합니다,이 repaint 함께 옵션을 몰랐어요. 나는 실제 코드에서 다양한 값으로 시도했지만 실제로 성능에 도움이되지는 않습니다. – smiley

+0

@smiley 나는 그것을 두려워했다. 그 밖의 모든 것은 일합니다. 나는 변화 이벤트에서 사이클을 점검하기를 바란다 (실제로 확신한다) : 타겟 패널의 마우스 리스너. 타겟 패널의 반복적 인 변경을 목표로하는 몇 가지 변경을 일으키는 변경. 복잡한 페인트 코드. –