Java Timer synchronize with GUI - java

I'm trying to do an incremental display of a Component because it takes too much time to make all the calculations. So i don't want to freeze the graphic interface i'd like to display my image ( a fractal ) every 2.3 seconds. The function which calculate all the points is compute. Before i want to make the incremental display this method was calculating all points. Now it only calculates 10000 points.
class FlameBuilderPreviewComponent:
Timer timer1=new Timer(1000,new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
time=time+10000;
fa= builder.build().compute(density,frame,getWidth(),getHeight(),accumulator);
}
});
timer1.start();
for (int z = 0; z <fa.height(); z++) {
for (int j = 0; j < fa.width(); j++) {
image.setRGB(j,z,fa.color(palette, background, j, fa.height()-1-z).asPackedRGB());
}
}
g0.drawImage(image,0,0,null);
if (time>density*getWidth()*getHeight()){
timer1.stop();
}
Then the other part of the program is the GUI interface, i put another timer this one is responsible of repainting the image.
class FlameMakerGUI :
fBPC=new FlameBuilderPreviewComponent(builder, background, palette, r1, density);
Timer timer = new Timer(2500,new ActionListener(){
public void actionPerformed(ActionEvent e) {
fBPC.repaint();
System.out.println("titi");
}
});
timer.start();
fractale.add(fBPC,BorderLayout.CENTER);
Then this is the error that the program show each time timer is executed:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at ch.epfl.flamemaker.gui.FlameBuilderPreviewComponent.paintComponent(FlameBuilderPreviewComponent.java:82)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1512)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1443)
at javax.swing.RepaintManager.paint(RepaintManager.java:1236)
at javax.swing.JComponent._paintImmediately(JComponent.java:5169)
at javax.swing.JComponent.paintImmediately(JComponent.java:4980)
at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
at javax.swing.RepaintManager$3.run(RepaintManager.java:784)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:784)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:757)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:706)
at javax.swing.RepaintManager.access$1000(RepaintManager.java:62)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1651)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:688)
at java.awt.EventQueue$3.run(EventQueue.java:686)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Thank you for helping

You are creating a action listener every second, that doesn't make any sense. You obviously do not understand how event listeners work or how the Timer class works.
Also, tasks on the EDT (event dispatch thread) must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive
You need to use Swing Worker in order to archive proper concurrency.
From the Oracle website:
Swing consists of three kinds of threads:
Initial threads, the threads that execute initial application code.
The event dispatch thread, where all event-handling code is executed. Most code that interacts with the Swing framework must also
execute on this thread.
Worker threads, also known as background threads, where time-consuming background tasks are executed.

Related

Java Swing Null Pointer Exception in Netbeans IDE

I'm still fairly new to Java and I've started on a simple GUI project with the netbeans java IDE 8.2 using swing and am running into a null pointer exception.
I've removed the majority of the code down to the bottom portion in order to try and find where the issue is coming from and I still get an exception running only these lines of code.
package finalmodel;
import javax.swing.*;
public class FinalModel extends JFrame {
public static void main (String[] args) {
new FinalModel();
}
public FinalModel () {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
The application runs fine, and as far as I can tell, the exception doesn't affect functionality (a window pops up and can be successfully closed from the above code), but the exception is thrown upon the window's closure.
The stack trace given to me by the IDE is
java.lang.NullPointerException: peer
at sun.awt.windows.WInputMethod.openCandidateWindow(Native Method)
at sun.awt.windows.WInputMethod.access$400(WInputMethod.java:45)
at sun.awt.windows.WInputMethod$1.run(WInputMethod.java:602)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
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:733)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159) [catch]
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
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)
Version Info
your example is very minimal. it might be missing some properties. give this a try:
package finalmodel;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class FinalModel extends JFrame {
public FinalModel () {
setTitle("setTitle()");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
FinalModel fm = new FinalModel ();
fm.setVisible(true);
}
}
here's a good article on jframe, for practice jframes
Netbeans bug! Reinstall Netbeans with un updated version or something like that.

NullPointerException while fast updating TextField

