Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

How may I zoom a Node centered in a ScrollPane?

jsmithMay 22 2013 — edited Jul 17 2013
I created a small sample application for zooming a node.

The application currently works by clipping the node when the node gets larger than it's container's viewable area.

I would like to place the node in a ScrollPane and maintain the following properties:

1. If the available scrollpane viewport is larger than the node, then the node is centered in the viewport.
2. Scrolling the mouse wheel anywhere within the viewport zooms the node in and out, it does not pan the node.
3. When zooming in or out on the node, the node does not shift around, but always zooms in or out on the current center of the viewport.
4. By pressing and dragging the mouse on the node you can pan the visible portion of the node within the viewport.

The zoom behaviour without panning the node around at all should be exactly the same as the clipped behaviour exhibited by the sample application.

What is the modification to the sample application required to achieve the desired behaviour?
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.event.*;
import javafx.geometry.Bounds;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;

public class GraphicsScalingApp extends Application {
  public static void main(String[] args) { launch(args); }

  @Override public void start(final Stage stage) {
    final Group group = new Group(
        createStar(),
        createCurve()
    );

    Parent zoomPane = createZoomPane(group);

    VBox layout = new VBox();
    layout.getChildren().setAll(
        createMenuBar(stage, group),
        zoomPane
    );

    VBox.setVgrow(zoomPane, Priority.ALWAYS);
    Scene scene = new Scene(
        layout
    );

    stage.setTitle("Zoomy");
    stage.getIcons().setAll(new Image(APP_ICON));
    stage.setScene(scene);
    stage.show();
  }

  private Parent createZoomPane(final Group group) {
    final double SCALE_DELTA = 1.1;
    final StackPane zoomPane = new StackPane();

    zoomPane.getChildren().add(group);
    zoomPane.setOnScroll(new EventHandler<ScrollEvent>() {
      @Override public void handle(ScrollEvent event) {
        event.consume();

        if (event.getDeltaY() == 0) {
          return;
        }

        double scaleFactor =
          (event.getDeltaY() > 0)
            ? SCALE_DELTA
            : 1/SCALE_DELTA;

        group.setScaleX(group.getScaleX() * scaleFactor);
        group.setScaleY(group.getScaleY() * scaleFactor);
      }
    });

    zoomPane.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
      @Override public void changed(ObservableValue<? extends Bounds> observable, Bounds oldBounds, Bounds bounds) {
      zoomPane.setClip(new Rectangle(bounds.getMinX(), bounds.getMinY(), bounds.getWidth(), bounds.getHeight()));
      }
    });

    return zoomPane;
  }

  private SVGPath createCurve() {
    SVGPath ellipticalArc = new SVGPath();
    ellipticalArc.setContent(
        "M10,150 A15 15 180 0 1 70 140 A15 25 180 0 0 130 130 A15 55 180 0 1 190 120"
    );
    ellipticalArc.setStroke(Color.LIGHTGREEN);
    ellipticalArc.setStrokeWidth(4);
    ellipticalArc.setFill(null);
    return ellipticalArc;
  }

  private SVGPath createStar() {
    SVGPath star = new SVGPath();
    star.setContent(
        "M100,10 L100,10 40,180 190,60 10,60 160,180 z"
    );
    star.setStrokeLineJoin(StrokeLineJoin.ROUND);
    star.setStroke(Color.BLUE);
    star.setFill(Color.DARKBLUE);
    star.setStrokeWidth(4);
    return star;
  }

  private MenuBar createMenuBar(final Stage stage, final Group group) {
    Menu fileMenu = new Menu("_File");
    MenuItem exitMenuItem = new MenuItem("E_xit");
    exitMenuItem.setGraphic(new ImageView(new Image(CLOSE_ICON)));
    exitMenuItem.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        stage.close();
      }
    });
    fileMenu.getItems().setAll(
        exitMenuItem
    );
    Menu zoomMenu = new Menu("_Zoom");
    MenuItem zoomResetMenuItem = new MenuItem("Zoom _Reset");
    zoomResetMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.ESCAPE));
    zoomResetMenuItem.setGraphic(new ImageView(new Image(ZOOM_RESET_ICON)));
    zoomResetMenuItem.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        group.setScaleX(1);
        group.setScaleY(1);
      }
    });
    MenuItem zoomInMenuItem = new MenuItem("Zoom _In");
    zoomInMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.I));
    zoomInMenuItem.setGraphic(new ImageView(new Image(ZOOM_IN_ICON)));
    zoomInMenuItem.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        group.setScaleX(group.getScaleX() * 1.5);
        group.setScaleY(group.getScaleY() * 1.5);
      }
    });
    MenuItem zoomOutMenuItem = new MenuItem("Zoom _Out");
    zoomOutMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.O));
    zoomOutMenuItem.setGraphic(new ImageView(new Image(ZOOM_OUT_ICON)));
    zoomOutMenuItem.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        group.setScaleX(group.getScaleX() * 1/1.5);
        group.setScaleY(group.getScaleY() * 1/1.5);
      }
    });
    zoomMenu.getItems().setAll(
        zoomResetMenuItem,
        zoomInMenuItem,
        zoomOutMenuItem
    );
    MenuBar menuBar = new MenuBar();
    menuBar.getMenus().setAll(
        fileMenu,
        zoomMenu
    );
    return menuBar;
  }

  // icons source from: http://www.iconarchive.com/show/soft-scraps-icons-by-deleket.html
  // icon license: CC Attribution-Noncommercial-No Derivate 3.0 =? http://creativecommons.org/licenses/by-nc-nd/3.0/
  // icon Commercial usage: Allowed (Author Approval required -> Visit artist website for details).

  public static final String APP_ICON        = "http://icons.iconarchive.com/icons/deleket/soft-scraps/128/Zoom-icon.png";
  public static final String ZOOM_RESET_ICON = "http://icons.iconarchive.com/icons/deleket/soft-scraps/24/Zoom-icon.png";
  public static final String ZOOM_OUT_ICON   = "http://icons.iconarchive.com/icons/deleket/soft-scraps/24/Zoom-Out-icon.png";
  public static final String ZOOM_IN_ICON    = "http://icons.iconarchive.com/icons/deleket/soft-scraps/24/Zoom-In-icon.png";
  public static final String CLOSE_ICON      = "http://icons.iconarchive.com/icons/deleket/soft-scraps/24/Button-Close-icon.png";
}
This post has been answered by James_D on May 24 2013
Jump to Answer

