Очистить окно от объектов рисования

У меня 4 класса:

Draw, Rectangle (продолжается Draw), FreeHand (расширяет Draw) и тестовый класс.

Я добавляю прямоугольники и линии, оттянутые свободной рукой в массивList.

У меня есть меню с вариантами Back and Clear. Назад удаляет последний нарисованный объект. Это делается путем удаления последнего объекта в arraylist. Очистить очищает окна. Это делается путем очистки архариста от всех предметов.

Теперь к моей проблеме: окно не очищается. Я не знаю, как написать код, чтобы он правильно перерисовывался, чтобы элементы удалялись из окна. Можете ли вы, пожалуйста, помочь мне, как выглядит код для этого, и где я его разместил. Я ценю это, спасибо.

Моя проблема № 2: после того, как я удалил последний элемент в arraylist, мне нужно нарисовать все элементы в списке arrayList. я пытался

for (Draw d : shapeList) {
 d.draw(g2);
 }

Но это не работает. Какие-либо предложения? Класс Ничья:

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public abstract class Draw extends JPanel {

 public int startX, startY, endX, endY, width, height, w, h;
 public String color = "Black";

 public Draw(int startX, int startY, int width, int height) {
 this.startX = startX;
 this.startY = startY;
 this.width = width;
 this.height = height;
 }

 public abstract void draw(Graphics2D g);


 @Override
 public int getX() {
 return startX;
 }

 public void setX(int startX) {
 this.startX = startX;
 }

 @Override
 public int getY() {
 return startY;
 }

 public void setY(int startY) {
 this.startY = startY;
 }

 @Override
 public int getWidth() {
 return width;
 }

 public void setWidth(int width) {
 this.width = width;
 }

 @Override
 public int getHeight() {
 return height;
 }

 public void setHeight(int height) {
 this.height = height;
 }

 public void setColor(String color) {
 this.color = color;
 }
}

Прямоугольник класса:

import java.awt.Color;
import java.awt.Graphics2D;

public class Rectangle extends Draw {

 public Rectangle(int x, int y, int width, int height) {
 super(x, y, width, height);
 }

 @Override
 public void draw(Graphics2D g2) {
 switch (color) {
 case "Red":
 g2.setColor(Color.RED);
 break;
 case "Green":
 g2.setColor(Color.GREEN);
 break;
 case "Blue":
 g2.setColor(Color.BLUE);
 break;
 case "Yellow":
 g2.setColor(Color.YELLOW);
 break;
 case "Orange":
 g2.setColor(Color.ORANGE);
 break;
 case "Black":
 g2.setColor(Color.BLACK);
 break;
 }

 g2.drawRect(getX(), getY(), getWidth(), getHeight());
 } 
}

Класс FreeHand:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;

public class FreeHand extends Draw {

 public FreeHand(int x, int y, int width, int height) {
 super(x, y, width, height);
 }

 /* public FreeHand() {
 super();
 }*/


 @Override
 public void draw(Graphics2D g2) {
 //Graphics2D g2 = (Graphics2D) g; 
 g2.setStroke(new BasicStroke(3)); 
 switch (color) {
 case "Red":
 g2.setColor(Color.RED);
 break;
 case "Green":
 g2.setColor(Color.GREEN);
 break;
 case "Blue":
 g2.setColor(Color.BLUE);
 break;
 case "Yellow":
 g2.setColor(Color.YELLOW);
 break;
 case "Orange":
 g2.setColor(Color.ORANGE);
 break;
 case "Black":
 g2.setColor(Color.BLACK);
 break;
 }
 g2.drawLine(getX(), getY(), getWidth(), getHeight());
 }
}

TestClass:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;

public class JavaApplication30 extends JFrame implements ActionListener {

 public ArrayList<draw> shapeList = new ArrayList<>(); 
 int startX, startY, endX, endY, w, h;
 private JPanel topPanel; 
 private JPanel bottomPanel;
 private JPanel orangePanel;
 private JPanel greenPanel;
 private JPanel *********;
 private JPanel blackPanel;
 private JPanel redPanel;
 private JPanel yellowPanel;
 private JPanel leftPanel;
 private JPanel rightPanel;
 private JPanel colorPanel; 
 private JMenuBar menuBar;
 private JMenu menu;
 private JMenuItem menuItem1;
 private JMenuItem menuItem2;
 private JMenuItem menuItem3;
 private JComboBox comboBox;
 private JLabel leftLabel; 
 private JLabel commaLabel;
 private JLabel colorLabel;
 private static JLabel xLabel;
 private static JLabel yLabel;
 private final String labelText = "Coordinates: ";
 private final String comma = ",";
 private final String color = "Color: "; 
 private final String[] boxOptions = new String[] {"Rectangle", "Freehand"}; 
 private String pickedColor = "Black";
 private String x = "";
 private String y = ""; 
 Container cp = getContentPane();
 private int count = 0;