I'm working on an app, that searches some files in the directed folder and prints them in TableView<myFile> foundFilesList, that is stored in the Main class. myFile just extends File a bit. The searching is done using service in background thread, that puts found data to ObservableList<myFile> filesOfUser.
I want to display current amount of find files in TextField foundFilesAmount in the same view, where TableView with files is located -- ResultsView
To do that, I added a ListChangeListener for foundFilesList to ResultsView controller, that uses method setText to print current size of filesOfUser. It looks like:
Main.filesOfUser.addListener(new ListChangeListener<myFile>() {
#Override
public void onChanged(Change<? extends myFile> c) {
while (c.next()){
if (c.wasAdded())
setCounter(c.getAddedSize());
}
}
});
void setCounter (int number) contains only
int currValue = Integer.valueOf(foundFilesAmount.getText());
foundFilesAmount.setText(String.valueOf(currValue + number));
And now what the problem is. Textfield with current amount of find files is updated very fast, and from one moment it stops doing it. In the console I see lots of repeated NullPointerException's from JavaFX Application Thread. Its' contents:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.javafx.text.PrismTextLayout.getRuns(PrismTextLayout.java:236)
at javafx.scene.text.Text.getRuns(Text.java:317)
at javafx.scene.text.Text.updatePGText(Text.java:1465)
at javafx.scene.text.Text.impl_updatePeer(Text.java:1500)
at javafx.scene.Node.impl_syncPeer(Node.java:503)
at javafx.scene.Scene$ScenePulseListener.synchronizeSceneNodes(Scene.java:2290)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2419)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
I tried to set sort of delay before using setText, like updating value in foundFilesAmount only after 5'th, 10'th, 15'th update, etc. But if the search works longer, exceptions are still thrown.
Is there a correct method to show current amount of found files, that contains real amount and doesn't cause so much exceptions?
Thanks in advance.
The correct way is not doing the updates of the UI on a thread other than the application thread. This can otherwise lead to issues with rendering/layouting.
You could use a Task to do the updates to the updates however:
Task<ObservableList<myFile>> task = new Task<
Task<ObservableList<myFile>>() {
#Override
protected ObservableList<myFile> call() throws Exception {
ObservableList<myFile> files = FXCollections.observableArrayList();
while (...) {
...
files.add(...);
updateMessage(Integer.toString(files.size()));
...
}
return files;
}
};
task.setOnSucceeded(evt -> tableView.setItems(task.getValue()));
Thread t = new Thread(task);
textField.textProperty().bind(task.messageProperty());
t.setDaemon(true);
t.start();
try something like this:
Platform.runLater(new Runnable() {
#Override
public void run() {
// update your JavaFX controls here
}
});

ConcurrentModificationException but not removing anything from ArrayList

So I'm making a game and every 5 seconds there must spawn an enemy, know when I run my application it throws an exception 'ConcurrentModificationException'.
This is a part of my code:
private void tick() {
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
enemyY = enemyYRand.nextInt(6);
enemy.add(new Enemy(enemyY, 10, enemyImg));
}
}, 0, 5, TimeUnit.SECONDS);
if (player.y > getHeight() - playerImg.getHeight(null)) {
player.setY(-10);
}
if (player.y < 0) {
player.setY(+10);
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(Enemy enemys : enemy) {
enemys.render(g);
}
player.render(g);
}
First the tick method get's called then paintComponent method.
This is the output:
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at _47b3n.spaceinvaders.framework.Main.paintComponent(Main.java:141)
at javax.swing.JComponent.paint(JComponent.java:1053)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5223)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290)
at javax.swing.RepaintManager.paint(RepaintManager.java:1265)
at javax.swing.JComponent._paintImmediately(JComponent.java:5171)
at javax.swing.JComponent.paintImmediately(JComponent.java:4982)
at javax.swing.RepaintManager$4.run(RepaintManager.java:824)
at javax.swing.RepaintManager$4.run(RepaintManager.java:807)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:807)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:782)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:731)
at javax.swing.RepaintManager.access$1300(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1720)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
at java.awt.EventQueue.access$400(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.awt.EventQueue$3.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
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)
It appears that you have 2 threads each operating on an ArrayList at the same time.
One of them is in the event dispatch thread, where paintComponent is called. You are using an enhanced for loop, which uses an Iterator internally. This iterator is what is throwing the ConcurrentModificationException.
You are modifying the ArrayList in the tick method, in some other thread, when you call enemy.add(new Enemy(enemyY, 10, enemyImg));.
The Iterator noticed that the ArrayList was modified and threw the exception. When you are displaying the enemies, it is necessary to have a consistent view of your ArrayList.
Synchronize access to this ArrayList on some object (maybe even enemy itself) by enclosing read and write operations on this ArrayList in synchronized blocks. That means that only one of these blocks can be executing at the same time.
synchronized (enemy) {
enemy.add(new Enemy(enemyY, 10, enemyImg));
}
and
synchronized (enemy) {
for(Enemy enemys : enemy) {
enemys.render(g);
}
}

