2009-11-25 3 views
1
워드 2007에서 줌 슬라이더를 모방

내가 (이미 존재하는 구성 요소 또는 찾기) 모방하려고 해요 :모방 줌 바 (JSlider에 수정 된)

Two state zoom bar http://i49.tinypic.com/iyk65l.png

주요 두 있습니다을 이 구성 요소와 표준 자바 JSlider에 차이 : 당신이 마우스를 놓을 때보다는 줄을 슬라이딩하는 동안

  1. 이 100 %를 제외하고 진드기에 스냅 및 스냅하지 않습니다
  2. 슬라이더는 아니다 슬라이더의 왼쪽 절반은 10 %에서 100 %로 이동합니다. 오른쪽은 100 %에서 500 %로 이동합니다. Java clone http://i45.tinypic.com/2i8dms9.png

    출처 : 여기에

는 내가 지금까지 무엇을 가지고

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

/** 
* 
* @author NDUNN 
* @date Nov 25, 2009 
*/ 
public class ZoomBar extends JPanel implements ActionListener, ChangeListener { 

    private JLabel zoomAmount; 
    private JButton minus; 
    private JButton plus; 
    private JSlider slider; 

    private static final int MIN_ZOOM = 10; 
    private static final int MAX_ZOOM = 200; 
    private static final int DEFAULT_ZOOM = 100; 

    private static final int MAJOR_ZOOM_SPACING = 50; 
    private static final int MINOR_ZOOM_SPACING = 10; 

