在我的应用程序中,我需要绘制网格线,就像Photoshop一样 - 例如,用户可以在文档上拖动线条来帮助对齐图层。现在,问题是我能够绘制这样的线条(只是使用Line2D进行简单的Java2D绘画),但我不能将这样的线条保持在其他所有内容的顶部,因为当子组件绘制自己时,我的网格线会被擦除。
程序结构如下:JFrame -> JPanel -> JScrollPane -> JPanel -> [许多其他像图层一样的JPanel]
作为测试,我将绘图代码添加到了JFrame中,它正确地显示了我的Line2D实例位于其他所有内容的顶部。然而,当我在需要子组件重新绘制自身的任何子组件中执行任何操作时,JFrame中绘制的线条会被擦除。
我知道这是预期的Swing行为 - 也就是说,它只会重新绘制那些已更改的区域。但是,我正在寻找一些方法来持续在其他所有内容的顶部绘制网格线。
我唯一能够使其工作的方法是使用一个Swing定时器,每10毫秒调用我的根组件上的repaint(),但它会消耗大量CPU。
更新 下面是一个示例的工作代码。请注意,在我的实际应用程序中,我有数十个不同的组件可能会触发repaint(),而且它们都没有对执行网格线绘制的组件的引用(当然我可以将其传递给每个人,但那似乎是最后的选择)。
程序结构如下:JFrame -> JPanel -> JScrollPane -> JPanel -> [许多其他像图层一样的JPanel]
作为测试,我将绘图代码添加到了JFrame中,它正确地显示了我的Line2D实例位于其他所有内容的顶部。然而,当我在需要子组件重新绘制自身的任何子组件中执行任何操作时,JFrame中绘制的线条会被擦除。
我知道这是预期的Swing行为 - 也就是说,它只会重新绘制那些已更改的区域。但是,我正在寻找一些方法来持续在其他所有内容的顶部绘制网格线。
我唯一能够使其工作的方法是使用一个Swing定时器,每10毫秒调用我的根组件上的repaint(),但它会消耗大量CPU。
更新 下面是一个示例的工作代码。请注意,在我的实际应用程序中,我有数十个不同的组件可能会触发repaint(),而且它们都没有对执行网格线绘制的组件的引用(当然我可以将其传递给每个人,但那似乎是最后的选择)。
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GridTest extends JFrame {
public static void main(String[] args) {
new GridTest().run();
}
private void run() {
setLayout(null);
setPreferredSize(new Dimension(200, 200));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel p = new JPanel();
p.setBounds(20, 20, 100, 100);
p.setBackground(Color.white);
add(p);
JButton b = new JButton("Refresh");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// When I call repaint() here, the paint() method of
// JFrame it's not called, thus resulting in part of the
// red line to be erased / overridden.
// In my real application application, I don't have
// easy access to the component that draws the lines
p.repaint();
}
});
b.setBounds(0, 150, 100, 30);
add(b);
pack();
setVisible(true);
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D gg = (Graphics2D)g.create();
Line2D line = new Line2D.Double(0, 50, getWidth(), 50);
gg.setStroke(new BasicStroke(3));
gg.setColor(Color.red);
gg.draw(line);
gg.dispose();
}
}