2016-09-16 11 views
2

그래서 JavaFX에서 맵을 생성하고 있으며, 전체 맵을 때때로 볼 수있게하고 싶습니다. 그러나, 문제는 내가 imageView를 화면 크기에 맞게 설정 한 다음 scrollPane에 추가하면 줌 기능이 제대로 작동하지만 확대 된 후에는 이미지 주변을 회전 할 수 없다는 것입니다. 아래는 제가 작성한 코드입니다.scrollPane 내에서 사용되는 이미지의 JavaFX setFitHeight()/setFitWidth()는 패닝을 사용하지 않습니다.

package gameaspects; 

import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.control.ScrollPane.ScrollBarPolicy; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.input.ScrollEvent; 
import javafx.scene.layout.AnchorPane; 
import javafx.stage.Stage; 

public class SourceCodeVersion8 extends Application{ 

final double SCALE_DELTA = 1.1; 
public double SCALE_TOTAL = 1; 

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

@Override 
public void start(Stage primaryStage) throws Exception { 
    AnchorPane mapAnchorO = addMapAnchor(); 
    Scene mapScene = new Scene(mapAnchorO); 
    primaryStage.setScene(mapScene); 
    primaryStage.setFullScreen(true); 
    primaryStage.setResizable(false); 
    primaryStage.show(); 
} 

//Creates an AnchorPane for the map 
private AnchorPane addMapAnchor() 
{ 
    AnchorPane mapAnchor = new AnchorPane(); 
    ScrollPane mapScrollO = addMapScroll(); 
    mapAnchor.getChildren().add(mapScrollO); 
    AnchorPane.setLeftAnchor(mapScrollO, 0.0); 
    AnchorPane.setTopAnchor(mapScrollO, 0.0); 
    AnchorPane.setBottomAnchor(mapScrollO, 0.0); 
    AnchorPane.setRightAnchor(mapScrollO, 0.0); 
    return mapAnchor; 
} 

//Creates an ImageView for the map 
private ImageView addMapView() 
{ 
    Image mapImage = new Image("WorldProvincialMap-v1.01.png"); 
    ImageView mapView = new ImageView(mapImage); 
    GraphicsDevice gd =    GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); 
    int width = gd.getDisplayMode().getWidth(); 
    int height = gd.getDisplayMode().getHeight(); 
    mapView.setFitHeight(height); 
    mapView.setFitWidth(width); 
    return mapView; 
} 

//Creates a scrollPane for the map 
private ScrollPane addMapScroll() 
{ 
    ScrollPane mapScroll = new ScrollPane(); 
    ImageView mapViewO = addMapView(); 
    mapScroll.setContent(mapViewO); 
    mapScroll.setPannable(true); 
    mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER); 
    mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER); 
    mapScroll.addEventFilter(ScrollEvent.ANY, e ->{ 
     e.consume(); 
     if(e.getDeltaY() == 0) 
     { 
      return; 
     } 
     double scaleFactor = 
        (e.getDeltaY() > 0) 
        ? SCALE_DELTA 
        : 1/SCALE_DELTA; 

     if(scaleFactor * SCALE_TOTAL >= 1) 
     { 
      mapScroll.setScaleX(mapScroll.getScaleX() * scaleFactor); 
      mapScroll.setScaleY(mapScroll.getScaleY() * scaleFactor); 
      SCALE_TOTAL *= scaleFactor; 
     } 
    }); 
    return mapScroll; 
    } 
} 
+0

나는이 테스트를하지 않은,하지만 내 생각 대신 마우스 이벤트에 응답하여 스크롤 창을 사용하지 않고 이미지보기의 뷰포트를 조작하는 방법을 고려할 수 있습니다. 어떤 것이 더 쉬운 지 분명하지 않습니다. –

답변

4

콘텐츠 대신 ScrollPane의 크기가 조정됩니다. 또한 ImageView의 크기를 조정하더라도 콘텐츠 크기를 계산할 때는 scaleXscaleY이 고려되지 않습니다. 당신은 그가 따라 위치를 스크롤 조정해야하기

private ScrollPane addMapScroll() { 
    ScrollPane mapScroll = new ScrollPane(); 
    ImageView mapViewO = addMapView(); 
    mapScroll.setContent(new Group(mapViewO)); 
    mapScroll.setPannable(true); 
    mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER); 
    mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER); 
    mapScroll.addEventFilter(ScrollEvent.ANY, e -> { 
     e.consume(); 
     if (e.getDeltaY() == 0) { 
      return; 
     } 
     double scaleFactor 
       = (e.getDeltaY() > 0) 
         ? SCALE_DELTA 
         : 1/SCALE_DELTA; 

     if (scaleFactor * SCALE_TOTAL >= 1) { 
      mapViewO.setScaleX(mapViewO.getScaleX() * scaleFactor); 
      mapViewO.setScaleY(mapViewO.getScaleY() * scaleFactor); 
      SCALE_TOTAL *= scaleFactor; 
     } 
    }); 
    return mapScroll; 
} 

"중심을 유지가 중심": 따라서 ImageViewGroup에 싸여해야