 public JavaApplication30(String title) {
 super(title);
 this.setLayout(new BorderLayout());
 this.setLocationRelativeTo(null); 
 this.setSize(840, 500); 
 this.initComponents();
 this.initMenu();
 this.setVisible(true);
 }


 private void initComponents() {
 cp.setBackground(Color.WHITE);

 comboBox = new JComboBox(boxOptions);
 topPanel = new JPanel(new GridLayout(1,7)); 
 bottomPanel = new JPanel(new GridLayout(1,2)); 
 orangePanel = new JPanel();
 greenPanel = new JPanel();
 *********= new JPanel();
 blackPanel = new JPanel();
 redPanel = new JPanel();
 yellowPanel = new JPanel();
 colorPanel = new JPanel();
 rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
 leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

 comboBox.setSelectedIndex(0); 
 comboBox.addActionListener(this); 

 topPanel.setPreferredSize(new Dimension(0,40)); 
 bottomPanel.setPreferredSize(new Dimension(0,30));
 colorPanel.setPreferredSize(new Dimension(60,20)); 

 leftLabel = new JLabel(labelText);
 commaLabel = new JLabel(comma);
 colorLabel = new JLabel(color); 

 bottomPanel.setBackground(Color.LIGHT_GRAY); 
 orangePanel.setBackground(Color.ORANGE); 
 greenPanel.setBackground(Color.GREEN);
 *********.setBackground(Color.BLUE); 
 blackPanel.setBackground(Color.BLACK); 
 redPanel.setBackground(Color.RED); 
 yellowPanel.setBackground(Color.YELLOW); 
 colorPanel.setBackground(Color.BLACK);

 topPanel.add(orangePanel);
 topPanel.add(greenPanel); 
 topPanel.add(*********); 
 topPanel.add(blackPanel);
 topPanel.add(redPanel);
 topPanel.add(yellowPanel);
 topPanel.add(comboBox);
 rightPanel.add(colorLabel);
 rightPanel.add(colorPanel);
 bottomPanel.add(leftPanel); 
 bottomPanel.add(rightPanel);

 this.add(topPanel, BorderLayout.PAGE_START); 
 this.add(bottomPanel, BorderLayout.PAGE_END);

 }


 @Override
 public void paint(Graphics g) {
 if(count == 0) {
 cp.repaint();
 }

 Graphics2D g2 = (Graphics2D) g;
 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

 g2.setStroke(new BasicStroke(1));

 for (Draw d : shapeList) {
 d.draw(g2);
 }


 if (startX != 0 && startY != 0 && endX != 0 && endY != 0) {

 int width = Math.abs(startX - endX);
 int height = Math.abs(startY - endY);

 int minX = Math.min(startX, endX);
 int minY = Math.min(startY, endY); 

 Rectangle r = new Rectangle(minX, minY, width, height);

 g2.setPaint(Color.WHITE);
 g2.fillRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 
 r.setColor(pickedColor);

 r.draw(g2);
 }
 }



