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
, Это перекрасит компонент. но ничего не будет нарисовано, поэтому вы получите пустой холст.