从JPanel的子类调用RemoveAll()时出现奇怪的Swing错误 [英] Strange Swing Error when from calling RemoveAll() on subclass of JPanel

查看:173
本文介绍了从JPanel的子类调用RemoveAll()时出现奇怪的Swing错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个Sudoku谜题生成器,并在调用JPanel的RemoveAll()方法之后/期间遇到一些间歇性的swing异常。当我在eclipse的调试模式下运行时,不会出现异常。以下是相关类的代码:

I'm working on a Sudoku puzzle generator and am running into some intermittent swing exceptions after/during a call to the RemoveAll() method of a JPanel. When I run in eclipse's debug mode, the exceptions do not appear. Here is the code for the class in question:

import java.awt.FlowLayout;
import java.awt.GridLayout;

import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * Represents a cell in the GUI Grid display
 * @author alex
 *
 */
public class CellGUI extends JPanel {



    public CellGUI()
    {
        super();

        this.setLayout(new GridLayout(3,3));

        for(int i = 1;i <=9;i++)
        {
            add(new JLabel("" + i));
        }

        setVisible(true);
    }

    public void clear()
    {
        this.removeAll();
        this.validate();
        this.setLayout(new GridLayout(3,3));

        for(int i = 1;i <= 9; i++)
        {
            add(new JLabel("" + i));
        }       

    }

    public void setValue(int newVal)
    {
        if (newVal == 0)
        {
            clear();
        }
        else
        {

            this.removeAll(); // this line appears to be the problem 

            //this.updateUI();
            //this.setLayout(new FlowLayout());

            //add(new   JLabel("" + newVal));
        }
    }
}

它通常会吐出这个异常:

It usually spits out this exception:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException
    at javax.swing.LayoutComparator.compare(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.mergeSort(Unknown Source)
    at java.util.Arrays.sort(Unknown Source)
    at java.util.Collections.sort(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(Unknown Source)
    at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(Unknown Source)
    at java.awt.FocusTraversalPolicy.getInitialComponent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.SequencedEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

我认为我的天真,我可能会以错误的方式做这件事。任何想法?

I figure in my naivety I'm probably going about doing this the wrong way. Any ideas?

编辑:根据要求,我发布了额外的代码。

By request, I'm posting additional code.

此类调用setValue CellGUI的方法:

This class calls the setValue method of the CellGUI:

public class GridGUI extends JPanel {

    ArrayList<CellGUI> cells = new ArrayList<CellGUI>();

    public GridGUI()
    {

        this.setLayout(new GridLayout(9,9));


        for(int i = 0; i < 81;i++)
        {
            CellGUI cell = new CellGUI();
            cells.add(cell);
            add(cell);
        }

    }


    public void updateGrid(Grid g)
    {
        for(int i = 0;i<81;i++)
        {
            cells.get(i).setValue(g.getValue(i));
        }
    }
}

GridGUI类已创建,由扩展JFrame的类管理:

The GridGUI class is created and managed by a class that extends JFrame:

public class GUI extends JFrame {   
...
public GUI() 
    {
        this.setLayout(new BorderLayout());
        add(gridGUI,BorderLayout.CENTER);

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout());
        panel.add(isValidLabel);
        panel.add(isSolvableLabel);
        panel.setVisible(true);

        add(panel, BorderLayout.SOUTH);

        this.setSize(600, 600);

        setVisible(true);       

    }
    public void loadGrid(String path)
    {
        grid = new Grid(path);
        grid.print();

        gridGUI.updateGrid(grid);

        updateLabels();
    }
...
}

我的主要课程:

public static void main(String[] args) 
{       
    GUI gui = new GUI();
    gui.loadGrid(args[0]);
}


推荐答案

所以,看看堆栈-trace显示当FocusManager尝试获取第一个组件时发生错误。为此,您的FocusTraversalPolicy尝试按布局顺序排序组件,这意味着大致在列和行中。对于GridLayout,这应该是完全无关紧要的。我们来看看 LayoutComparator 的代码。它在某些地方抛出ClassCastException:

So, looking at the stack-trace shows that the error occurs when the FocusManager is trying to get the first component. For this, your FocusTraversalPolicy tries to order the components in "layout order", which means roughly in columns and rows. For a GridLayout, this should be totally trivial. Let's look at the code of LayoutComparator. It throws a ClassCastException in some places:

        if (a == null) {
            // 'a' is not part of a Window hierarchy. Can't cope.
            throw new ClassCastException();
        }

a是这里包含的窗口,还是 null 如果不存在这样的窗口。

a is either the containing Window here, or null if no such Window exists.

因此,看起来您的组件尚未在组件树中完全注册。正如其他人所说,如果你在不在AWT事件派发线程中的GUI中做了一些更改,就会发生这种情况。

So, looks like your components are not yet totally registered in the Component tree. As the others said, this can occur if you do some changes in the GUI when not being in the AWT event dispatch thread.

为了避免这种情况,包装所有在 EventQueue.invokeLater(...) 。 (有时 invokeAndWait 更有用,你也可以在SwingUtilities中使用相同名称的方法。)在你的情况下,改变非常简单:

To avoid this, wrap all changes to the GUI (including creating the components, like your constructor call above) in a call of EventQueue.invokeLater(...). (Sometimes invokeAndWait is more useful, and you also can use the same-named methods in SwingUtilities instead.) In your case, the change is quite simple:

public static void main(String[] args) 
{
    EventQueue.invokeLater(new Runnable() { public void run() {
        GUI gui = new GUI();
        gui.loadGrid(args[0]);
    }});
}

这篇关于从JPanel的子类调用RemoveAll()时出现奇怪的Swing错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