2010-04-06 5 views
2

버튼에서 마우스를 누르고있는 동안 지정된 .actionPerformed를 호출하는 JButton 또는 AbstractButton의 하위 클래스를 생성하려고합니다.자바 스윙 보류 버튼

지금까지 JButton을 확장하고, 생성자 (생성자 내부)에 마우스 수신기를 추가하고 마우스가 작동하는 동안 actionPerformed를 호출 할 생각을했습니다. 지금까지 나는 그걸 생각해 냈습니다. 그러나 내가 올바른 방향에 있다면 놀라움을 금치 못했습니다. 만약 그렇다면, "고정 된"논리를 올바르게 구현하는 방법.

package components; 

import java.awt.event.ActionEvent; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 

import javax.swing.Action; 
import javax.swing.Icon; 
import javax.swing.JButton; 

public class HoldButton extends JButton { 

    private class HeldDownMouseListener implements MouseListener { 

     private boolean mouseIsHeldDown; 

     private HoldButton button; 

     private long millis; 

     public HeldDownMouseListener(HoldButton button, long millis) { 
      this.button = button; 
      this.millis = millis; 
     } 

     @Override 
     public void mouseClicked(MouseEvent arg0) { } 

     @Override 
     public void mouseEntered(MouseEvent arg0) { } 

     @Override 
     public void mouseExited(MouseEvent arg0) { } 

     @Override 
     public void mousePressed(MouseEvent arg0) { 
      mouseIsHeldDown = true; 
//   This should be run in a sub thread? 
//   while (mouseIsHeldDown) { 
//    button.fireActionPerformed(new ActionEvent(button, ActionEvent.ACTION_PERFORMED, "heldDown")); 
//    try { 
//     Thread.sleep(millis); 
//    } catch (InterruptedException e) { 
//     e.printStackTrace(); 
//     continue; 
//    } 
//   } 
     } 

     @Override 
     public void mouseReleased(MouseEvent arg0) { 
      mouseIsHeldDown = false; 
     } 

    } 

    public HoldButton() { 
     addHeldDownMouseListener(); 
    } 

    public HoldButton(Icon icon) { 
     super(icon); 
     addHeldDownMouseListener(); 
    } 

    public HoldButton(String text) { 
     super(text); 
     addHeldDownMouseListener(); 
    } 

    public HoldButton(Action a) { 
     super(a); 
     addHeldDownMouseListener(); 
    } 

    private void addHeldDownMouseListener() { 
     addMouseListener(new HeldDownMouseListener(this, 300)); 
    } 

} 

시간 내 주셔서 감사합니다.

편집 : 나는 작업을 구현 해낸 타이머 방법 선택 :

package components; 

import java.awt.event.ActionEvent; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.Timer; 
import java.util.TimerTask; 

import javax.swing.Action; 
import javax.swing.Icon; 
import javax.swing.JButton; 

public class HoldButton extends JButton { 

    private static final long serialVersionUID = 1L; 

    public static final long CLICK_LAG = 300; 

    public static final long INITIAL_FIRE_DELAY = 500; 

    public static final double FIRE_DELAY_STEP_MULTIPLIER = 25; 

    public static final long MIN_FIRE_DELAY = 100; 

    private class HeldDownMouseListener implements MouseListener { 

     private class HeldDownCheckerTask extends TimerTask { 

      private HeldDownMouseListener listener; 

      public HeldDownCheckerTask(HeldDownMouseListener listener) { 
       this.listener = listener; 
      } 

      @Override 
      public void run() { 
       long delay = INITIAL_FIRE_DELAY; 

       while (listener.isMouseHeldDownOnButton()) { 
        listener.fireMouseHeldDown(); 

        try { 
         Thread.sleep(delay); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 

        if (delay > MIN_FIRE_DELAY) { 
         final long decrease = Math.round(FIRE_DELAY_STEP_MULTIPLIER * Math.pow(INITIAL_FIRE_DELAY/delay, 2)); 
         delay = Math.max(delay - decrease, MIN_FIRE_DELAY); 
        } 
       } 
      } 

     } 

     private boolean mouseIsHeldDown; 

     private boolean mouseIsOnButton; 

     private HoldButton button; 

     private Timer timer; 

     public HeldDownMouseListener(HoldButton button) { 
      this.button = button; 
     } 

     public boolean isMouseHeldDownOnButton() { 
      return mouseIsHeldDown && mouseIsOnButton; 
     } 

     private void cancelTimer() { 
      if (timer != null) { 
       timer.cancel(); 
       timer = null; 
      } 
     } 

     private void fireMouseHeldDown() { 
      button.fireActionPerformed(new ActionEvent(button, ActionEvent.ACTION_PERFORMED, "heldDown")); 
     } 

     @Override 
     public void mouseClicked(MouseEvent arg0) { 
      cancelTimer(); 
     } 

     @Override 
     public void mouseEntered(MouseEvent arg0) { 
      mouseIsOnButton = true; 
     } 

     @Override 
     public void mouseExited(MouseEvent arg0) { 
      mouseIsOnButton = false; 
     } 

     @Override 
     public void mousePressed(MouseEvent arg0) { 
      cancelTimer(); 
      mouseIsHeldDown = true; 
      timer = new Timer(); 
      timer.schedule(new HeldDownCheckerTask(this), CLICK_LAG); 
     } 

     @Override 
     public void mouseReleased(MouseEvent arg0) { 
      mouseIsHeldDown = false; 
     } 

    } 

    public HoldButton() { 
     addHeldDownMouseListener(); 
    } 

    public HoldButton(Icon icon) { 
     super(icon); 
     addHeldDownMouseListener(); 
    } 

    public HoldButton(String text) { 
     super(text); 
     addHeldDownMouseListener(); 
    } 

    public HoldButton(Action a) { 
     super(a); 
     addHeldDownMouseListener(); 
    } 

    private void addHeldDownMouseListener() { 
     addMouseListener(new HeldDownMouseListener(this)); 
    } 

} 
+1

그럼 java.util.Timer 대신 javax.swing.Timer를 사용해야한다고 생각합니다. 그리고 당신은 반복적 인 시간으로 설정해야합니다 (그래서 당신은 자기 자신을 sleep()이라고 부를 필요가 없습니다). javax.swing.Timer의 장점은 일반적으로 Event Dispatch Thread 내에서 작업을 실행한다는 것입니다. 이는 일반적으로 모든 Swing EventListener에 대한 호출에 필요합니다. actionPerformed()가 GUI 구성 요소를 액세스하거나 변경하면 현재 구현에서 actionPerformed _ outside_EDT를 호출합니다. – jfpoilpret

답변

1

마우스 버튼을 할 때까지 당신이 필요로하는 간격으로 반복적으로 액션을 호출하는 타이머를 시작할 수 누르면 가기. 그런 다음 타이머를 중지 할 수 있습니다. 타이머에 제출함으로써 새로운 스레드에 제출하고 스레드 관리를 직접 수행 할 수 없습니다.

1

적어도 하나의 좋은 습관은 '작업'을 수행하는 것입니다.이 경우 SwingUtilies.invokeLater()를 통해 실행 가능 영역에서 actionPerformed-loop를 수행하십시오. 그런 식으로 이벤트 threadpool/queue에 오프로드되고 awt 메인 스레드를 차단하지 않으므로 GUI를 차단하지 않습니다.