Creating JTextPane is leading to NullPointerException - OpenOffice Extension - java

I'm currently developing an Extension for OpenOffice. I'm using Java 1.6 and the OpenOffice SDK 4.1.2.
If I try to create a javax.swing.JTextPane, I get a NullpointerException in the Constructor of JTextPane.
public class Dialog extends javax.JFrame {
private final JTextPane jTextPane;
private final JTable jTable;
public Dialog() {
jTable = new JTable();
jTextPane = new JTextPane();
}
}
The Dialog is initialized in another Thread:
public class DialogManager {
private static JournalDialog journalDialog;
public void showDialog() {
Thread startThread = new Thread(new Runnable() {
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
dialog = new Dialog();
...
}
}
}
}
}}
The creation of JTable works fine, but in the next line I get a Nullpointerexception
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at java.util.Hashtable.put(Unknown Source)
at javax.swing.JEditorPane.registerEditorKitForContentType(Unknown Source)
at javax.swing.JEditorPane.registerEditorKitForContentType(Unknown Source)
at javax.swing.JEditorPane.loadDefaultKitsIfNecessary(Unknown Source)
at javax.swing.JEditorPane.getKitTypeRegistry(Unknown Source)
at javax.swing.JEditorPane.getEditorKitClassNameForContentType(Unknown Source)
at javax.swing.JTextPane.<init>(Unknown Source)
at .gui.Dialog.<init>(Dialog.java:159)
at .gui.DialogManager$6$1.run(DialogManager.java:334)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.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 hope someone has an idea what causes this exception. I tried to run the extension in Java 1.7 and 1.8, but there is the same issue.
Best regards
Update 16.08.2016:
If I add a JTexPane over the Netbeans Palette into the Designer, it works. Only the initialisation in the constructor fails.

It may not be possible to use Swing for this task without crashing. Instead, use the com.sun.star.awt module. Complete examples are at http://api.libreoffice.org/examples/DevelopersGuide/examples.html#GraphicalUserInterfaces.
For more information, see Creating Dialogs at Runtime.
One more link: This example does use Swing. Try it to see if the same problem occurs.

My dirty solution is to initialize the JTextPane twice within a try-catch. Because on the second call i don't get an exception.

Related

(java.lang.IllegalArgumentException) Error with gui

I am making a simple gui program in java. When i click run it gives me an error that looks like this:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: adding a window to a container
at java.awt.Container.checkNotAWindow(Unknown Source)
at java.awt.Container.addImpl(Unknown Source)
at javax.swing.JLayeredPane.addImpl(Unknown Source)
at java.awt.Container.add(Unknown Source)
at javax.swing.JRootPane.setContentPane(Unknown Source)
at javax.swing.JFrame.setContentPane(Unknown Source)
at main.cool(main.java:31)
at main$1.run(main.java:43)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.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)
and here is my code:
import javax.swing.*;
import java.awt.Container;
import java.awt.event.*;
public class main extends JFrame implements ActionListener {
protected JButton click, fun;
public main()
{
click = new JButton("Click");
click.setActionCommand("click");
click.addActionListener(this);
add(click);
click.setSize(16, 16);
fun = new JButton("wow");
fun.setActionCommand("wow");
fun.addActionListener(this);
add(fun);
}
public static void cool()
{
JFrame frame = new JFrame("TEST!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main main = new main();
frame.setContentPane(main);
frame.setSize(128, 128);
frame.setVisible(true);
frame.setResizable(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run()
{
cool();
}
});
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if("click".equals(e.getActionCommand()))
{
System.out.println("oh right");
} else if ("wow".equals(e.getActionCommand()))
{
System.out.println("hi");
}
}
}
I believe the bug may be in the cool() method; with the setContentPane line. but not sure. Can anyone please help me.
Yes; the bug is triggered in the frame.setContentPanel() in your cool() method in your main class. Your main class should extend JPanel instead of extend JFrame.
Aside: avoid declaring local variables which match class names; and, avoid declaring class names which are the same as standard method names...so, rename your main class as Main (if you must, but try to be more descriptive...perhaps Application), and make your local variable name something other than main...perhaps m or application.
Your class main extends JFrame instead of JPanel, so you are calling frame.setContentPane() on another JFrame, and it doesn't make sense to have a JFrame inside a JFrame. Change the superclass to JPanel and the error will go away

Why do I need to reset setText() in a JLabel to prevent errors?

