Java 如何防止JInternalFrame重新绘制重叠的JInternalFrame
我有两个JinternalFrame,每个包含一个JPanel。一个JPanel(源代码)更新其GUI和一些数据以响应鼠标事件。另一个JPanel(目标)接收到一个事件,指示数据已更改,并相应地更新其外观 如果源面板与目标面板重叠,则目标面板中的重新绘制将触发源面板中的重新绘制。此外,即使源面板掩盖了对目标面板所需的更改,目标面板仍会重新绘制,并仍会在源面板中触发重新绘制 在我的实际应用程序中,这会产生性能问题,因为多个面板在鼠标拖动时会触发重绘,并且源面板有一个复杂的图像要显示 如何防止目标面板更新触发源面板中的重新绘制? 我尝试过的事情:Java 如何防止JInternalFrame重新绘制重叠的JInternalFrame,java,repaint,jinternalframe,Java,Repaint,Jinternalframe,我有两个JinternalFrame,每个包含一个JPanel。一个JPanel(源代码)更新其GUI和一些数据以响应鼠标事件。另一个JPanel(目标)接收到一个事件,指示数据已更改,并相应地更新其外观 如果源面板与目标面板重叠,则目标面板中的重新绘制将触发源面板中的重新绘制。此外,即使源面板掩盖了对目标面板所需的更改,目标面板仍会重新绘制,并仍会在源面板中触发重新绘制 在我的实际应用程序中,这会产生性能问题,因为多个面板在鼠标拖动时会触发重绘,并且源面板有一个复杂的图像要显示 如何防止目标面
- 为重绘指定参数(这意味着只重绘目标面板的非重叠部分)可以解决问题,但在我的例子中,我不知道目标面板的哪一部分是可见的(我尝试了getVisibleRect和getClipBounds,但它们只返回整个面板的大小)。在我的实际应用程序中,整个目标面板都会更新,而不仅仅是其中的一部分,因此我也不能以这种方式限制重新绘制
- 基于现有InternalFrameDemo创建了一个最小的示例:相同的问题,请参见下面的代码。如我所述,该示例有两个面板,单击源面板(带标签的文档1)在该位置绘制一个红色框,并更新DataModel对象,该对象触发目标面板(带标签的文档2)拾取的事件,目标面板本身在同一位置绘制一个红色框。在source 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(); } }); } }
(原始JInternalFrame示例代码的版权声明:)
您可以缓存鼠标更改并每隔一段时间或在鼠标跟踪结束时执行这些更改 最简单的可能是尝试推迟重新喷漆
@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)后实际重新喷漆代码>。(出于我的感觉,我选择了第五秒的高值。)每个paintComponent
方法必须调用super.paintComponent(g)代码>在执行任何其他操作之前。请看。@VGR好的,已经添加了它-但是这对我的问题没有任何影响。谢谢你有趣的建议,我不知道这是一个重新绘制的选项。我用不同的值在我的实际代码中试用了它,但它并没有真正提高性能。@smiley我很害怕。其他一切都是工作。我希望(事实上我确信)您检查了更改事件中的周期:目标面板上的鼠标侦听器,一个更改导致多个更改,所有这些更改都是针对目标面板上的重复更改或其他任何更改。复杂的油漆代码。
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);
}
}
/*
* 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.
*/
@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);
}