if (scaleFactor * SCALE_TOTAL >= 1) { 
    Bounds viewPort = mapScroll.getViewportBounds(); 
    Bounds contentSize = mapViewO.getBoundsInParent(); 

    double centerPosX = (contentSize.getWidth() - viewPort.getWidth()) * mapScroll.getHvalue() + viewPort.getWidth()/2; 
    double centerPosY = (contentSize.getHeight() - viewPort.getHeight()) * mapScroll.getVvalue() + viewPort.getHeight()/2; 

    mapViewO.setScaleX(mapViewO.getScaleX() * scaleFactor); 
    mapViewO.setScaleY(mapViewO.getScaleY() * scaleFactor); 
    SCALE_TOTAL *= scaleFactor; 

    double newCenterX = centerPosX * scaleFactor; 
    double newCenterY = centerPosY * scaleFactor; 

    mapScroll.setHvalue((newCenterX - viewPort.getWidth()/2)/(contentSize.getWidth() * scaleFactor - viewPort.getWidth())); 
    mapScroll.setVvalue((newCenterY - viewPort.getHeight()/2)/(contentSize.getHeight() * scaleFactor -viewPort.getHeight())); 
} 
+0

이 솔루션을 사용했습니다. 그러나 이제 확대하면 왼쪽 상단으로 이동합니다. 화면 가운데를 확대 할 수있는 방법이 있습니까? –

+0

@AdamRen 실제로는 있지만 스크롤 위치를 다시 계산해야합니다. 내 편집을 참조하십시오. – fabian

1

나는 mouseDragHandler를 사용하여 버전을 향상 시켰습니다.

문제 해결에 가장 적합한 솔루션입니다.

package test; 

import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.control.ScrollPane.ScrollBarPolicy; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.input.ScrollEvent; 
import javafx.scene.layout.AnchorPane; 
import javafx.stage.Stage; 

public class test extends Application { 

final double SCALE_DELTA = 1.1; 
public double SCALE_TOTAL = 1; 

public double dragDeltay; 
public double dragDeltax; 


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

@Override 
public void start(Stage primaryStage) throws Exception { 
    AnchorPane mapAnchorO = addMapAnchor(); 
    Scene mapScene = new Scene(mapAnchorO); 
    primaryStage.setScene(mapScene); 
    primaryStage.setFullScreen(true); 
    primaryStage.setResizable(false); 
    primaryStage.show(); 
} 

// Creates an AnchorPane for the map 
private AnchorPane addMapAnchor() { 
    AnchorPane mapAnchor = new AnchorPane(); 
    ScrollPane mapScrollO = addMapScroll(); 
    mapAnchor.getChildren().add(mapScrollO); 
    AnchorPane.setLeftAnchor(mapScrollO, 0.0); 
    AnchorPane.setTopAnchor(mapScrollO, 0.0); 
    AnchorPane.setBottomAnchor(mapScrollO, 0.0); 
    AnchorPane.setRightAnchor(mapScrollO, 0.0); 
    return mapAnchor; 
} 

// Creates an ImageView for the map 
private ImageView addMapView() { 
    Image mapImage = new Image("WorldProvincialMap-v1.01.png"); 
    ImageView mapView = new ImageView(mapImage); 
    GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); 
    int width = gd.getDisplayMode().getWidth(); 
    int height = gd.getDisplayMode().getHeight(); 
    mapView.setFitHeight(height); 
    mapView.setFitWidth(width); 
    return mapView; 
} 

// Creates a scrollPane for the map 
private ScrollPane addMapScroll() { 
    ScrollPane mapScroll = new ScrollPane(); 
    ImageView mapViewO = addMapView(); 
    mapScroll.setContent(mapViewO); 

    mapViewO.setOnMousePressed(new EventHandler<MouseEvent>() { 
     @Override 
     public void handle(MouseEvent mouseEvent) { 
      dragDeltax = mapViewO.getX() - mouseEvent.getScreenX(); 
      dragDeltay = mapViewO.getY() - mouseEvent.getScreenY(); 
     } 
    }); 

    mapViewO.setOnMouseDragged(new EventHandler<MouseEvent>() { 
     @Override 
     public void handle(MouseEvent mouseEvent) { 
      mapScroll.setTranslateX(mouseEvent.getScreenX() + dragDeltax); 
      mapScroll.setTranslateY(mouseEvent.getScreenY() + dragDeltay); 
     } 
    }); 

    mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER); 
    mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER); 
    mapScroll.addEventFilter(ScrollEvent.ANY, e -> { 
     e.consume(); 
     if (e.getDeltaY() == 0) { 
      return; 
     } 
     double scaleFactor = (e.getDeltaY() > 0) ? SCALE_DELTA : 1/SCALE_DELTA; 

     if (scaleFactor * SCALE_TOTAL >= 1) { 
      mapScroll.setScaleX(mapScroll.getScaleX() * scaleFactor); 
      mapScroll.setScaleY(mapScroll.getScaleY() * scaleFactor); 
      SCALE_TOTAL *= scaleFactor; 
     } 
    }); 

    return mapScroll; 
} 

} 
+0

이렇게하면 패닝의 문제는 해결되지만지도 외부에서 볼 수있는 문제가 발생합니다. 그 해결책이 있습니까? –