Ridding JFrame текущей формы. т.е. очистка "холста", например, в Microsoft Paint

Чтобы решить эту проблему, нужно избавиться от текущей фигуры в JFrame. Я только что закончил книгу о Джойсе Фарреле по Java, поэтому решил бросить вызов самому себе, чтобы создать это мини-приложение, но я застрял на том, чтобы эта форма исчезла. Я вырвал остальную часть кода, не имеющего отношения к проблеме, чтобы облегчить ответ на вопрос. Я по-прежнему добавил весь проект в конец для тех из вас, кто, возможно, захочет взглянуть немного глубже, или, возможно, это поможет найти решение.

Чтобы уточнить, первый сегмент вставленного кода, где я считаю, проблема заключается. Второй вставленный сегмент - это все, что я собрал до этого момента. Если проблема ясна, я был бы признателен, если бы не испортил мне этот опыт обучения, сказав мне ответ, если это действительно очень простое решение. Я буду продолжать искать простое решение в надежде сохранить больше информации во время моих собственных исследований. Просто дайте мне область для изучения Java. Надеюсь это поможет!!!

Во время работы приложения пользователь выбирает JMenuItem "New Canvas", и приложение внезапно зависает? Он не вылетает, но замораживает весь JFrame, заставляя пользователя закрыть JFrame и начать заново с приложением. В идеале, когда пользователь выбирает опцию "Новый холст", фигура в центре JFrame исчезает, но, к сожалению, все фигура задерживается все время, пока приложение зависает. Я предполагаю, что как только я избавляюсь от фигуры, она немедленно возвращается из-за метода paintComponent() и вызывает зависание приложения.

Пробовал ---- 1.) Я вызвал метод repaint(), а также метод validate() как действия, выполняемые при нажатии JMenuItem

2.) Я попытался закомментировать вызов super в методе paintComponent() и получил довольно аккуратные результаты, однако это не решило проблему

3.) Я попытался создать экземпляр объекта Graphics с начала класса, а затем создать метод, который принимает объект Graphics и преобразует его в объект Graphics2D, который затем нарисует простой квадрат в центре ошибки JFrame из эта попытка

 Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at JHouse.draw(JHouse.java:73)
        at JHouse.actionPerformed(JHouse.java:123)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
        at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
        at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
        at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
        at java.awt.Component.processMouseEvent(Component.java:6533)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
        at java.awt.Component.processEvent(Component.java:6298)
        at java.awt.Container.processEvent(Container.java:2236)
        at java.awt.Component.dispatchEventImpl(Component.java:4889)
        at java.awt.Container.dispatchEventImpl(Container.java:2294)
        at java.awt.Component.dispatchEvent(Component.java:4711)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
        at java.awt.Container.dispatchEventImpl(Container.java:2280)
        at java.awt.Window.dispatchEventImpl(Window.java:2746)
        at java.awt.Component.dispatchEvent(Component.java:4711)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
        at java.awt.EventQueue.access$500(EventQueue.java:97)
        at java.awt.EventQueue$3.run(EventQueue.java:709)
        at java.awt.EventQueue$3.run(EventQueue.java:703)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
        at java.awt.EventQueue$4.run(EventQueue.java:731)
        at java.awt.EventQueue$4.run(EventQueue.java:729)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Вот сокращенный код, содержащий основную проблему не правильно исчезающей фигуры:

import java.awt.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.event.*;

public class JHouse extends JPanel implements MouseListener, MouseMotionListener, ActionListener {

   private boolean isPressed;
   // Menus/Panel

   private static JFrame frame;
   private static JMenuBar mainBar = new JMenuBar();
   private static JMenu create = new JMenu("Create");
   private static JMenuItem canvas = new JMenuItem("New Canvas");

   // Locations/Sizes (Tools)
   private static int JSize = 700;
   private int rectXLoc = 200;
   private int rectYLoc = 200;
   private int rectXSize = 300;
   private int rectYSize = 300;

