Aggiornamento di JButton su un timer in un ciclo do-while

Sto avendo qualche problema a ottenere un JButton da aggiornare ripetutamente (usato con un timer) in un ciclo do-while. Sto lavorando a un gioco semplice, giocato su una griglia 10 * 10 di oggetti tile che corrispondono a una lista array JButton con 100 pulsanti.

Questa parte del programma gestisce un semplice path-finding (cioè se clicco su un personaggio, quindi su una tessera vuota, il personaggio si sposterà attraverso ogni tessera sulla sua strada verso la destinazione). C’è un ritardo tra ogni passaggio in modo che l’utente possa vedere i progressi del personaggio.

Nello stato attuale delle cose, il movimento è corretto, ma il JButton viene aggiornato solo quando il personaggio raggiunge la destinazione, non su passaggi intermedi.

public void move(int terrainTile) { int currentPosition = actorList.get(selectedActor).getPosition(); int movementValue = 0; int destination = terrainTile; int destinationX = destination / 10; int destinationY = destination % 10; do { currentPosition = actorList.get(selectedActor).getPosition(); // Gets PC's current position (before move) System.out.println("Old position is " + currentPosition); int currentX = currentPosition / 10; int currentY = currentPosition % 10; if(actorList.get(selectedActor).getCurrentAP() > 0) { movementValue = 0; if(destinationX > currentX) { movementValue += 10; } if(destinationX  currentY) { movementValue += 1; } if(destinationY < currentY) { movementValue -= 1; } int nextStep = currentPosition + movementValue; myGame.setActorIdInTile(currentPosition, -1); //Changes ActorId in PC current tile back to -1 scrubTiles(currentPosition); actorList.get(selectedActor).setPosition(nextStep); // Sets new position in actor object System.out.println("Actor " + selectedActor + " " + actorList.get(selectedActor).getName() + " position has been updated to " + nextStep); myGame.setActorIdInTile(nextStep, selectedActor); // Sets ActorId in moved to Tile System.out.println("Tile " + nextStep + " actorId has been updated to " + selectedActor); buttons.get(nextStep).setIcon(new ImageIcon(actorList.get(selectedActor).getImageName())); // If orthagonal move AP-4 if(movementValue == 10 || movementValue == -10 || movementValue == 1 || movementValue == -1) { actorList.get(selectedActor).reduceAP(4); } // If diagonal move AP-6 else { actorList.get(selectedActor).reduceAP(6); } System.out.println(actorList.get(selectedActor).getName() + " has " + actorList.get(selectedActor).getCurrentAP() + " AP remaining"); try { Thread.sleep(500); // one second } catch (Exception e){} buttons.get(nextStep).repaint(); } else { System.out.println(actorList.get(selectedActor).getName() + " has insufficient AP to move"); break; } }while(destination != (currentPosition + movementValue)); 

Quello che ho provato:

  1. buttons.get (NeXTSTEP) .repaint (); (Ho provato a inserire un comando per ridisegnare il pulsante dopo aver impostato imageIcon. Nessuna modifica.

  2. buttons.get (NeXTSTEP) .revalidate (); (Non è sicuro al 100% di ciò che fa – è venuto fuori come una soluzione potenziale, ma non funziona.

  3. Passaggi 1 e 2 combinati

  4. Guardato nella class del timer swing – il movimento non si verifica ogni volta che viene triggersto un actionEvent, (solo se il personaggio è selezionato e il riquadro di destinazione è vuoto) quindi non sono sicuro di come farlo funzionare

Qualsiasi aiuto sarebbe molto apprezzato!

Non so davvero esattamente cosa volevi sapere nei tuoi commenti, anche se +1 alla risposta sopra, mi sembra che sia la vera causa. Dai un’occhiata a questo programma di esempio, aggiungi semplicemente il tuo metodo call to the move(...) all’interno di timerAction , sembra che possa funzionare per te. Qui prova questo codice:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GridExample { private static final int SIZE = 36; private JButton[] buttons; private int presentPos; private int desiredPos; private Timer timer; private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon"); private ActionListener timerAction = new ActionListener() { public void actionPerformsd(ActionEvent ae) { buttons[presentPos].setIcon(null); if (desiredPos < presentPos) { presentPos--; buttons[presentPos].setIcon(infoIcon); } else if (desiredPos > presentPos) { presentPos++; buttons[presentPos].setIcon(infoIcon); } else if (desiredPos == presentPos) { timer.stop(); buttons[presentPos].setIcon(infoIcon); } } }; public GridExample() { buttons = new JButton[SIZE]; presentPos = 0; desiredPos = 0; } private void createAndDisplayGUI() { JFrame frame = new JFrame("Grid Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel contentPane = new JPanel(); contentPane.setLayout(new GridLayout(6, 6, 5, 5)); for (int i = 0; i < SIZE; i++) { final int counter = i; buttons[i] = new JButton(); buttons[i].setActionCommand("" + i); buttons[i].addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { desiredPos = Integer.parseInt( (String) buttons[counter].getActionCommand()); timer.start(); } }); contentPane.add(buttons[i]); } buttons[presentPos].setIcon(infoIcon); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); timer = new Timer(1000, timerAction); } public static void main(String... args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new GridExample().createAndDisplayGUI(); } }); } } 

Questo perché stai facendo do {} mentre sei nel thread dell’interfaccia utente. Per risolvere questo, dovresti usare SwingWorker o javax.swing.Timer