 @Override
 public void actionPerformed(ActionEvent e) {
 count++;
 if (e.getSource().equals(menuItem1)) { 
 shapeList.clear();

 //Code to clear window

 }
 if (e.getSource().equals(menuItem2)) {
 shapeList.remove(shapeList.size() - 1);

 //Code to clear window

 Graphics g = getGraphics(); 
 Graphics2D g2 = (Graphics2D) g;
 for (Draw d : shapeList) {
 d.draw(g2);
 } 
 }


 if (e.getSource().equals(menuItem3)) {
 //Exit
 }



 if (e.getSource().equals(comboBox)) { 

 JComboBox cb = (JComboBox)e.getSource();

 if (cb.getSelectedItem().equals("Rectangle")) {

 this.addMouseListener(new MouseAdapter() { 

 @Override
 public void mousePressed(MouseEvent e) { 
 startX = e.getX(); 
 startY = e.getY(); 

 endX = startX; 
 endY = startY; 
 repaint(); 

 }

 @Override
 public void mouseReleased(MouseEvent e) {
 endX = e.getX();
 endY = e.getY();

 int width = Math.abs(startX - endX);
 int height = Math.abs(startY - endY);

 int minX = Math.min(startX, endX);
 int minY = Math.min(startY, endY); 

 Rectangle r = new Rectangle(minX, minY, width, height);
 shapeList.add(r);
 r.setColor(pickedColor);

 startX = 0;
 startY = 0;
 endX = 0;
 endY = 0;
 repaint();
 }
 }); 

 this.addMouseMotionListener(new MouseMotionAdapter() {
 @Override
 public void mouseDragged(MouseEvent e) {
 endX = e.getX();
 endY = e.getY();
 repaint();
 }
 });
 } 


 else if (cb.getSelectedItem().equals("Freehand")) {

 this.addMouseListener(new MouseAdapter() { 
 @Override
 public void mousePressed(MouseEvent e) { 
 startX = e.getX();
 startY = e.getY(); 
 }
 });

 this.addMouseMotionListener(new MouseMotionAdapter() {
 @Override
 public void mouseDragged(MouseEvent e) { 
 Graphics g = getGraphics(); 
 Graphics2D g2 = (Graphics2D) g; 

 FreeHand fh = new FreeHand(startX, startY, e.getX(), e.getY());
 shapeList.add(fh);
 fh.setColor(pickedColor);
 fh.draw(g2); 
 startX = e.getX();
 startY = e.getY(); 
 }
 }); 
 }
 }
 }





 private void initMenu() {

 menuBar = new JMenuBar();
 menu = new JMenu("File");
 menuBar.add(menu);


 menuItem1 = new JMenuItem("Clear");
 menuItem2 = new JMenuItem("Back");
 menuItem3 = new JMenuItem("Exit");
 menu.add(menuItem1);
 menu.add(menuItem2);
 menu.addSeparator();
 menu.add(menuItem3);

 menu.setMnemonic(KeyEvent.VK_A); 
 KeyStroke ks1 = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK); //Crtl+n
 KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_MASK); //Ctrl+i
 KeyStroke ks3 = KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK); //Ctrl+e 
 menuItem1.setAccelerator(ks1);
 menuItem2.setAccelerator(ks2);
 menuItem3.setAccelerator(ks3);

 menuItem1.addActionListener(this); 
 menuItem2.addActionListener(this);
 menuItem3.addActionListener(this);

 setJMenuBar(menuBar); 
 }




 public static void main(String args[]) {
 new JavaApplication30("Draw");
 }
}
</draw>
1 ответ

Ваша проблема заключается в том, что ваш метод рисования не вызывает метод суперкраски, поскольку у этого компонента будет чистый элемент всех "грязных" битов изображения. Но, сказав это, вы не должны рисовать непосредственно в JFrame. Вместо этого примените метод paintComponent для JComponent или JPanel, и в этом методе обязательно вызовите метод super paintComponent:

public class MyDrawingPanel extends JPanel {

 @Override
 proteced void paintComponent(Graphics g) {
 super.paintComponent(g); // don't forget this!

 // do your drawing here
 }
}

Кроме того, почему ваш класс Draw и, следовательно, все классы, полученные из него, расширяют JPanel, когда он не используется как JPanel? Таким образом, вы уделяете много лишних накладных расходов этим классам.

редактировать Ты спрашиваешь:

Значит, вы хотите переместить все в методе paint-метод paintComponent в Draw? Почему защищено?

Нет. Я имею в виду, что Draw не должен расширять JPanel, но вместо этого должен быть логическим классом, а не производным от Swing классом. Я думаю, что вы должны создать новый класс, например MyDrawingPanel, где вы делаете весь свой рисунок. См. Мой фрагмент кода выше. Также paintComponent объявлен в JComponent для защиты, а не для публики, и я не вижу преимущества, чтобы сделать его общедоступным при его переопределении, поэтому рекомендую оставить его защищенным.

Пожалуйста, ознакомьтесь с Swing Info Links, чтобы увидеть обучающие видеоролики Swing и дать им прочитать.

Изменить 2 Вы также используете getGraphics() для компонента, чтобы получить объект Graphics, а не хороший, поскольку он вернет нестабильный графический объект. Вместо этого сделайте весь чертеж в методе paintComponent или в BufferedImage (который снова нарисован в paintComponent).

Редактировать 3

Некоторые из моих примеров кода:

licensed under cc by-sa 3.0 with attribution.