   public static void createJFrame() {

      frame = new JFrame();
      frame.add(new JHouse());
      frame.setLocation(650, 225);
      frame.setSize(JSize, JSize);
      frame.setVisible(true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setJMenuBar(mainBar);
      mainBar.add(create);
      create.add(canvas);
      frame.add(new JHouse(), "Center");
   }

   public JHouse() {

     canvas.addActionListener(this);
     addMouseListener(this);
     addMouseMotionListener(this);
   }

   public void paintComponent(Graphics g) {

      super.paintComponent(g);
      BasicStroke aStroke = new BasicStroke(1.0f,
         BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
      Graphics2D gr2D = (Graphics2D)g;
      gr2D.setStroke(aStroke);
      gr2D.drawRect(rectXLoc, rectYLoc, rectXSize, rectYSize);
   }

   public void mouseClicked(MouseEvent e) {

   }

   public void mousePressed(MouseEvent e) {

      isPressed = true;
   }

   public void mouseDragged(MouseEvent e) {

      int x = e.getX();
      int y = e.getY();

      if(isPressed){
         rectXLoc = x;
         rectYLoc = y;
         repaint();
         validate();     
      }
   }

   public void mouseReleased(MouseEvent e) {

      isPressed = false;
   }

   public void mouseEntered(MouseEvent e) {
   }

   public void mouseExited(MouseEvent e) {
   }

   public void mouseMoved(MouseEvent e) {
   }

   public void actionPerformed(ActionEvent e) {

      Object source = e.getSource();

      if(source == canvas) {
         frame.removeAll();
         frame.repaint();
         frame.validate();
      }
   }

   public static void main(String [] args) {

      createJFrame();
   }
}

Вот полный код проекта, который я сейчас предпринимаю:

import java.awt.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.event.*;

public class JHouse extends JPanel implements MouseListener, MouseMotionListener, ActionListener {

   //Graphics g;  This was part of attempt # 3 (Failed attempt)

   private boolean isPressed;

   // Menus/Panel
   private static JFrame frame;
   private static JMenuBar mainBar = new JMenuBar();
   private static JMenu create = new JMenu("Create");
   private static JMenu presets = new JMenu("Presets");
   private static JMenu transform = new JMenu("Transform");
   private static JMenu tools = new JMenu("Tools");
   private static JMenuItem canvas = new JMenuItem("New Canvas");
   private static JMenuItem freeDraw = new JMenuItem("Free Draw");
   private static JMenuItem rectangle = new JMenuItem("Rect Tool");
   private static JMenuItem polygon = new JMenuItem("Polygon Tool");
   private static JMenuItem circle = new JMenuItem("Circular Tool");

   // Locations/Sizes (Tools)
   private static int JSize = 700;
   private int rectXLoc = 200;
   private int rectYLoc = 200;
   private int rectXSize = 300;
   private int rectYSize = 300;

   public static void createJFrame() {

      frame = new JFrame();
      frame.add(new JHouse());
      frame.setLocation(650, 225);
      frame.setSize(JSize, JSize);
      frame.setVisible(true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setJMenuBar(mainBar);
      mainBar.add(create);
      mainBar.add(tools);
      mainBar.add(presets);
      create.add(canvas);
      tools.add(freeDraw);
      tools.add(rectangle);
      tools.add(polygon);
      tools.add(circle);
   }

   public JHouse() {

     canvas.addActionListener(this);
     freeDraw.addActionListener(this);
     rectangle.addActionListener(this);
     polygon.addActionListener(this);
     circle.addActionListener(this);
     addMouseListener(this);
     addMouseMotionListener(this);
   }

   public void paintComponent(Graphics g) {

      super.paintComponent(g);
      BasicStroke aStroke = new BasicStroke(1.0f,
         BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
      Graphics2D gr2D = (Graphics2D)g;
      gr2D.setStroke(aStroke);
      gr2D.drawRect(rectXLoc, rectYLoc, rectXSize, rectYSize);
   }

  /* public void draw(Graphics g) {
      BasicStroke aStroke = new BasicStroke(1.0f,
         BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);        This was a part of attempt # 3 (Failed attempt)
      Graphics2D gr2D = (Graphics2D)g;
      gr2D.setStroke(aStroke);
      gr2D.drawRect(rectXLoc, rectYLoc, rectXSize, rectYSize);
   }*/

   public void mouseClicked(MouseEvent e) {

      /* rectXSize += 6;
      repaint();
      validate();*/
   }
   public void mousePressed(MouseEvent e) {

      isPressed = true;
   }

   public void mouseDragged(MouseEvent e) {

      int x = e.getX();
      int y = e.getY();

      if(isPressed){
         rectXLoc = x;
         rectYLoc = y;
         repaint();
         validate();     
      }
   }

   public void mouseEntered(MouseEvent e) {
   }

   public void mouseExited(MouseEvent e) {
   }

   public void mouseMoved(MouseEvent e) {
   }

   public void mouseReleased(MouseEvent e) {

      isPressed = false;
   }

   public void actionPerformed(ActionEvent e) {

      Object source = e.getSource();

      if(source == canvas) {
         frame.removeAll();
         frame.repaint();  
         frame.validate();
         //draw(g);    This was part of attempt #3 (Failed attempt)

      }
   }
   public static void main(String [] args) {

      createJFrame();
   }
}

1 ответ

Решение

frame.removeAll() Метод удаляет все компоненты в кадре. Включая ваши меню, поэтому вы получаете исключение нулевого указателя. Решением здесь было бы сбросить начальные значения, установленные здесь, используя приватный метод. Например:

private void resetValues() {
    JSize = 700;   
    rectXLoc = 200;
    rectYLoc = 200;
    rectXSize = 300;
    rectYSize = 300;
}

используйте этот метод для сброса значений к начальным значениям, а затем вызовите этот метод вместо frame.removeAll(), Итак, ваше состояние будет:

if(source == canvas) {
     resetValues();
     frame.repaint();  
     frame.validate();
}

Здесь вы можете использовать этот метод для сброса значений всех операций. Я вижу, что у вас есть 4 различных доступных операции - Free Draw, Rectangle, Polygon и Circle. Вам необходимо сбросить все значения.

Если вам нужен пустой холст (т.е. вы хотите удалить все компоненты внутри него), объявите логическую переменную, скажем, boolean reset = false в качестве переменной класса и в paintComponent() Метод проверки:

if(reset) {
   reset = false; // you dont want reset to be set true permanantly
   return;
}
// rest of your code

и в actionPerformed() метод, перед вызовом frame.repaint() задавать reset = true, Это перекрасит компонент. но ничего не будет нарисовано, поэтому вы получите пустой холст.

Другие вопросы по тегам