    public ZoomBar() { 
     super(); 

     minus = new JButton("-"); 
     plus = new JButton("+"); 
     slider = new JSlider(MIN_ZOOM, MAX_ZOOM, DEFAULT_ZOOM); 

     slider.setMinorTickSpacing(MINOR_ZOOM_SPACING); 
     slider.setMajorTickSpacing(MAJOR_ZOOM_SPACING); 
     slider.setPaintTicks(true); 
     slider.setSnapToTicks(true); 

     zoomAmount = new JLabel(slider.getValue() + "%"); 

     add(zoomAmount); 
     add(minus); 
     add(slider); 
     add(plus); 

     plus.addActionListener(this); 
     minus.addActionListener(this); 

     slider.addChangeListener(this); 
    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("Zoom bar clone"); 
     frame.setContentPane(new ZoomBar()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public void actionPerformed(ActionEvent e) { 
     if (e.getSource() == plus) { 
      slider.setValue(slider.getValue() + MINOR_ZOOM_SPACING); 
     } 
     else if (e.getSource() == minus) { 
      slider.setValue(slider.getValue() - MINOR_ZOOM_SPACING); 
     } 
    } 

    public void stateChanged(ChangeEvent e) { 
     if (slider.getValueIsAdjusting()) { 
      return; 
     } 
     zoomAmount.setText(slider.getValue() + "%"); 
    } 

} 

는 기본적으로 단지 모양을 흉내 낸 있지만를 위에서 언급 한 두 가지 기능없이. JSlider API에이 동작을 허용하는 항목이 없습니다. 이 문제를 해결하기 위해 처음부터 다시 시작해야합니까? 그렇다면 내 시간에는 가치가 없지만,이 행동을 취하는 좋은 방법을 아는 사람이라면, 내가 작업하고있는 프로젝트에 참여하는 것이 좋을 것 같습니다.

감사합니다,


편집 : 단지 다른 값으로 0..50 및 50..100 매핑에 대한 아이디어 PSpeed에

감사합니다. 그렇게하는 코드는 아래와 같습니다.

불행히도 setValue를 snap으로 변경하는 것에 대한 아이디어가 작동하지 않았습니다.

public void stateChanged(ChangeEvent e) { 
    // While slider is moving, snap it to midpoint 
    int value = slider.getValue(); 
    if (slider.getValueIsAdjusting()) { 
     return; 
    } 

    zoomValue = fromSlider(value); 
    zoomLabel.setText(zoomValue + "%"); 
} 

public int fromSlider(int sliderValue) { 
    int mappedValue = 0; 
    if (sliderValue <= 50) { 
     // Map from [0, 50] to [MIN ... DEFAULT] 
     mappedValue = (int) map(sliderValue, 0, 50, MIN_ZOOM, DEFAULT_ZOOM); 
    } 
    else { 
     // Convert from (50, 100] to (DEFAULT ... MAX] 
     mappedValue = (int) map(sliderValue, 50, 100, DEFAULT_ZOOM, MAX_ZOOM); 
    } 
    return mappedValue; 
} 

public int toSlider(int modelValue) { 
    int mappedValue = 0; 
    if (modelValue <= DEFAULT_ZOOM) { 
     // Map from [MIN_ZOOM, DEFAULT_ZOOM] to [0 ... 50] 
     mappedValue = (int) map(modelValue, MIN_ZOOM, DEFAULT_ZOOM, 0, 50); 
    } 
    else { 
     // Convert from (DEFAULT ... MAX] to (50, 100] 
     mappedValue = (int) map(modelValue, DEFAULT_ZOOM, MAX_ZOOM, 50, 100); 
    } 
    return mappedValue; 
} 


/** 
* @param value The incoming value to be converted 
* @param low1 Lower bound of the value's current range 
* @param high1 Upper bound of the value's current range 
* @param low2 Lower bound of the value's target range 
* @param high2 Upper bound of the value's target range 
* @return 
*/ 
public static final double map(double value, double low1, double high1, double low2, double high2) { 

    double diff = value - low1; 
    double proportion = diff/(high1 - low1); 

    return lerp(low2, high2, proportion); 
} 

public static final double lerp(double value1, double value2, double amt) { 
    return ((value2 - value1) * amt) + value1; 
} 

편집 2 : 또 다른 차이가 나는주의 사항 JButton의 사무실에서 +/- 버튼이 할 반면에 당신이 발사 버튼을 여러 번을 누르고하지 않는다는 것입니다. 이 아이디어를 어떻게 모방합니까?

+0

스냅을 어디에서 했습니까? 아이디어는 사용자 정의 경계 범위 모델에서 수행하는 것이 었습니다. 이론은 JSlider가 47을 말하려고 시도하지만 모델이 듣지 않고 자체 값을 50으로 설정한다는 것입니다.하지만 여전히 변경 이벤트를 발생시켜야합니다. 그렇게하면 JSlider는 엄지 손가락의 적절한 위치를 알 수 있습니다. 사용자가 여전히 드래그하고 있기 때문에 마우스는 여전히 '47'위치에 있어야하며 마우스가 조금 더 왼쪽으로 움직이면 마우스가 스냅됩니다.실제로 일어난 일을 설명하면 다른 것을 생각할 수 있습니다. – PSpeed

+0

re : 편집 2, 커스텀 ButtonModel이 그것을 처리 할 수 ​​있어야합니다 ... 스윙은 이미 스피너에서 사용하고 있지만 노출되어 있지는 않습니다. 실제로 그들은 액션 리스너에서 복잡한 트릭을하는 것처럼 보입니다. 나는 여전히 사용자 정의 버튼 모델이 가장 먼저 쉬울 것이라고 생각합니다. setPressed (true)는 수행 된 액션을 발생시키는 타이머를 시작하고 setPressed (false)는 타이머를 중지시킵니다. 기분을 좋게하기 위해 초기 지연을 추가하십시오. – PSpeed

+0

BoundedRangeModel 및 JSlider 자체에서 시도했다. http://pastebin.com/f10ddb17f 값은 확실히 랩핑입니다 (나는 또한 업데이트 중입니다). 그러나 문제는 엄지 손가락의 위치가 마우스 커서의 위치에 단단히 묶여 있다는 것입니다. – I82Much

답변

2

사용자 정의 BoundedRangeModel을 사용하여 이러한 모든 동작을 얻을 수 있다고 생각합니다. 핵심은 모델 보고서를 일반적인 범위의 값으로 만들지 만 확대/축소 비율을 원할 때는 다르게 처리하는 것입니다.

예를 들어 범위를 0-100으로 설정하면 한 방향으로 0-50, 다른 방향으로는 50-100을 각각 처리 할 수 ​​있습니다 (각각 10-100 % 및 100-500 %).

스냅 동작을 얻으려면 setValue()를 재정 의하여 원하는 범위를 스냅 할 수 있습니다. 따라서 0-100을 값 범위로 사용하면 setValue()가 47-53으로 호출되면 값을 50으로 스냅합니다.