gpt4 book ai didi

java - 在玻璃板上喷漆,无需重新喷漆其他部件

转载 作者:太空宇宙 更新时间:2023-11-04 06:36:34 24 4
gpt4 key购买 nike

假设我有一个名为 contentJPanel,其 paintComponent(g) 已被覆盖。该面板通常绘制速度非常快,但有时(澄清:用户生成的图形对象可以有数千个点,这会减慢渲染速度。它需要这样,这不是我的问题的一部分)由于其中发生的所有图形内容,可能需要整整一秒钟才能重新绘制。

我想在鼠标位置附近绘制一个点,但我希望它能够快速更新,而不必在每次移动鼠标时重新绘制内容

我试图做的是将它画在玻璃板上,如下所示:

class LabelGlassPane extends JComponent {
public LabelGlassPane(JApplet frame) {
this.frame = frame;
}
public JApplet frame;
public void paintComponent(Graphics g) {
if(ell != null){
g2.setColor(Vars.overDot);
g2.fill(ell); //this is an ellipse field that was created in the mouesmoved() listener
}
}
}

我的问题是,即使我现在仅在移动鼠标时更新此玻璃 Pane ,但当我对其调用 repaint() 时,它会重新绘制小程序中的所有其他组件。

如何在不绘制下面的组件的情况下在该玻璃板上绘制(或使用其他绘制方式)?

谢谢。

编辑:这是一个简单的例子。当鼠标移动时,jp 不应该更新,但它确实更新了。

public class Glasspanetest extends JApplet implements Runnable{

public void init() {
setLayout(new BorderLayout());
GraphicsPanel jp = new GraphicsPanel();
add(jp, BorderLayout.CENTER);
glass = new LabelGlassPane(this);
this.setGlassPane(glass);
glass.setVisible(true);
}


class GraphicsPanel extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(50, 50, 50, 50);
System.err.println("Painting bottom panel");
}
}

public LabelGlassPane glass = null;
public Ellipse2D.Double ell = null;

class LabelGlassPane extends JComponent {
public LabelGlassPane(JApplet frame) {
this.frame = frame;
this.addMouseMotionListener(new MoveInfoListener());
}
public JApplet frame;
public void paintComponent(Graphics g) {
//g.setColor(Color.red);
//Container root = frame.getRootPane();
// g.setColor(new Color(255,100,100,100));
// g.fillRect(100, 100, 500, 500);
if(ell != null){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.black);
g2.fill(ell);
System.out.println("Painted glass pane");
}

//rPaint(root,g);
}
}

public class MoveInfoListener implements MouseMotionListener{
public void mouseMoved(MouseEvent e) {
ell = new Ellipse2D.Double(e.getX()-3, e.getY()-3, 6, 6);
glass.repaint();
}

public void mouseDragged(MouseEvent arg0) {}
}

public void run() {}

}

最佳答案

问题是 Swing 无法知道它应该只重绘 LabelGlassPane 的一小部分,并且可能重绘 GraphicsPanel 的一小部分或不重绘。

这是因为您在组件中执行自定义绘制,并且虽然您只绘制面板的一小部分区域,但您也可以很好地绘制整个面板。

现在,至于为什么每次重新绘制 LabelGlassPane 时,GraphicsPanel 都会重新绘制,这是因为 LabelGlassPane 不是不透明的,这意味着,为了正确显示未绘制的区域,它需要绘制玻璃板“下方”的所有内容。

这两个方面的结合迫使 Swing 在每次调用 repaint 时都完全绘制两个面板。

但是有一些方法可以避免这种糟糕的组合。为此,您需要通过以下方式使您的绘画方法更加巧妙:

  1. 仅要求重新绘制已变脏的矩形(即旧椭圆和新椭圆的并集)
  2. 在您的绘制组件中,仅当Graphics 的剪辑与您计划绘制的区域相交时才进行重新绘制。如果没有交集,则可以跳过绘制操作。

小演示代码显示:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Ellipse2D.Double;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Glasspanetest extends JFrame {

public JFrame init() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
GraphicsPanel jp = new GraphicsPanel();
add(jp, BorderLayout.CENTER);
LabelGlassPane glass = new LabelGlassPane();
this.setGlassPane(glass);
glass.setVisible(true);
setSize(400, 400);
return this;
}

class GraphicsPanel extends JPanel {

private Shape oval = new Ellipse2D.Double(50, 50, 50, 50);

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (g.getClip().intersects(oval.getBounds2D())) {
g.setColor(Color.red);
((Graphics2D) g).fill(oval);
System.out.println("Painting bottom panel");
}
}
}

public Ellipse2D.Double ell = null;

class LabelGlassPane extends JComponent {
public LabelGlassPane() {
this.addMouseMotionListener(new MoveInfoListener());
}

public class MoveInfoListener implements MouseMotionListener {
@Override
public void mouseMoved(MouseEvent e) {
Ellipse2D.Double oldEll = ell;
ell = new Ellipse2D.Double(e.getX() - 3, e.getY() - 3, 6, 6);
LabelGlassPane.this.repaint(oldEll, ell);
}

@Override
public void mouseDragged(MouseEvent arg0) {
}
}

public void repaint(Double oldEll, Double ell) {
Rectangle rect = ell.getBounds();
if (oldEll != null) {
rect = rect.union(oldEll.getBounds());
}
// repaint(rect);
repaint();
}

@Override
public void paintComponent(Graphics g) {
// g.setColor(Color.red);
// Container root = frame.getRootPane();
// g.setColor(new Color(255,100,100,100));
// g.fillRect(100, 100, 500, 500);
if (ell != null) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.black);
g2.fill(ell);
System.out.println("Painted glass pane");
}

// rPaint(root,g);
}

}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new Glasspanetest().init().setVisible(true);
}
});
}

}

注意:这不是我最喜欢的应用程序方法,但它会起作用。不幸的是,我没有您的应用程序的完整情况,因此无法提供替代方法。

关于java - 在玻璃板上喷漆,无需重新喷漆其他部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25298319/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com