多次单击按钮后 Small Swing 应用程序崩溃
Small Swing Application Crashes after Clicking Buttons multiple times
此代码是问答游戏的简单引擎。这个想法是答案显示在 JButton 上。为此,我必须设置一个刷新方法来删除所有内容并重新绘制它。似乎每次调用此方法时,它都会变得越来越慢。单击大约 10 次按钮后它变得非常慢,它将停止响应,我将不得不手动关闭程序。
谢谢
package mainPackage;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MainGame{
static JFrame frame;
static WindowComp w;
public static void main(String[] args) {
frame = new JFrame("Game");
w = new WindowComp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setVisible(true);
frame.setResizable(true);
WindowComp.setAnswers( "start", "start", "start", "start");
WindowComp.refreshAll(w, frame);
WindowComp.setAnswers("final", "final", "final", "final");
WindowComp.refreshAll(w, frame);
}
}
public class WindowComp extends JComponent implements ActionListener {
static JButton [] buttons = new JButton[4];
static JLabel question = new JLabel("default");
public WindowComp(){
setAnswers("default", "default", "default", "default");
}
public void paintComponent(Graphics g){
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == buttons[0]){
setQuestion("button 1");
}
if(e.getSource() == buttons[1]){
setQuestion("button 2");
}
if(e.getSource() == buttons[2]){
setQuestion("button 3");
}
if(e.getSource() == buttons[3]){
setQuestion("button 4");
}
refreshAll(MainGame.w, MainGame.frame);
}
public void addAll(){
setLayout(new FlowLayout());
buttons[0].addActionListener(this);
buttons[1].addActionListener(this);
buttons[2].addActionListener(this);
buttons[3].addActionListener(this);
add(buttons[0]);
add(buttons[1]);
add(buttons[2]);
add(buttons[3]);
add(question);
}
public static void setAnswers( String ans1, String ans2, String ans3,String ans4){
buttons[0] = new JButton("Answer 1 : " + ans1);
buttons[1] = new JButton("Answer 2 : " + ans2);
buttons[2] = new JButton("Answer 3 : " + ans3);
buttons[3] = new JButton("Answer 4 : " + ans4);
}
public static void setQuestion(String q){
question = new JLabel("Question: " + q);
}
public static void refreshAll(WindowComp w, JFrame frame){
w.removeAll();
w.addAll();
w.revalidate();
frame.add(w);
}
}
您的问题是 ActionListeners 总是添加到按钮,但从未被删除。一个快速的解决方法是编写一个方法来删除它们:
public void removeActionListeners(){
buttons[0].removeActionListener(this);
buttons[1].removeActionListener(this);
buttons[2].removeActionListener(this);
buttons[3].removeActionListener(this);
}
然后在你的"refreshAll()"中调用它:
public static void refreshAll(WindowComp w, JFrame frame){
w.removeActionListeners();
w.removeAll();
w.addAll();
w.revalidate();
frame.add(w);
}
...正如已经指出的那样,这 不是 执行此操作的最佳方法,但它不会再滞后了。
好的,正如评论所说,你添加的ActionListener过多,导致你描述的问题。
以下是我想给你的一些建议。
首先,您不必每次都使用关键字 new
来更改按钮的文本。垃圾收集将摆脱未使用的按钮,但为什么您想要新按钮而不是仅通过 setTest(String)
更新按钮上的文本,这不会调用任何垃圾收集。
最后,尽量多使用构造函数,实际上你可以让你需要的一切(至少在这种情况下,不是一般情况下)在调用构造函数时创建。例如,您可以在构造函数中创建所有 JButton 并将所有侦听器添加到按钮(我将在下面提供一些代码)。
我稍微重写了你的代码,它的功能与你的不一样,但也没有崩溃。
package de;
import javax.swing.JFrame;
public class MainGame{
static JFrame frame;
static WindowComp w;
public static void main(String[] args) {
frame = new JFrame("Game");
w = new WindowComp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.add(w);
frame.setVisible(true);
frame.setResizable(true);
/*WindowComp.setAnswers( "start", "start", "start", "start");
WindowComp.refreshAll(w, frame);
WindowComp.setAnswers("final", "final", "final", "final");
WindowComp.refreshAll(w, frame);*/
}
}
package de;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
@SuppressWarnings("serial")
public class WindowComp extends JComponent implements ActionListener {
static JButton [] buttons;
static JLabel question;
public WindowComp(){
question = new JLabel("default");
buttons = new JButton[4];
setLayout(new FlowLayout());
buttons[0] = new JButton("Answer 1 : " + "default");
buttons[1] = new JButton("Answer 2 : " + "default");
buttons[2] = new JButton("Answer 3 : " + "default");
buttons[3] = new JButton("Answer 4 : " + "default");
buttons[0].addActionListener(this);
buttons[1].addActionListener(this);
buttons[2].addActionListener(this);
buttons[3].addActionListener(this);
addAll();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == buttons[0]){
setQuestion("button 1");
setAnswers( "start", "start", "start", "start");
}
if(e.getSource() == buttons[1]){
setQuestion("button 2");
setAnswers("final", "final", "final", "final");
}
if(e.getSource() == buttons[2]){
setQuestion("button 3");
}
if(e.getSource() == buttons[3]){
setQuestion("button 4");
}
//refreshAll(MainGame.w, MainGame.frame);
}
public void addAll(){
add(buttons[0]);
add(buttons[1]);
add(buttons[2]);
add(buttons[3]);
add(question);
}
public static void setAnswers( String ans1, String ans2, String ans3,String ans4){
buttons[0].setText("Answer 1 : " + ans1);
buttons[1].setText("Answer 2 : " + ans2);
buttons[2].setText("Answer 3 : " + ans3);
buttons[3].setText("Answer 4 : " + ans4);
}
public static void setQuestion(String q){
question.setText("Question: " + q);
}
public static void refreshAll(WindowComp w, JFrame frame){
w.removeAll();
w.addAll();
w.revalidate();
frame.add(w);
}
}
编辑:就当前代码而言,您的函数 refreshAll(WindowComp w, JFrame frame)
不再被调用,因为目前不需要调用它。在没有调用的情况下测试程序后,我用这个编辑将其注释掉。
此代码是问答游戏的简单引擎。这个想法是答案显示在 JButton 上。为此,我必须设置一个刷新方法来删除所有内容并重新绘制它。似乎每次调用此方法时,它都会变得越来越慢。单击大约 10 次按钮后它变得非常慢,它将停止响应,我将不得不手动关闭程序。
谢谢
package mainPackage;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MainGame{
static JFrame frame;
static WindowComp w;
public static void main(String[] args) {
frame = new JFrame("Game");
w = new WindowComp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setVisible(true);
frame.setResizable(true);
WindowComp.setAnswers( "start", "start", "start", "start");
WindowComp.refreshAll(w, frame);
WindowComp.setAnswers("final", "final", "final", "final");
WindowComp.refreshAll(w, frame);
}
}
public class WindowComp extends JComponent implements ActionListener {
static JButton [] buttons = new JButton[4];
static JLabel question = new JLabel("default");
public WindowComp(){
setAnswers("default", "default", "default", "default");
}
public void paintComponent(Graphics g){
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == buttons[0]){
setQuestion("button 1");
}
if(e.getSource() == buttons[1]){
setQuestion("button 2");
}
if(e.getSource() == buttons[2]){
setQuestion("button 3");
}
if(e.getSource() == buttons[3]){
setQuestion("button 4");
}
refreshAll(MainGame.w, MainGame.frame);
}
public void addAll(){
setLayout(new FlowLayout());
buttons[0].addActionListener(this);
buttons[1].addActionListener(this);
buttons[2].addActionListener(this);
buttons[3].addActionListener(this);
add(buttons[0]);
add(buttons[1]);
add(buttons[2]);
add(buttons[3]);
add(question);
}
public static void setAnswers( String ans1, String ans2, String ans3,String ans4){
buttons[0] = new JButton("Answer 1 : " + ans1);
buttons[1] = new JButton("Answer 2 : " + ans2);
buttons[2] = new JButton("Answer 3 : " + ans3);
buttons[3] = new JButton("Answer 4 : " + ans4);
}
public static void setQuestion(String q){
question = new JLabel("Question: " + q);
}
public static void refreshAll(WindowComp w, JFrame frame){
w.removeAll();
w.addAll();
w.revalidate();
frame.add(w);
}
}
您的问题是 ActionListeners 总是添加到按钮,但从未被删除。一个快速的解决方法是编写一个方法来删除它们:
public void removeActionListeners(){
buttons[0].removeActionListener(this);
buttons[1].removeActionListener(this);
buttons[2].removeActionListener(this);
buttons[3].removeActionListener(this);
}
然后在你的"refreshAll()"中调用它:
public static void refreshAll(WindowComp w, JFrame frame){
w.removeActionListeners();
w.removeAll();
w.addAll();
w.revalidate();
frame.add(w);
}
...正如已经指出的那样,这 不是 执行此操作的最佳方法,但它不会再滞后了。
好的,正如评论所说,你添加的ActionListener过多,导致你描述的问题。
以下是我想给你的一些建议。
首先,您不必每次都使用关键字 new
来更改按钮的文本。垃圾收集将摆脱未使用的按钮,但为什么您想要新按钮而不是仅通过 setTest(String)
更新按钮上的文本,这不会调用任何垃圾收集。
最后,尽量多使用构造函数,实际上你可以让你需要的一切(至少在这种情况下,不是一般情况下)在调用构造函数时创建。例如,您可以在构造函数中创建所有 JButton 并将所有侦听器添加到按钮(我将在下面提供一些代码)。
我稍微重写了你的代码,它的功能与你的不一样,但也没有崩溃。
package de;
import javax.swing.JFrame;
public class MainGame{
static JFrame frame;
static WindowComp w;
public static void main(String[] args) {
frame = new JFrame("Game");
w = new WindowComp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.add(w);
frame.setVisible(true);
frame.setResizable(true);
/*WindowComp.setAnswers( "start", "start", "start", "start");
WindowComp.refreshAll(w, frame);
WindowComp.setAnswers("final", "final", "final", "final");
WindowComp.refreshAll(w, frame);*/
}
}
package de;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
@SuppressWarnings("serial")
public class WindowComp extends JComponent implements ActionListener {
static JButton [] buttons;
static JLabel question;
public WindowComp(){
question = new JLabel("default");
buttons = new JButton[4];
setLayout(new FlowLayout());
buttons[0] = new JButton("Answer 1 : " + "default");
buttons[1] = new JButton("Answer 2 : " + "default");
buttons[2] = new JButton("Answer 3 : " + "default");
buttons[3] = new JButton("Answer 4 : " + "default");
buttons[0].addActionListener(this);
buttons[1].addActionListener(this);
buttons[2].addActionListener(this);
buttons[3].addActionListener(this);
addAll();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == buttons[0]){
setQuestion("button 1");
setAnswers( "start", "start", "start", "start");
}
if(e.getSource() == buttons[1]){
setQuestion("button 2");
setAnswers("final", "final", "final", "final");
}
if(e.getSource() == buttons[2]){
setQuestion("button 3");
}
if(e.getSource() == buttons[3]){
setQuestion("button 4");
}
//refreshAll(MainGame.w, MainGame.frame);
}
public void addAll(){
add(buttons[0]);
add(buttons[1]);
add(buttons[2]);
add(buttons[3]);
add(question);
}
public static void setAnswers( String ans1, String ans2, String ans3,String ans4){
buttons[0].setText("Answer 1 : " + ans1);
buttons[1].setText("Answer 2 : " + ans2);
buttons[2].setText("Answer 3 : " + ans3);
buttons[3].setText("Answer 4 : " + ans4);
}
public static void setQuestion(String q){
question.setText("Question: " + q);
}
public static void refreshAll(WindowComp w, JFrame frame){
w.removeAll();
w.addAll();
w.revalidate();
frame.add(w);
}
}
编辑:就当前代码而言,您的函数 refreshAll(WindowComp w, JFrame frame)
不再被调用,因为目前不需要调用它。在没有调用的情况下测试程序后,我用这个编辑将其注释掉。