As a follow-up to this question that I posted earlier, I am wondering about the cause of the issue I had.
The problem was that I was getting this error when updating a JLabel with a lot of HTML text.
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.html.StyleSheet$ListPainter.paint(Unknown Source)
at javax.swing.text.html.ListView.paintChild(Unknown Source)
at javax.swing.text.BoxView.paint(Unknown Source)
at javax.swing.text.html.BlockView.paint(Unknown Source)
at javax.swing.text.html.ListView.paint(Unknown Source)
at javax.swing.text.BoxView.paintChild(Unknown Source)
at javax.swing.text.BoxView.paint(Unknown Source)
at javax.swing.text.html.BlockView.paint(Unknown Source)
at javax.swing.text.BoxView.paintChild(Unknown Source)
at javax.swing.text.BoxView.paint(Unknown Source)
at javax.swing.text.html.BlockView.paint(Unknown Source)
at javax.swing.text.BoxView.paintChild(Unknown Source)
at javax.swing.text.BoxView.paint(Unknown Source)
at javax.swing.text.html.BlockView.paint(Unknown Source)
at javax.swing.plaf.basic.BasicHTML$Renderer.paint(Unknown Source)
at javax.swing.plaf.basic.BasicLabelUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1200(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.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)
The HTML that's being set is generated by a StringBuilder and the converted .toString. Something like this, but more extensive:
public static String entityOverviewHTML() {
StringBuilder sb = new StringBuilder();
List<Entity> entities = Entity.getEntities();
sb.append("<html><div style='padding: 12px;'>");
sb.append("<h1>People: alive</h1>");
// A lot of appending: also loop through getEntities (dynamic, can change)
// and get contents from each entity in #getEntityInfo below
if (entities.size() > 0) {
sb.append("<ul>");
for (Entity e: entities) {
getEntityInfo(e);
}
sb.append("</ul>");
}
sb.append("</div></html>");
return sb.toString();
}
private static StringBuilder getEntityInfo(Entity e) {
StringBuilder sbInfo = new StringBuilder();
// A lot of appending: append info of Entity e such as e.getFirstName()
sbInfo.append("<li>");
sbInfo.append(e.getFirstName())
sbInfo.append("</li>");
return sbInfo;
}
After some events, the HTML will change after which I call a custom refresh method:
public static void bringToFront() {
getInstance().setVisible(true);
getInstance().setExtendedState(JFrame.ICONIFIED);
getInstance().setExtendedState(JFrame.NORMAL);
}
public static void refresh() {
// text is a JLabel
text.setText(entityOverviewHTML());
bringToFront();
}
And it's then that the errors at the top of this post happen, however not always! I haven't figured out why this happens, but I did find that when resetting the text to an empty string and then calling entityOverviewHTML solves the issue.
public static void refresh() {
text.setText(""); // Here we go
text.setText(entityOverviewHTML());
bringToFront();
}
text is defined as a Class variable:
private static JLabel text = new JLabel();
What I like to know is: why? How can this single line of seemingly obsolete code solve the problem? Exactly what is the problem?
The problem is that your refresh() method is not called on the Swing EDT.
Swing is not threadsafe (https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) which means that the call text.setText(entityOverviewHTML()); corrupts the internal data structures that your JLabel instance uses to display the text.
Your refresh-method needs to be rewritten like this:
public static void refresh() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
text.setText(entityOverviewHTML());
bringToFront();
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
Usually when JLabel is instantiated, it has no width , if it is instantiated with empty text width is zero. When JLabel text is updated it won't show up as its size is not set properly.
Use preferred size: text.setPreferredSize(new Dimension(x, y)); then text.setText(html)

Threads stopping, suspending, and resuming

