2014-05-23 2 views
0

나는 만들고있는이 게임에 대해 내 JButton 깜박임을 빨간색으로 만들려고합니다. 본 웹 사이트의 모든 솔루션은 스레드를 사용하여 잠을 넣어 또는 타이머를 사용하는 것이 좋습니다 그러나, 일시 정지 약화시켜 준다는 색상 변경 여기자바 스윙 JButton 시간 지연 (깜박임)

후 올 것 같다 나의 코드입니다 경우

Color cb = board[Y1][X1].getBackground(); 
board[Y1][X1].setBackground(Color.RED); 
//Pause 
board[Y1][X1].setBackground(cb); 

I 스레드를 넣고 3 행에서 잠자기 상태로두고 4 행에서 주석 처리하면 JButton이 빨간색으로 변하기 전에 일시 정지가 발생합니다. (노트 보드는 JButton의 2D 배열 일뿐입니다.)

+2

스택 오버플로에 오신 것을 환영합니다! 귀하의 문제를 보여주는 실제 실행 가능한 예제 (https://stackoverflow.com/help/mcve)는 덜 추측적인 작업과 더 나은 응답을 포함합니다. – MadProgrammer

+0

나는 실제 코드가 쓸모가 없기 전에 누군가가 비슷한 문제에 부딪 쳤음에 틀림 없다고 생각했습니다. 그것은 자바 문제가 더 있습니다. JButton -> Red 일시 중지 JButton -> 검정색 – user3667398

+0

놀랄 것입니다. – MadProgrammer

답변

4

이 문제가 발생하는 이유는 여러 가지가있을 수 있으며 동일하게 고정 될 수있는 여러 가지 이유가 있습니다.

설명에 따르면 이벤트 발송 스레드 외부에서 UI를 업데이트하려고하는 것 같습니다.

스윙은 단일 스레드 환경이며 스레드로부터 안전하지도 않습니다. 기본적으로 이것은 UI에 대한 모든 상호 작용/변경이 EDT의 맥락에서 수행 될 것이라는 기대가 있습니다. 이 규칙을 지키지 않으면 모든 종류의 이상하고 멋진 행동으로 이어질 수 있습니다.

가장 간단한 해결책은

Flashy

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class FlashyButton { 

    public static void main(String[] args) { 
     new FlashyButton(); 
    } 

    public FlashyButton() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private JButton button; 
     private Color[] colors = new Color[]{Color.RED, Color.YELLOW}; 

     public TestPane() { 
      button = new JButton("Flash Gorden"); 
      button.setContentAreaFilled(false); 
      button.setBorderPainted(false); 
      button.setFocusPainted(false); 
      button.setOpaque(true); 
      button.setBackground(Color.YELLOW); 
      setLayout(new GridBagLayout()); 
      add(button); 

      Timer timer = new Timer(500, new ActionListener() { 
       private int counter = 0; 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        counter++; 
        if (counter % 2 == 0) { 
         button.setBackground(colors[0]); 
        } else { 
         button.setBackground(colors[1]); 
        } 
       } 
      }); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.dispose(); 
     } 
    } 

} 

Concurrency in Swing에서보세요 당신은 예를 들어 EDT 내에서 실행이 보장되는 정규 시간 제한 이벤트를 예약 할 수있는하는 javax.swing.Timer을 사용하는 것입니다 자세한 내용은 How to Use Swing Timers을 참조하십시오.

더 복잡한 솔루션을 사용하면 Thread을 사용할 수 있습니다,하지만 당신은 UI를 업데이트하는 데 사용할 것이다하는 Runnable 인터페이스를 실행하는 것 EDT 위에 이벤트를 배치 할 SwingUtilities.invokeLater를 사용하여 UI를 업데이트 할 필요 . 조심스럽게 업데이트 프로세스를 제어하지 않는 한 실제 이벤트가 트리거되기 전에 호출 한 Thread이 옮겨져 일부 더티 업데이트가 발생할 수 있으므로 동기화 문제가 발생할 수 있습니다 ...

+0

이 솔루션은 내 특정 문제에 대해 작동하지 않습니다. 한 번 플래시하지 않고 계속 플래시해야합니다. 이와 같은 방법으로 나는 카운터를 boolean으로 바꾸고 if/else를 사용했다. 그러나 보드에서 이것을 사용하고 있기 때문에, 매우 빠르게 내려 간다. – user3667398

+1

그래서? 필요한 수의 깜박임 이후에 '타이머'를 멈추십시오. 당신은 또한 플래시 될 필요가있는 아이템의 하나의'Timer'와'List' 또는'Queue'를 사용할 수 있습니다. – MadProgrammer

+0

실행 가능한 예제를 보면, 정말 도움이됩니다 ... – MadProgrammer