Java: Removing Runnable Canvas Component

I have been working on this game for a while now, which actually has different game modes built into it. At first, I have been handling the execution by just exiting the program after the user has lost, or wants to exit. Since not only is it annoying to have to re-open the program, and when users don't understand why it closed, I have a reason to after losing or wanting to exit, that they return to the main menu.
The problem that appears at this time is that I am using swing in the main part of my design of the game. This not only includes the main menu, but other menus, and even in part with the game. Swing is being used is for the interactivity of buttons and other primary features. So now that I am switching to returning to the main menu and everything, I have been having to rewrite basically the whole base of rendering and switching between the windows.
Since I am rewriting the render method of the game, I decided to make a StateRenderer class. From this, it would handle and decide if it currently even needs to process. So within the run() method, I put a line of code that checks if it even needs to render at a state of a menu.
#Override
public void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = BILLION / UPDATE_RATE;
double delta = 0;
int updates = 0, frames = 0;
while (running) {
// right here I am checking the state for it
GameState state = CellDefender.getGameState();
if (state == GameState.MAIN_MENU || state == GameState.STORE_MENU || state == GameState.SETTINGS_MENU) continue;
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
update();
updates++;
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer >= 1000) {
while (System.currentTimeMillis() - timer >= 1000) // while idling it builds up much, and makes it less annoying when debugging
timer += 1000;
System.out.println("UPS: " + updates + ", FPS: " + frames);
updates = 0;
frames = 0;
}
}
stop();
}
Now, that works fine when I decide to switch from the main menu to an actual game mode, but if I were to lose on the mode, or want to exit to main, I get this nasty error, which I have no idea how I would ever fix it:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: component argument pData
at sun.java2d.windows.GDIWindowSurfaceData.initOps(Native Method)
at sun.java2d.windows.GDIWindowSurfaceData.<init>(Unknown Source)
at sun.java2d.windows.GDIWindowSurfaceData.createData(Unknown Source)
at sun.java2d.d3d.D3DScreenUpdateManager.getGdiSurface(Unknown Source)
at sun.java2d.d3d.D3DScreenUpdateManager.createGraphics(Unknown Source)
at sun.awt.windows.WComponentPeer.getGraphics(Unknown Source)
at java.awt.Component.getGraphics(Unknown Source)
at sun.awt.RepaintArea.paint(Unknown Source)
at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
at java.awt.Component.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)
The only part that I understand is I'm doing something completely wrong with AWT, which deals with things such as Graphics and Canvas. It would probably be a horrible idea to just engulf the error with a try..catch method, but then again I don't really know where it is caused.
To get into details about how I switch, here is from my main menu to an actual GameMode:
private void initListeners() {
btnRegular.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setGameState(GameState.REGULAR);
renderer.switchDisplay(RegularMode.class);
}
});
// more code is here, but useless for now
}
My renderer is my StateRenderer which is meant to be built to handle all rendering for the game, when you are actually on a screen that has the Canvas element, and is tracked by the GameState. Now I will show you what is thrown into the renderer.switchDisplay(Class class) method.
public void switchDisplay(Class<? extends GameMode> mode) {
if (mode == RegularMode.class) {
currentMode = new RegularMode(size);
setPreferredSize(size);
screen = new Screen(size.width, size.height);
panel.add(currentMode.getFunctionBar(), BorderLayout.NORTH);
panel.add(currentMode.getScoreBar(), BorderLayout.SOUTH);
// -- extra stuff that is similar --
} else return;
JFrame frame = CellDefender.getFrame();
frame.remove(CellDefender.getMainPanel());
panel.add(this, BorderLayout.CENTER);
frame.add(panel);
frame.validate();
frame.repaint();
frame.pack();
currentMode.initialize();
requestFocus();
}
This may be somewhat inefficient, but all of this seems to work seemingly fine. Now to dive into when everything is getting switched back to the main menu that throws all of the errors!
This is the code that is ran that is directly causing the error:
public static void switchDisplay() {
setGameState(GameState.MAIN_MENU); // Switched the game state, should stop looping.
frame.setContentPane(panel);
frame.validate();
frame.repaint();
frame.pack();
}
This, of course, gives me a complete feeling that the error lies somewhere in my StateRenderer class, and more specifically anything that relates into the run() method. The part that I have already handled the loop about the rendering.
Summary
So I am having a problem when switching from a panel with a Canvas component, that implements Runnable. In my code, I have handled the problem about it rendering when it doesn't have a visible Canvas, or when the GameState is not one that is for the game to render. However, when switching from a canvas that is currently being rendered and updated to a menu that isn't doing so causes a NullPointerException.
I would like to go ahead and thank anyone and everyone for your help, because this issue really has me stumped.
Edit(s)
With further testing that I always decide to do when I ask for help, I see the problem occurs in the CellDefender.switchDisplay() method at the line frame.validate(). I don't understand why this is causing the problem.
According to the discussion in the comments, the problem is most likely related to a violation of the Swing "Single Thread Rule":
Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.
The results of violating this rule may be arbitrarily odd, but NullPointerExceptions from deeply inside the Swing management infrastructure are among the more common ones.
In many cases, this issue can be resolved by a pragmatic pattern: Assume you have a method that modifies Swing components:
void modifySwingComponents()
{
someComponent.add(someOtherComponent);
someComponent.remove(somethingElse);
someTextComponent.setText("Text");
...
}
Then you can easily check whether the Single Thread Rule is violated by inserting something like
System.out.println(Thread.currentThread());
in this method. It should always print Thread[AWT-EventQueue-0,6,main] (or similar, indicating that the method is executed on the Event Dispatch Thread). Alternatively, you can directly query
System.out.println(SwingUtilities.isEventDispatchThread());
If the method is called from a Thread that is not the Event Dispatch Thread (EDT), you may "wrap" this method into a Runnable that you put on the event queue:
void modifySwingComponents()
{
if (SwingUtilities.isEventDispatchThread())
{
// We're on the right thread - direcly call the method
modifySwingComponentsOnEDT();
}
else
{
// Put the task to execute the method in the event queue,
// so that it will be executed on the EDT as soon as possible
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
modifySwingComponentsOnEDT();
}
});
}
}
// Always called on the EDT!
void modifySwingComponentsOnEDT()
{
someComponent.add(someOtherComponent);
someComponent.remove(somethingElse);
someTextComponent.setText("Text");
...
}
But NOTE that although this looks simple and may seem to easily resolve certain issues, it does NOT release you from the duty to diligently check and document which method is executed on which thread.