I'm writing a code that involves JFrame, and a thread.
The thread should take the text from a text field and write it into text area.
I have 4 buttons as follows:
"Start" to start the thread.
"Stop" which stops the thread.
"Pause" which pause and continues the thread.
and "Exit" which stops the thread and exits the program.
I've created the thread and implemented "run()" function in frame's constructor, here it is:
WritingThread = new Thread(new Runnable() {
#Override
public void run() {
String s = WrittenText.getText();
while(true)
{
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < s.length(); j++)
{
WritingArea.append("" + s.charAt(j));
try {
Thread.sleep((int)ThreadSpeedSpinner.getValue());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
WritingArea.append("\n");
}
WritingArea.setText("");
}
}
});
and these are the buttons:
JButton btnStart = new JButton("Start");
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(!WritingThread.isAlive())
WritingThread.start();
}
});
JButton btnStop = new JButton("Stop");
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(WritingThread.isAlive())
WritingThread.stop();
}
});
btnPause = new JButton("Pause");
btnPause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(!isPaused)
{
if(WritingThread.isAlive())
{
WritingThread.suspend();
btnPause.setText("Continue");
isPaused = true;
}
}
else
{
WritingThread.resume();
btnPause.setText("Pause");
}
}
});
JButton btnExit = new JButton("Exit");
btnExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
WritingThread.stop();
System.exit(0);
}
});
I have two problems showing up:
When I use stop(), suspend(), or resume(), I get a warning says "The method from the type Thread is deprecated".
When I run the program, I start the thread, then stop it, then try to start it I have this exception
Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at com.HomeWork.HomeWork5$6.actionPerformed(HomeWork5.java:140)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(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$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$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 don't want direct answers, I want to understand why I'm getting these errors, and if there any resources I should go through.
P.S. I searched for an answer a lot and didn't get anything explaining this problem.
Thanks
Threads acquire lock on objects. And the most important part of multithreading
is to safely interweave the threads, so that all the threads can use the resource (object).
If not dealt with correctly, it leads to deadlock.
When you use stop(), you are killing the thread. That thread is gone forever. It
may lead the objects, that stopped thread had acquired, in a inconsistent state.
suspend() is deprecated, because once the thread is suspended other threads won't get the
resource, since the suspended thread holds a lock on it.
The image below describes how threads should be correctly used.
Use sleep(), wait(), and notify() for interleaving the threads efficiently.

Java Display message issue

I have a java program that creates a JFrame like this:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
gui.setFrame(new gui(), 1000, 300);
}
});
I also have a class (gui.java) that implements setFrame:
public static void setFrame(final JFrame frame, final int width, final int height) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f1=frame;
frame.setTitle("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
});
}
If the user tries to click Submit (a button I created) and the fields in the JFrame are not filled in then it throws an error. The code for the error message is:
submit.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {
//check to make sure all values filled in
if(chooser.getSelectedFile().toString()!=null&&saveChooser.getSelectedFile().toString()!=null)
parseFile.readFile(chooser.getSelectedFile(),saveChooser.getSelectedFile(),startSpanText.getText(),(String)col2.getSelectedItem(),(String)col3.getSelectedItem(),(String)col4.getSelectedItem(),(String)col5.getSelectedItem(),(String)col6.getSelectedItem());
else
JOptionPane.showMessageDialog(f1,"Bad");
}
});
//Note: f1 is a static version of the frame I initially received
The error I get is:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at gui$3.mouseReleased(gui.java:133)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(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$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$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)
What did I do wrong?
One of the variables is null. It could be:
chooser
chooser.getSelectedFile()
saveChooser
saveChooser.getSelectedFile()
parseFile
startSpanText
col2 to col6
Use the line number in the stack trace, and a debugger or traces in the code to know which one. My guess would be one of the selected files, since it makes no sense to call
chooser.getSelectedFile().toString() != null
Either there is no selected file, and it throws an NPE because getSelectedFile() returns null, or there is one, and its toString() will never be null.
Also, you shouldn't use a mouse listener to do something when a button is pressed. That's what an ActionListener is for. It will be simpler, and also work when the user presses the button with its keyboard.
Your exception message should point you to the answer. One of the items you are using in your mouseReleased method is null:
#Override
public void mouseReleased(MouseEvent e) {
//check to make sure all values filled in
if(chooser.getSelectedFile().toString()!=null &&
saveChooser.getSelectedFile().toString()!=null)
parseFile.readFile(chooser.getSelectedFile(), saveChooser.getSelectedFile(),
startSpanText.getText(), (String)col2.getSelectedItem(),
(String)col3.getSelectedItem(), (String)col4.getSelectedItem(),
(String)col5.getSelectedItem(), (String)col6.getSelectedItem());
else
JOptionPane.showMessageDialog(f1,"Bad");
}
Use a debugger to inspect which variables are set. Use the line number in the exception message to help you.

Strange Swing Error when from calling RemoveAll() on subclass of JPanel

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?
Edit: By request, I'm posting additional code.
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));
}
}
}
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();
}
...
}
Which is called by my main class:
public static void main(String[] args)
{
GUI gui = new GUI();
gui.loadGrid(args[0]);
}
'Intermittent/occasional errors' in Swing apps. are often caused by updating the UI off the EDT. See Concurrency in Swing for more details.
Note that for better help sooner, post an SSCCE. If my suspicions above are the cause of the problem, then the problem is actually in code not shown.
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 is either the containing Window here, or null if no such Window exists.
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.
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]);
}});
}
Intermittent errors like this make me worry about calling Swing code off of the EDT, the Event Dispatch Thread, which is the main Swing thread and is responsible for Swing graphics and user interaction. Where and how are you calling the CellGUI#setValue(...) method? Could it be off of the EDT?
I don't see any reason to remove all the labels?
All you need to do us use setText(...) to change the text of the labels. No need to remove them all and then add them back.
Sometimes when you only intend a single thread, you get more and run into the updating from the wrong thread problem.
For me, it's happened when an application starts up and starts preparing a GUI.
Meanwhile, the mouse is sitting in the screen location where the GUI is going to be.
The GUI discovering the mouse is already in its space can happen asynchronously to the background work. Putting the mouse off in a corner of the screen makes the problem goes away.

Categories

Resources