Raf*_*eil 3 java swing drawing java-2d
在我的应用程序中,我需要像Photoshop那样绘制网格线 - 例如,用户可以在文档上拖动线条以帮助他对齐图层.现在,问题在于我能够绘制这样的线条(它只是简单的使用Line2D的简单Java2D绘画),但是我无法将这些线条放在其他所有内容之上,因为当子组件绘制自己时,我的网格线被删除了.
程序结构是这样的:JFrame - > JPanel - > JScrollPane - > JPanel - > [很多其他JPanels,就像层一样]
作为测试,我将绘制代码添加到JFrame,它正确显示我的Line2D实例在其他所有内容之上.但是,当我在子组件中执行任何需要该子项重新绘制的内容时,JFrame中绘制的线将被删除.
我知道这是预期的Swing行为 - 也就是说,它只会重绘那些已经改变的区域.但是,我正在寻找一些方法,不断在其他所有方面绘制线网格线.
我能够让它工作的唯一方法是使用一个Swing Timer,它每隔10ms在我的根组件上调用repaint(),但它消耗了大量的CPU.
更新
示例的工作代码如下.请注意,在我的实际应用程序中,我有许多可以触发重绘()的不同组件,并且没有一个组件引用了执行网格线绘制的组件(当然我可以将它传递给每个人,但是成为最新的选择)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想画在JComponents放置的JScrollPane,那么你可以画的JViewPort,例如这里
编辑:
1)因为您的代码被绘制到错误的容器中JFrame,确实可以绘制到JFrame,但是您必须提取RootPane或GlassPane
2)你必须学习如何使用LayoutManagers,我让你的代码用原始的大小调整,不好看也很糟糕
3)油漆到GlassPane或JViewPort
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.*;
public class GridTest extends JFrame {
private static final long serialVersionUID = 1L;
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() {
private static final long serialVersionUID = 1L;
@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();
}
};
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) {
p.repaint();
}
});
b.setBounds(0, 150, 100, 30);
add(b);
pack();
setVisible(true);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:2,如果你期望单行,在固定的界限上

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class GridTest extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
new GridTest().run();
}
private void run() {
setPreferredSize(new Dimension(200, 200));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel p = new JPanel() {
private static final long serialVersionUID = 1L;
@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();
}
};
JPanel p1 = new JPanel();
p1.setBorder(new LineBorder(Color.black,1));
JPanel p2 = new JPanel();
p2.setBorder(new LineBorder(Color.black,1));
JPanel p3 = new JPanel();
p3.setBorder(new LineBorder(Color.black,1));
p.setLayout(new GridLayout(3,0));
p.add(p1);
p.add(p2);
p.add(p3);
p.setBounds(20, 20, 100, 100);
p.setBackground(Color.white);
add(p, BorderLayout.CENTER);
JButton b = new JButton("Refresh");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
p.repaint();
}
});
add(b, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
Run Code Online (Sandbox Code Playgroud)