JFrame
s не предназначены для переопределения paintComponent
: это многослойные контейнеры. Если вы хотите нарисовать пользовательский компонент, создайте подкласс JComponent
(или JPanel
), а затем вставьте его (панель содержимого) в ваш JFrame
.
. Это работает для меня:
public class SketchPad extends JComponent {
private final List<Line> lineList = new ArrayList<>();
private Line currentLine = null;
private Color drawingColor = Color.RED;
public SketchPad() {
initialize();
}
public Color getDrawingColor() {
return drawingColor;
}
public void setDrawingColor(Color newColor) {
if (newColor == null) {
throw new IllegalArgumentException("Drawing color cannot be null");
}
this.drawingColor = newColor;
}
private void initialize() {
addMouseListener(new MouseAdapter() {
int x1;
int y1;
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
currentLine = null;
}
@Override
public void mouseReleased(MouseEvent e) {
Line line = createLine(e, drawingColor);
lineList.add(line);
currentLine = null;
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
currentLine = createLine(e, Color.BLACK);
repaint();
}
private Line createLine(MouseEvent e, Color currentColor) {
int x2 = e.getX();
int y2 = e.getY();
return new Line(x1, x2, y1, y2, currentColor);
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Line line : lineList) {
line.draw(g);
System.out.println(line);
}
if (currentLine != null) {
currentLine.draw(g);
}
}
private static class Line {
private final int x1;
private final int x2;
private final int y1;
private final int y2;
private final Color color;
public Line(int x1, int x2, int y1, int y2, Color color) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.color = color;
}
public void draw(Graphics page) {
page.setColor(color); //!! This first!
page.drawLine(x1, y1, x2, y2); // **Then** this
}
}
}
Основной кадр:
public class MainFrame extends javax.swing.JFrame {
private SketchPad pad;
public MainFrame() {
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents() {
pad = new SketchPad();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().add(pad, java.awt.BorderLayout.CENTER);
pack();
}
}
ОБНОВЛЕНИЕ: необходим mouseMotionListener:
private void initialize() {
MouseAdapter adapter = new MouseAdapter() {
int x1;
int y1;
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
currentLine = null;
addMouseMotionListener(this);
}
@Override
public void mouseReleased(MouseEvent e) {
Line line = createLine(e, drawingColor);
lineList.add(line);
currentLine = null;
repaint();
removeMouseMotionListener(this);
}
@Override
public void mouseDragged(MouseEvent e) {
currentLine = createLine(e, Color.BLACK);
repaint();
}
private Line createLine(MouseEvent e, Color currentColor) {
int x2 = e.getX();
int y2 = e.getY();
return new Line(x1, x2, y1, y2, currentColor);
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
ОБНОВЛЕНИЕ 2: обрабатывать включение / отключение
private final MouseAdapter adapter = new MouseAdapter() {
int x1;
int y1;
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
currentLine = null;
}
@Override
public void mouseReleased(MouseEvent e) {
Line line = createLine(e, drawingColor);
lineList.add(line);
currentLine = null;
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
currentLine = createLine(e, Color.BLACK);
repaint();
}
private Line createLine(MouseEvent e, Color currentColor) {
int x2 = e.getX();
int y2 = e.getY();
return new Line(x1, x2, y1, y2, currentColor);
}
};
...
private void initialize() {
setEnabled(isEnabled());
}
...
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled) {
addMouseListener(adapter);
addMouseMotionListener(adapter);
} else {
removeMouseListener(adapter);
removeMouseMotionListener(adapter);
}
}