首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止JInternalFrame重新绘制重叠的JInternalFrame

如何防止JInternalFrame重新绘制重叠的JInternalFrame
EN

Stack Overflow用户
提问于 2017-10-19 18:08:17
回答 1查看 279关注 0票数 1

我有两个JInternalFrames,每个都包含一个JPanel。一个JPanel (源)更新它的图形用户界面和响应鼠标事件的一些数据。另一个JPanel (目标)接收指示数据已更改的事件并相应地更新其外观。

如果源面板与目标面板重叠,则目标面板中的重绘将触发源面板中的重绘。而且,即使对目标面板所需的更改被源面板遮住了,目标面板仍然重新绘制,并且仍然在源面板中触发重绘。

在我的实际应用程序中,这会造成性能问题,因为多个面板正在鼠标拖动上触发重新绘制,源面板有一个复杂的图像要显示。

如何防止目标面板更新触发源面板中的重新绘制?

我尝试过的事情:

  • 给出参数来重新绘制,这意味着只有目标面板的一个不重叠的位被重新绘制,停止了问题,但在我的例子中,我不知道目标面板的哪个部分是可见的(我尝试了getVisibleRect和getClipBounds,但它们只是返回整个面板大小)。在我的实际应用程序中,整个目标面板是更新的,而不仅仅是它的一部分,所以我也不能以这种方式限制重绘。
  • 基于现有的InternalFrameDemo创建了一个最小的示例:相同的问题,参见下面的代码。该示例有两个面板,如我所描述的,单击源面板(标记为Document 1)在该位置绘制一个红色框,并更新DataModel对象,该对象将触发目标面板(标记为Document2)接收的事件,该事件本身在同一位置绘制一个红色框。在源paintComponent方法中设置一个断点,您可以看到有两个更新,一个来自SourcePanel重绘,一个来自TargetPanel重绘。 公共类InternalFrameDemo扩展JFrame实现ActionListener { JDesktopPane桌面;DataModel model =新DataModel();public InternalFrameDemo() { super("InternalFrameDemo");//使大窗口从屏幕的每边//缩进50个像素。int inset = 50;维度screenSize = Toolkit.getDefaultToolkit().getScreenSize();setBounds(inset,inset,screenSize.width - inset*2,screenSize.height - inset*2);//设置GUI。桌面=新的JDesktopPane();//一个专门的分层窗格MyInternalFrame frame1 = createFrame();//创建第一个“窗口”MyInternalFrame frame2 = createFrame();setContentPane(桌面);SourcePanel sp =新SourcePanel(模型);Fra1.add(Sp);TargetPanel tp =新TargetPanel(模型);Fra2.add(Tp);//使拖动速度更快,但可能更丑。desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);} actionPerformed(ActionEvent e) {}//创建一个新的内部框架。受保护的MyInternalFrame createFrame() { MyInternalFrame frame =新的MyInternalFrame();frame.setVisible(真);//必要的自1.3 frame.setOpaque(真);desktop.add(frame);尝试{frame.setSelected(真);}MyInternalFrame (java.beans.PropertyVetoException e) {}返回帧;}//退出应用程序。受保护的void (){ System.exit(0);} /** *创建并显示该GUI。为了线程安全,*应该从*事件分派线程调用此方法。*/私有静态空createAndShowGUI() {//创建并设置窗口。frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//显示窗口。frame.setVisible(true);}公共静态void (String[] args) {//调度一个作业,用于事件分派线程://创建和显示该应用程序的GUI。javax.swing.SwingUtilities.invokeLater(new (){ public void (){ createAndShowGUI();});}
代码语言:javascript
复制
    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);
    }
}
代码语言:javascript
复制
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);
    }
}
代码语言:javascript
复制
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);
    }
}
代码语言:javascript
复制
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示例代码的版权通知:)

代码语言:javascript
复制
/*
 * 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.
 */ 
EN

回答 1

Stack Overflow用户

发布于 2017-10-19 20:51:14

您可以缓存鼠标更改,并按间隔执行,或在鼠标跟踪结束时执行。

最简单的办法可能是尝试一次延期的重新油漆。

代码语言:javascript
复制
@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秒的高价值。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46836269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档