Event dispatching thread remove from List exception SWING

Hi I have this strange exception when trying to remove a element from list in JPanel which implements the State interface. Here is the code:
public static class ButtonListener implements ActionListener {
private State state;
public ButtonListener(State state) {
this.state = state;
}
#Override
public void actionPerformed(ActionEvent e) {
state.applyMove(state.getMoves().get(0));
}
}
And the JPanel where is the implementation of "applyMove" method:
public class RushHourBoard extends JPanel implements MouseListener, MouseMotionListener, State {
...
private List<Vehicle> vehicles;
...
#Override
public State applyMove(Move vehicleMove) {
VehicleMove move = (VehicleMove) vehicleMove;
Vehicle moved = move.getVehicle();
vehicles.remove(moved);
...
And the trace of the exception:
Exception in thread "AWT-EventQueue-0" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at entrery.rushhour.RushHourBoard.applyMove(RushHourBoard.java:174)
at entrery.rushhour.MyDragDemo$ButtonListener.actionPerformed(MyDragDemo.java:59)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Is this something with UI thread security policy ? Thanks in advances for your help.
The instance assigned to RushHourBoard.vehicles does not support removal. Perhaps it is from Arrays.asList or Collections.unmodifiableList.
List, like many in Java collections, is a poor interface. It's so unspecific many of the methods may not be implemented (usefully). Even with a loose contract, many of the collection implementations don't even conform to the minimal terms of the interfaces they implement.

Categories