Comments

RadhakrishnaSarma
SQL> create table sample1
  2  as select 1 col1, null col2 from dual
  3  union all
  4  select 2, null from dual
  5  union all
  6  select null, 3 from dual
  7  /

Table created.

SQL> select column_name, num_nulls
  2  from user_tab_col_statistics
  3  where table_name = 'SAMPLE1'
  4  /

no rows selected

SQL> execute dbms_stats.gather_table_stats(user, 'SAMPLE1');

PL/SQL procedure successfully completed.

SQL> select column_name, num_nulls
  2  from user_tab_col_statistics
  3  where table_name = 'SAMPLE1'
  4  /

COLUMN_NAME                     NUM_NULLS
------------------------------ ----------
COL1                                    1
COL2                                    2

SQL> 
Cheers
Sarma.
549855
Hi Sarma,
Thank you for your quick response.
Your solution looks fine , but i dont want to recollect statistics on my production database with noreason.
Could you please suggest another option ?
Thanks.
RPuttagunta
You can write a select which 'counts' each column for number of NON_NULL. Something like:

select 'select count(*), '|| column_name || ' from ' || table_name || ' where ' || column_name || ' is not null;' from user_tab_cols s where s.table_name = 'your_table';

and then:

run the output selects on their own. Wherever the counts are zero, there is your column.

Message was edited by:
RPuttagunta
RadhakrishnaSarma
You can use Dynamic SQL to get the column_names from user_tab_columns and then for each columns execute the null check and get the count.
Your solution looks fine , but i dont want to recollect statistics on my production database with
noreason.
Your approach is not correct. With Production database, you OUGHT to have statistics up-to-date. If you have statistics already available, then skip the collection of statistics and just use my SQL.

Cheers
sarma.
1 - 4
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Aug 14 2013
Added on May 22 2013
16 comments
20,466 views