Zooming a plot in a JScrollPane

Hi,
I am stuck! I'd appreciate it if you can get me unstuck ...
Below a trimmed-down .java file with a "main" that shows my problem. I create a JFrame. In the contentPane of this JFrame I put a JScrollPane, and in that JScrollPane I put a JPanel. I then show() the JFrame and set the preferredSize of the JPanel equal to it's actual getSize(). This way the scrollbars are just not required. If the user makes the JFrame a little bit smaller with the mouse, then the scrollbars appear. Try it!
In the JPanel I plot an artificial profile in a white rectangle, i.e. a simple cross-plot. To convert from userspace to physical space I use a combination of 4 affineTransforms, all according to 'the book'. All works lovely.
Now I want to zoom by dragging a box in the plot. Note that I already have the code that shows the zoom-box! Once I let go of the mouse (mouseReleased) I want to zoom on that box, and that's where it goes wrong. With some jickerypoke I can actually do the zoom (not in the code below), but ... the scrollBars do not appear, and the whole idea of course if that they do appear, so that the user can scroll up/down sideways without having to change the scaling.
( In essence the question is this: if I plot outside of the (user) min/max (for instance change the line "line.lineTo((float)x, (float)y[i]);" to "line.lineTo((float)x[i], (float)(y[i]+500));"), why does the JScrollPane not decide to pop-up the scrollBars so that the user can scroll to the bit outside of the (user) min/max? )
I'd be grateful for some pointers as to how to fix this, as I am going around in circles.
Cheers - Michel - London
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
public class PanelModelTest2 extends JPanel implements MouseListener, MouseMotionListener {
//Constants
private final double MARGIN_TOP = 50.0;
private final double MARGIN_BOTTOM = 10.0;
private final double MARGIN_LEFT = 50.0;
private final double MARGIN_RIGHT = 10.0;
//Private parts
private Model model_;
private Point2D mouseDownPosition_ = null;
private Point2D mouseDragPosition_ = null;
private boolean flMouseInPanel_;
private AffineTransform affineTransform_;
public PanelModelTest2(Model model) {
model_ = model;
addMouseListener(this);
addMouseMotionListener(this);
public void paintComponent(Graphics g) {
//Always call this method on the parents first. (Why???)
super.paintComponent(g);
//Cast g onto g2d to expose the extra methods!
Graphics2D g2d = (Graphics2D)g;
//Determine the userspace
double xMin = model_.getXMin();
double xMax = model_.getXMax();
double xRng = xMax - xMin;
double yMin = model_.getYMin();
double yMax = model_.getYMax();
double yRng = yMax - yMin;
//Determine the physical space (width and height is all you need)
Dimension panelDimension = getSize();
double xRngPhy = panelDimension.getWidth();
double yRngPhy = panelDimension.getHeight();
//Instantiate the affineTransform_, then compose in reverse order!
affineTransform_ = new AffineTransform(); //Default: the Identity transform
//==>Step 4: Move axes "Margin' away from the origin
affineTransform_.translate(MARGIN_LEFT, MARGIN_TOP);
//==>Step 3: Map from panelspace to axesspace
affineTransform_.scale((xRngPhy - MARGIN_LEFT - MARGIN_RIGHT)/xRngPhy, (yRngPhy - MARGIN_TOP - MARGIN_BOTTOM)/yRngPhy);
//==>Step 2: Map from userspace to panelspace
affineTransform_.scale(xRngPhy/xRng, yRngPhy/yRng);
//==>Step 1: Map (xMin,yMin) onto (0,0)
affineTransform_.translate(-xMin, -yMin);
//1. Make, then draw the axes rectangle
Rectangle2D whiteAxes = new Rectangle2D.Double(xMin, yMin, xRng, yRng);
g2d.setColor(Color.WHITE);
g2d.fill(affineTransform_.createTransformedShape(whiteAxes));
g2d.setColor(Color.BLACK); //Reset color to black!
//2. Plot the axes
//Still outstanding!!
//3. Get, then plot the data
double[] y = model_.getY();
double[] x = model_.getX();
GeneralPath line = new GeneralPath();
for (int i=0; i<y.length; i++) {
if (i==0) line.moveTo((float)x[i], (float)y[i]);
line.lineTo((float)x[i], (float)y[i]);
g2d.clip(affineTransform_.createTransformedShape(whiteAxes));
g2d.draw(affineTransform_.createTransformedShape(line));
//Zoom box
if (flMouseInPanel_) {
if (mouseDownPosition_ != null) {
Rectangle2D zoomBox = new Rectangle2D.Double(mouseDownPosition_.getX(), mouseDownPosition_.getY(), mouseDragPosition_.getX() - mouseDownPosition_.getX(), mouseDragPosition_.getY() - mouseDownPosition_.getY());
g2d.draw(zoomBox);
public void mouseEntered(MouseEvent evt) {
flMouseInPanel_ = true;
public void mouseExited(MouseEvent evt) {
flMouseInPanel_ = false;
public void mouseMoved(MouseEvent evt) {
public void mouseReleased(MouseEvent evt) {
//Here code to zoom!!!???
mouseDownPosition_ = null; //This ensures that the
mouseDragPosition_ = null; //zoombox is no longer plotted!
repaint();
public void mousePressed(MouseEvent evt) {
mouseDownPosition_ = evt.getPoint();
public void mouseClicked(MouseEvent evt) {
public void mouseDragged(MouseEvent evt) {
mouseDragPosition_ = evt.getPoint();
repaint();
public static void main(String[] args) {
Model model = new Model();
MainJFrame mainJFrame = new MainJFrame(model);
class Model {
//Private parts ...
private double yMin_;
private double yMax_;
private double xMin_;
private double xMax_;
private double[] y_ = new double[20];
private double[] x_ = new double[20];
public Model() {
//Make fake profile
for (int i=0; i<20; i++) {
y_[i]=50*i+1300;
x_[i]=Math.sin(i/3);
//Set corresponding mins and maxs
xMin_ = -1;
xMax_ = 1;
yMin_ = 1300;
yMax_ = 2300;
public double getXMin() {return xMin_;}
public double getXMax() {return xMax_;}
public double getYMin() {return yMin_;}
public double getYMax() {return yMax_;}
public double[] getX() {return x_;}
public double[] getY() {return y_;}
class MainJFrame extends JFrame {
//Constants
public final static int WINDOWS_START_BAR_HEIGHT = 28;
//Private parts ...
private Model model_;
private PanelModelTest2 pnlModel_;
public MainJFrame(Model model) {
//Set the private parts associated with the input arguments ...
model_ = model;
//Deal with using clicking the 'x' in the top right corner
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {dispose(); System.exit(0);}
//Panel goes 'in' JScrollPane, which goes 'in' JFrame's contentPane
pnlModel_ = new PanelModelTest2(model_);
JScrollPane scroller = new JScrollPane(pnlModel_);
getContentPane().add(scroller, BorderLayout.CENTER);
//Pack, set to full screen, show and set preferredSize of panel to it's getSize
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
pack();
setBounds(0, 0, (int)screenSize.getWidth(), (int)screenSize.getHeight() - WINDOWS_START_BAR_HEIGHT);
show();
pnlModel_.setPreferredSize(pnlModel_.getSize()); //Now, if you make window wee bit
} //smaller, scrollbars appear
public PanelModelTest2 getPnlModel() {return pnlModel_;}

Oops, I forgot the tags. Here it is again ...
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
public class PanelModelTest2 extends JPanel implements MouseListener, MouseMotionListener {
    //Constants
    private final double MARGIN_TOP = 50.0;
    private final double MARGIN_BOTTOM = 10.0;
    private final double MARGIN_LEFT = 50.0;
    private final double MARGIN_RIGHT = 10.0;
    //Private parts
    private Model model_;
    private Point2D mouseDownPosition_ = null;
    private Point2D mouseDragPosition_ = null;
    private boolean flMouseInPanel_;
    private AffineTransform affineTransform_;
    public PanelModelTest2(Model model) {
        model_ = model;
        addMouseListener(this);
        addMouseMotionListener(this);
    public void paintComponent(Graphics g) {
        //Always call this method on the parents first. (Why???)
        super.paintComponent(g);
        //Cast g onto g2d to expose the extra methods!
        Graphics2D g2d = (Graphics2D)g;
        //Determine the userspace
        double xMin = model_.getXMin();
        double xMax = model_.getXMax();
        double xRng = xMax - xMin;
        double yMin = model_.getYMin();
        double yMax = model_.getYMax();
        double yRng = yMax - yMin;
        //Determine the physical space (width and height is all you need)
        Dimension panelDimension = getSize();
        double xRngPhy = panelDimension.getWidth();
        double yRngPhy = panelDimension.getHeight();
        //Instantiate the affineTransform_, then compose in reverse order!
        affineTransform_ = new AffineTransform(); //Default: the Identity transform
        //==>Step 4: Move axes "Margin' away from the origin
        affineTransform_.translate(MARGIN_LEFT, MARGIN_TOP);
        //==>Step 3: Map from panelspace to axesspace
        affineTransform_.scale((xRngPhy - MARGIN_LEFT - MARGIN_RIGHT)/xRngPhy, (yRngPhy - MARGIN_TOP - MARGIN_BOTTOM)/yRngPhy);
        //==>Step 2: Map from userspace to panelspace
        affineTransform_.scale(xRngPhy/xRng, yRngPhy/yRng);
        //==>Step 1: Map (xMin,yMin) onto (0,0)
        affineTransform_.translate(-xMin, -yMin);
        //1. Make, then draw the axes rectangle     
        Rectangle2D whiteAxes = new Rectangle2D.Double(xMin, yMin, xRng, yRng);
        g2d.setColor(Color.WHITE);
        g2d.fill(affineTransform_.createTransformedShape(whiteAxes));
        g2d.setColor(Color.BLACK); //Reset color to black!
        //2. Plot the axes
        //Still outstanding!!
        //3. Get, then plot the data
        double[] y = model_.getY();
        double[] x = model_.getX();
        GeneralPath line = new GeneralPath();
        for (int i=0; i<y.length; i++) {
            if (i==0) line.moveTo((float)x, (float)y[i]);
line.lineTo((float)x[i], (float)y[i]);
g2d.clip(affineTransform_.createTransformedShape(whiteAxes));
g2d.draw(affineTransform_.createTransformedShape(line));
//Zoom box
if (flMouseInPanel_) {
if (mouseDownPosition_ != null) {
Rectangle2D zoomBox = new Rectangle2D.Double(mouseDownPosition_.getX(), mouseDownPosition_.getY(), mouseDragPosition_.getX() - mouseDownPosition_.getX(), mouseDragPosition_.getY() - mouseDownPosition_.getY());
g2d.draw(zoomBox);
public void mouseEntered(MouseEvent evt) {
flMouseInPanel_ = true;
public void mouseExited(MouseEvent evt) {
flMouseInPanel_ = false;
public void mouseMoved(MouseEvent evt) {
public void mouseReleased(MouseEvent evt) {
//Here code to zoom!!!???
mouseDownPosition_ = null; //This ensures that the
mouseDragPosition_ = null; //zoombox is no longer plotted!
repaint();
public void mousePressed(MouseEvent evt) {
mouseDownPosition_ = evt.getPoint();
public void mouseClicked(MouseEvent evt) {
public void mouseDragged(MouseEvent evt) {
mouseDragPosition_ = evt.getPoint();
repaint();
public static void main(String[] args) {
Model model = new Model();
MainJFrame mainJFrame = new MainJFrame(model);
class Model {
//Private parts ...
private double yMin_;
private double yMax_;
private double xMin_;
private double xMax_;
private double[] y_ = new double[20];
private double[] x_ = new double[20];
public Model() {
//Make fake profile
for (int i=0; i<20; i++) {
y_[i]=50*i+1300;
x_[i]=Math.sin(i/3);
//Set corresponding mins and maxs
xMin_ = -1;
xMax_ = 1;
yMin_ = 1300;
yMax_ = 2300;
public double getXMin() {return xMin_;}
public double getXMax() {return xMax_;}
public double getYMin() {return yMin_;}
public double getYMax() {return yMax_;}
public double[] getX() {return x_;}
public double[] getY() {return y_;}
class MainJFrame extends JFrame {
//Constants
public final static int WINDOWS_START_BAR_HEIGHT = 28;
//Private parts ...
private Model model_;
private PanelModelTest2 pnlModel_;
public MainJFrame(Model model) {
//Set the private parts associated with the input arguments ...
model_ = model;
//Deal with using clicking the 'x' in the top right corner
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {dispose(); System.exit(0);}
//Panel goes 'in' JScrollPane, which goes 'in' JFrame's contentPane
pnlModel_ = new PanelModelTest2(model_);
JScrollPane scroller = new JScrollPane(pnlModel_);
getContentPane().add(scroller, BorderLayout.CENTER);
//Pack, set to full screen, show and set preferredSize of panel to it's getSize
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
pack();
setBounds(0, 0, (int)screenSize.getWidth(), (int)screenSize.getHeight() - WINDOWS_START_BAR_HEIGHT);
show();
pnlModel_.setPreferredSize(pnlModel_.getSize()); //Now, if you make window wee bit
} //smaller, scrollbars appear
public PanelModelTest2 getPnlModel() {return pnlModel_;}

Similar Messages

  • Zooming Options in Diadem View Window

    How can I make it possible to zoom all plots in different sheets (View Window) to same range on x-axis (all plots have same x-axis)

    Hi Vasista,
    If you put these two attached VBScripts in the same folder somewhere, then run the "Cursor Memory.VBS" script in the DIAdem SCRIPT panel, it will declare that the callback function in the "Cursor Memory Functions.VBS" script should run every time you switch between tabs in DIAdem VIEW.  This function sets the new tab's cursor properties equal to the old tab's cursor properties.
    I believe this will give you what you want,
    Brad Turpin
    DIAdem Product Support Engineer
    National Instruments
    Attachments:
    Cursor Memory.VBS ‏1 KB
    Cursor Memory Functions.VBS ‏2 KB

  • Zooming into image problems

    Hi everybody,
    I'm trying to learn how to zoom images, and I've been able to put together a test program; based on the posts I've seen on this forum (I didn't see anything about zooming in the Java tutorial), I thought it should be working, but it doesn't.
    My GUI consists of a JLabel with an icon on it, and a button panel beneath with zoom percentages. When I click on one of the zoom percentage buttons, the image is supposed to zoom in or out to that percent magnification, based on its original size (when the GUI is first created). When I click on the buttons in my test GUI, though, nothing happens to the image.
    EDIT: Oh, and I forgot to ask -- is zooming an established image like this the same as zooming a panel on which something has been painted? That's my eventual goal, but I thought it might be easier to learn with an established image first.
    Would anyone mind looking at my code, please, and giving me a hand?
    Thanks,
    Jezzica85
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GridLayout;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.geom.AffineTransform;
    import java.io.File;
    import javax.imageio.ImageIO;
    import javax.swing.BorderFactory;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    public class ZoomTest extends JPanel {
         private static final long serialVersionUID = 1L;     // Serial ID
         private ImageIcon icon;                                        // Icon shown as picture
         private int zoomFactor;                                        // Factor of zoom (percent--ex 25=25%)
         // Constructor
         public ZoomTest() throws Exception {
              // Set initial zoom factor and read file
              zoomFactor = 100;
              String file = "C:\\test.bmp";
              icon = new ImageIcon( ImageIO.read( new File( file ) ) );
              JLabel label = new JLabel();
              label.setIcon( icon );
              // Add label with picture to scroll pane so zoomed image can be seen
              JScrollPane scroller = new JScrollPane( label );
              scroller.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS );
              scroller.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
              scroller.setBorder( BorderFactory.createEmptyBorder( 10, 10, 10, 10 ) );
              scroller.setOpaque( true );
              scroller.setBackground( Color.WHITE );
              add( scroller );
         // Paint the image
         public void paintComponent( Graphics g ) {
              super.paintComponent( g );
            Graphics2D g2 = (Graphics2D)g;
            RenderingHints rh = new RenderingHints(
                 RenderingHints.KEY_ANTIALIASING,
                 RenderingHints.VALUE_ANTIALIAS_ON );
            g2.setRenderingHints( rh );
            AffineTransform at = new AffineTransform();
            AffineTransform initial = g2.getTransform();
            at.scale( zoomFactor, zoomFactor );
            g2.drawImage( icon.getImage(), at, this );
            g2.setTransform( initial );
         // Set the zoom factor for this panel
         public void setZoom( int factor ) { zoomFactor = factor; }
         // Main method for testing
         public static void main( String args[] ) {
              try {
                   // Add zoomable panel to frame
                   JFrame frame = new JFrame( "Zoom Test" );
                   frame.setLayout( new BorderLayout() );
                   final ZoomTest zoomer = new ZoomTest();
                   frame.add( zoomer );
                   // Add button panel with zoom levels
                   JPanel panel = new JPanel( new GridLayout( 1, 8 ) );
                   for( int i = 25; i <= 200; i+=25 ) {
                        final int amount = i;
                        JButton button = new JButton( Integer.toString( i ) );
                        button.addActionListener( new ActionListener() {
                             public void actionPerformed( ActionEvent e ) {
                                  zoomer.setZoom( amount );
                                  zoomer.repaint();
                        panel.add( button );
                   frame.add( panel, BorderLayout.SOUTH );
                   // Set Frame properties
                   frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                   frame.pack();
                   frame.setResizable( false );
                   frame.setAlwaysOnTop( true );
                   frame.setLocationRelativeTo( null );
                   frame.setVisible( true );
              catch( Exception e ) {
                   e.printStackTrace();
                   System.exit( -1 );
    }Edited by: jezzica85 on Dec 12, 2008 11:17 AM

    Since so many help me here, here is one solution
    package com.unittest.images;
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GraphicsConfiguration;
    import java.awt.GraphicsEnvironment;
    import java.awt.GridLayout;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import javax.imageio.ImageIO;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    * @author gcaulton
    public class Test extends JPanel {
              private static final long serialVersionUID = 1L;     // Serial ID
              private int zoomFactor = 100;                                        // Factor of zoom (percent--ex 25=25%)
              private BufferedImage zoomedImage = null;
              private BufferedImage originalImage = null;
              public Test() {
                   setOpaque(false);
              // Paint the image
              public void paintComponent( Graphics g ) {
                   super.paintComponent( g );
                 Graphics2D g2 = (Graphics2D)g;
                 g2.drawImage( zoomImage(), null, 0, 0);
              // Set the zoom factor for this panel
              public void setZoom( int factor ) {
                   zoomFactor = factor;
                   int newWidth = (int) (originalImage.getWidth() * zoomFactor /100.0);
                   int newHeight = (int) (originalImage.getHeight() * zoomFactor /100.0);
                   zoomedImage = resizeImage(originalImage, newWidth, newHeight);
              // Main method for testing
              public static void main( String args[] ) {
                   try {
                        // Add zoomable panel to frame
                        JFrame frame = new JFrame( "Zoom Test" );
                        frame.setLayout( new BorderLayout() );
                        final Test zoomer = new Test();
                        String file = "C:\\test.bmp";
                        zoomer.originalImage = ImageIO.read( new File( file ));
                        frame.getContentPane().setLayout(new BorderLayout());
                        frame.getContentPane().add( zoomer, BorderLayout.CENTER);
                        // Add button panel with zoom levels
                        JPanel panel = new JPanel( new GridLayout( 1, 8 ) );
                        for( int i = 25; i <= 200; i+=25 ) {
                             final int amount = i;
                             JButton button = new JButton( Integer.toString( i ) );
                             button.addActionListener( new ActionListener() {
                                  public void actionPerformed( ActionEvent e ) {
                                       zoomer.setZoom( amount );
                                       zoomer.repaint();
                             panel.add( button );
                        frame.add( panel, BorderLayout.SOUTH );
                        // Set Frame properties
                        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                        frame.setResizable( true );
                        frame.setAlwaysOnTop( true );
                        frame.setSize(zoomer.originalImage.getWidth(),zoomer.originalImage.getHeight()+200);
                        frame.setLocationRelativeTo( null );
                        frame.setVisible( true );
                        zoomer.setZoom(100);
                   catch( Exception e ) {
                        e.printStackTrace();
                        System.exit( -1 );
              private BufferedImage zoomImage() {
                   return zoomedImage;
              * @param image
              * @param newWidth
              * @param newHeight
              * @return
             public static BufferedImage resizeImage(BufferedImage image, int newWidth, int newHeight) {
                 if (image.getWidth() == newWidth && image.getHeight() == newHeight) {
                      return image;
                 } else {
                     BufferedImage temp = createCompatibleImage(image, newWidth, newHeight);
                     Graphics2D g2 = temp.createGraphics();
                     g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                     g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null);
                     g2.dispose();
                      return temp;
             public static BufferedImage createCompatibleImage(BufferedImage image, int width, int height) {
                  GraphicsConfiguration g = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
                 return g.createCompatibleImage(width, height, image.getTransparency());
    }

  • Zooming an image and scrolling it using a JScrollPane

    Hi all, I know this is one of the most common problems in this forum but i cant get any of the replys to work in my code.
    The problem:
    I create an image with varying pixel colors depending on the value obtained from an AbstractTableModel and display it to the screen.
    I then wish to be able to zoom in on the image and make it scrollable as required.
    At the minute the scrolling method is working but only when i resize or un-focus and re-focus the JInternalFrame. Ive tried calling revalidate (and various other options) on the JScrollPane within the paintComponents(Graphics g) method but all to no avail.
    Has anyone out there any ideas cause this is melting my head!
    Heres the code im using (instance is called and added to a JDesktopPane):
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.*;
    import java.awt.geom.AffineTransform;
    import uk.ac.qub.mvda.gui.MVDATableModel;
    import uk.ac.qub.mvda.utils.MVDAConstants;
    public class HCLSpectrumPlot extends JInternalFrame implements MVDAConstants
      AbstractAction zoomInAction = new ZoomInAction();
      AbstractAction zoomOutAction = new ZoomOutAction();
      double zoomFactorX = 1.0;
      double zoomFactorY = 1.0;
      private AffineTransform theTransform;
      private ImagePanel imageViewerPanel;
      private JScrollPane imageViewerScroller;
      public HCLSpectrumPlot(String title, MVDATableModel model)
        super(title, true, true, true, true);
        int imageHeight_numOfRows = model.getRowCount();
        int imageWidth_numOfCols = model.getColumnCount();
        int numberOfColourBands = 3;
        double maxValueInTable = 0;
        double[][] ValueAtTablePosition =
            new double[imageHeight_numOfRows][imageWidth_numOfCols];
        for(int i=0; i<imageHeight_numOfRows; i++)
          for(int j=0; j<imageWidth_numOfCols; j++)
         ValueAtTablePosition[i][j] = ((Double)model.getValueAt
                 (i,j)).doubleValue();
        for(int i=0; i<imageHeight_numOfRows; i++)
          for(int j=0; j<imageWidth_numOfCols; j++)
         if ( ValueAtTablePosition[i][j] > maxValueInTable)
           maxValueInTable = ValueAtTablePosition[i][j];
        BufferedImage newImage = new BufferedImage(imageWidth_numOfCols,
              imageHeight_numOfRows, BufferedImage.TYPE_3BYTE_BGR);
        WritableRaster newWritableImage = newImage.getRaster();
        int colourB;
        double pixelValue, cellValue, newPixelValue;
        for (int x = 0; x < imageHeight_numOfRows; x++)
          for (int y = 0; y < imageWidth_numOfCols; y++)
         colourB = 0;
         cellValue = ValueAtTablePosition[x][y];
         pixelValue = (1 - (cellValue / maxValueInTable)) * 767;
         pixelValue = pixelValue - 256;
         while (colourB < numberOfColourBands)
           if ( pixelValue < 0 )
             newPixelValue = 256 + pixelValue;
             newWritableImage.setSample(x, y, colourB, newPixelValue);
             colourB++;
                while ( colourB < numberOfColourBands )
               newWritableImage.setSample(x, y, colourB, 0);
               colourB++;
         else
           newWritableImage.setSample(x, y, colourB, 255);
         colourB++;
         pixelValue = pixelValue - 256;
          }//while
         }//for-y
        }//for-x
        imageViewerPanel = new ImagePanel(this, newImage);
        imageViewerScroller =     new JScrollPane(imageViewerPanel,
                            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                   JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        this.getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(imageViewerScroller, BorderLayout.CENTER);
        JToolBar editTools = new JToolBar();
        editTools.setOrientation(JToolBar.VERTICAL);
        editTools.add(zoomInAction);
        editTools.add(zoomOutAction);
        this.getContentPane().add(editTools, BorderLayout.WEST);
        this.setVisible(true);
      class ImagePanel extends JPanel
        private int iWidth, iHeight;
        private int i=0;
        private BufferedImage bufferedImageToDisplay;
        private JInternalFrame parentFrame;
        public ImagePanel(JInternalFrame parent, BufferedImage image)
          super();
          parentFrame = parent;
          bufferedImageToDisplay = image;
          iWidth = bufferedImageToDisplay.getWidth();
          iHeight = bufferedImageToDisplay.getHeight();
          theTransform = new AffineTransform();
          //theTransform.setToScale(parent.getContentPane().getWidth(),
                                    parent.getContentPane().getHeight());
          this.setPreferredSize(new Dimension(iWidth, iHeight));
        }//Constructor
        public void paintComponent(Graphics g)
          super.paintComponent(g);
          ((Graphics2D)g).drawRenderedImage(bufferedImageToDisplay,
                                             theTransform);
          this.setPreferredSize(new Dimension((int)(iWidth*zoomFactorX),
                                          (int)(iHeight*zoomFactorY)));
        }//paintComponent
      }// end class ImagePanel
       * Class to handle a zoom in event
       * @author Ross McCaughrain
       * @version 1.0
      class ZoomInAction extends AbstractAction
       * Default Constructor.
      public ZoomInAction()
        super(null, new ImageIcon(HCLSpectrumPlot.class.getResource("../"+
                  MVDAConstants.PATH_TO_IMAGES + "ZoomIn24.gif")));
        this.putValue(Action.SHORT_DESCRIPTION,"Zooms In on the Image");
        this.setEnabled(true);
      public void actionPerformed(ActionEvent e)
        zoomFactorX += 0.5;
        zoomFactorY += 0.5;
        theTransform = AffineTransform.getScaleInstance(zoomFactorX,
                                                    zoomFactorY);
        repaint();
      // ZoomOut to be implemented
    }// end class HCLSpectrumPlotAll/any help greatly appreciated! thanks for your time.
    RossMcC

    Small mistake, the revalidate must be called on the panel not on the jsp.
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class UsaZ extends JFrame 
         IPanel      panel = new IPanel();
         JScrollPane jsp   = new JScrollPane(panel);
    public UsaZ() 
         addWindowListener(new WindowAdapter()
         addWindowListener(new WindowAdapter()
         {     public void windowClosing(WindowEvent ev)
              {     dispose();
                   System.exit(0);
         setBackground(Color.lightGray);
         getContentPane().add("Center",jsp);
         setBounds(1,1,400,320);
         setVisible(true);
    public class IPanel extends JComponent
         Image  map;
         double zoom = 1;
         double iw;
         double ih;
    public IPanel()
         map = getToolkit().createImage("us.gif");
         MediaTracker tracker = new MediaTracker(this);
         tracker.addImage(map,0);
         try {tracker.waitForID(0);}
         catch (InterruptedException e){}
         iw = map.getWidth(this);
         ih = map.getHeight(this);
         zoom(0);     
         addMouseListener(new MouseAdapter()     
         {     public void mouseReleased(MouseEvent m)
                   zoom(0.04);               
                   repaint();      
                   revalidate();
    public void zoom(double z)
         zoom = zoom + z;
         setPreferredSize(new Dimension((int)(iw*zoom)+2,(int)(ih*zoom)+2));
    public void paintComponent(Graphics g)
         super.paintComponent(g);
         Graphics2D g2 = (Graphics2D)g;
         g2.scale(zoom,zoom);
         g2.drawImage(map,1,1,null);
         g.drawRect(0,0,map.getWidth(this)+1,map.getHeight(this)+1);
    public static void main (String[] args) 
          new UsaZ();
    [/cdoe]
    Noah                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

  • Zoom Issues with JScrollPane

    Hello all,
    I have ran into an issue with zoom functionality on a JScrollPane.
    Here is the situation (code to follow):
    I have a JFrame with a JDesktopPane as the contentpane. Then I have a JScrollPane with a JPanel inside. On this JPanel are three rectangles. When they are clicked on, they will open up a JInternalFrame with their name (rect1, rect2, or rect3) as the title bar. Rect3 is positioned (2000,2000).
    I have attached a mousewheel listener to the JPanel so I can zoom in and out.
    I have also attached a mouse listener so I can detect the mouse clicks for the rectangles. I also do a transformation on the point so I can be use it during clicks while the panel is zoomed.
    All of this works fantastic. The only issue I am having is that when the JScrollPane scroll bars change, I cannot select any of the rectangles.
    I will give a step by step reproduction to be used with the code:
    1.) Upon loading you will see two rectangles. Click the far right one. You'll see a window appear. Good. Move it to the far right side.
    2.) Zoom in with your mouse wheel (push it towards you) until you cannot zoom anymore (May have to get focus back on the panel). You should see three rectangles. Click on the newly shown rectangle. Another window, titled rect3 should appear. Close both windows.
    3.) This is where things get alittle tricky. Sometimes it works as intended, other times it doesn't. But do something to this affect: Scroll to the right so that only the third rectangle is showing. Try to click on it. If a window does not appear - that is the problem. But if a window does appear, close it out and try to click on the 3rd rect again. Most times, it will not display another window for me. I have to zoom out one step and back in. Then the window will appear.
    After playing around with it for awhile, I first thought it may be a focus issue...I've put some code in the internal window listeners so the JPanel/JScrollPane can grab the focus upon window closing, but it still does not work. So, either the AffineTransform and/or point conversion could be the problem with the scroll bars? It only happens when the scroll bar has been moved. What affect would this have on the AffineTransform and/or point conversion?
    Any help would be great.
    Here is the code, it consists of two files:
    import java.awt.Color;
    import java.awt.Dimension;
    import javax.swing.BorderFactory;
    import javax.swing.JDesktopPane;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    public class InternalFrameAffineTransformIssue
         public static void main ( String[] args )
              JFrame frame = new JFrame("AffineTransform Scroll Issue");
              frame.setLayout(null);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              JDesktopPane desktop = new JDesktopPane();
              frame.setContentPane(desktop);
              MyJPanel panel = new MyJPanel(frame);
              JScrollPane myScrollPane = new JScrollPane(panel);
              panel.setScrollPane(myScrollPane);
              myScrollPane.setLocation(0, 0);
              myScrollPane.setSize(new Dimension(800, 800));
              myScrollPane.getVerticalScrollBar().setUnitIncrement(50);
              myScrollPane.getHorizontalScrollBar().setUnitIncrement(50);
              myScrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black));
              frame.getContentPane().add(myScrollPane);
              frame.setBounds(0, 100, 900, 900);
              frame.setVisible(true);
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseWheelEvent;
    import java.awt.event.MouseWheelListener;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.NoninvertibleTransformException;
    import java.awt.geom.Point2D;
    import javax.swing.JFrame;
    import javax.swing.JInternalFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.event.InternalFrameAdapter;
    import javax.swing.event.InternalFrameEvent;
    import javax.swing.event.InternalFrameListener;
    public class MyJPanel extends JPanel implements MouseWheelListener
              double zoom = 1;
              Rectangle rect1 = new Rectangle(50, 50, 20, 20);
              Rectangle rect2 = new Rectangle(100, 50, 20, 20);
              Rectangle rect3 = new Rectangle(2000, 2000, 20, 20);
              AffineTransform zoomedAffineTransform;
              JFrame frame;
              JPanel myPanel = this;
              JScrollPane myScrollPane;
              public MyJPanel(JFrame inputFrame)
                   setAutoscrolls(true);
                   addMouseListener(new MouseAdapter(){
                        public void mousePressed ( MouseEvent e )
                             System.out.println("Clicked: " + e.getPoint());
                             AffineTransform affineTransform = zoomedAffineTransform;
                             Point2D transformedPoint = e.getPoint();
                             //Do the transform if it is not null
                             if(affineTransform != null)
                                  try
                                       transformedPoint = affineTransform.inverseTransform(transformedPoint, null);
                                  catch (NoninvertibleTransformException ex)
                                       ex.printStackTrace();
                             System.out.println("Tranformed Point: " + transformedPoint);
                             if(rect1.contains(transformedPoint))
                                  System.out.println("You clicked on rect1.");
                                  createInternalFrame("Rect1");
                             if(rect2.contains(transformedPoint))
                                  System.out.println("You clicked on rect2.");
                                  createInternalFrame("Rect2");
                             if(rect3.contains(transformedPoint))
                                  System.out.println("You clicked on rect3.");
                                  createInternalFrame("Rect3");
                   addMouseWheelListener(this);
                   frame = inputFrame;
                   setPreferredSize(new Dimension(4000, 4000));
                   setLocation(0, 0);
              public void paintComponent ( Graphics g )
                   super.paintComponent(g);
                   Graphics2D g2d = (Graphics2D) g;
                   g2d.scale(zoom, zoom);
                   zoomedAffineTransform = g2d.getTransform();
                   g2d.draw(rect1);
                   g2d.draw(rect2);
                   g2d.draw(rect3);
              public void mouseWheelMoved ( MouseWheelEvent e )
                   System.out.println("Mouse wheel is moving.");
                   if(e.getWheelRotation() == 1)
                        zoom -= 0.05;
                        if(zoom <= 0.20)
                             zoom = 0.20;
                   else if(e.getWheelRotation() == -1)
                        zoom += 0.05;
                        if(zoom >= 1)
                             zoom = 1;
                   repaint();
              public void createInternalFrame ( String name )
                   JInternalFrame internalFrame = new JInternalFrame(name, true, true, true, true);
                   internalFrame.setBounds(10, 10, 300, 300);
                   internalFrame.setVisible(true);
                   internalFrame.addInternalFrameListener(new InternalFrameAdapter(){
                        public void internalFrameClosed ( InternalFrameEvent arg0 )
                             //myPanel.grabFocus();
                             myScrollPane.grabFocus();
                        public void internalFrameClosing ( InternalFrameEvent arg0 )
                             //myPanel.grabFocus();
                             myScrollPane.grabFocus();
                   frame.getContentPane().add(internalFrame, 0);
              public void setScrollPane ( JScrollPane myScrollPane )
                   this.myScrollPane = myScrollPane;
         }

    What I'm noticing is your zoomedAffineTransform is changing when you click to close the internal frame. This ends up being passed down the line, thus mucking up your clicks until you do something to reset it (like zoom in and out).
    Clicking on the JInternalFrame appears to add a translate to the g2d transform. This translation is what's throwing everything off. So in the paintComponent where you set the zoomedAffineTransform, you can verify if the transform has a translation before storing the reference:
             if (g2d.getTransform().getTranslateX() == 0.0) {
                zoomedAffineTransform = g2d.getTransform();
             }Edited by: jboeing on Oct 2, 2009 8:23 AM

  • How to record and plot only the zoomed portion of a Graph or Chart?

    I'm using LabVIEW 8.6 and have problem plotting only zoomed part of a graph or chart onto other. Please help.

    Sorry, your VI makes absolutely no sense. First you slowly generate chart data, then you write it to a file, read it back from a file, do some exceedingly elaborate while loop that could be done with almost no code at all, then chart all data at once again. The stop button in the while loop makes no sense, because the while loop executes so fast that it is not possible to actually stop it while it is running, only if the button has already been pressed during the first FOR loop.
    What is the purpose of the two arrays? They don't seem to serve any purpose. Why are you getting the array size with every iteration of the loop? Once, right before the loop should be enough. Index array is resizable, so only one instance is enough. Instead, array to cluster is probably all you need.
    The sequence structure is only needed because you write, and then immediately read from the file. All you probably need is to write to the file and wire the 2D array to the seconds structure. Now we have a data dependency and the sequence structure is no longer needed.
    Can you tell us a little more how you are zooming. Do you want to zoom any of the two graphs and automatically zoom the other accordingly?
    As it currently stands, only the first chart gets data, so zooming the other one seems useless. Once the second chart has data, the VI stops and you can't do much either programmatically. Please explain how you are zooming.
    LabVIEW Champion . Do more with less code and in less time .

  • How to Zoom in or out in a 3D Plot??

     Hi guys,
    I have created a 3D plot with the Creat_Plot_Parametric.VI. (I made a sphere) But I unknown how to move my view through the space. I want to Zoom In and Out. It doesn't have options like the XY Graph.. Someone can give me an advise?
    Solved!
    Go to Solution.

    Which control do you use?
    For 3D plot controls in Modern->Graph->3D Graph, holding Shift and mouse left button then move the mouse up for zoom in and down for zoom out
    For 3D plot controls in Classic->Graph, use mouse wheel to zoom.

  • Centered Zooming In a JScrollPane

    I have a vector drawing being rendered to a JPanel, say 2000x3000 (these being the raw world coordinates). This is contained within a JScrollPane and I can scroll around within it just fine. There is also a zoom factor. Each time I zoom in or out, I resize the JPanel to 2000*zoom by 3000*zoom so I can only scroll around within the limits of the zoomed vector drawing. What I would like to be able to do is to scroll around to any point in the vector drawing, press zoom in/out, and then have the center of the current "viewport" remain the center as the vector drawing is zoomed. This means adjusting the scrollbars values somehow. So far I can't get it to work.
    I can do it without a JScrollPane by simply using absolute drawing coordinates. For example, I can keep an "origin" x and y, say ox & oy, which are maintained as world coordinates. When I am actually drawing to the Graphics context, I can transform everything drawn with the following translation:
    tx = viewportWidth/2 - ox*zoom
    ty = viewportHeight/2 - oy*zoom
    This works great and no matter where I pan in the vector, when I press zoom, the current center remains the center.
    However, adjusting scrollbars to achieve this same behavior has proven difficult so far. Everytime I resize the panel I make sure the scrollbar maximums remain at the absolute size of the vector drawing, in this case 2000 and 3000.
    I would think that I could first do the following when changing the zoom factor, to obtain the center point (in world coordinates) of the currently viewed area:
    double centerx = hsb.getValue() + viewportPixelWidth/2*(1/zoom);
    double centery = vsb.getValue() + viewportPixelHeight/2*(1/zoom);
    Where hsb & vsb are the horizontal and vertical scrollbars. 1/zoom would be the number of world coordinates per pixel according to the current zoom. I'm assuming if I keep the horizontal and vertical scrollbars at the vector drawings maximums (2000 and 3000, respectively), then whatever point the scrollbars are currently at would be the upper left world coordinates of the viewed space in the viewport. And then of course the pixelWidth/2*(1/zoom) would give me the center point, in world coordinates, of the viewed space in the viewport. Then to zoom I would do something like this:
    zoom = newZoom;
    double newx = centerx - viewportWidth/2*(1/zoom);
    double newy = centery - viewportHeight/2*(1/zoom);
    hsb.setValue(newx);
    vsb.setValue(newy);
    Which, off the world coordinates in centerx & centery, should reach back out to the new upper left, which would be half the viewport in pixels multiplied by the new world-coordinates-per-pixel (1/zoom) value. But of course, I'm missing something. I'm no mathematician, so perhaps it's something simple I'm missing, but I can't seem to get the knack of it just yet. I must have something partially correct, because if I slide out near to the lower right and start zooming in (starting at a zoom factor of 1.0; so on down to 0.9, 0.8, etc.), the scrollbars end up adjusting me up and to the left too much but then it hits a point where it correctly zooms on the center for a certain factor, but then slides back around the other way and starts going in that direction too much.
    Also, I realize that if I keep the scrollbars at their maximum world coordinates, and scrolled to the bottom of the vertical scrollbar for example, which would be 3000, then I would still be viewing part of the vector drawing, and thus vsb.getValue() would not be the Y coordinates along the top of the viewed area (ie. the "upper" part in the "upper left" when I'm trying to do my gauging of the center, in world coordinates, of the viewed area off of the "upper left"). So that's messing with my head also. I've tried setting the maximums to values along the lines of 2000-viewportWidth and 3000-viewportHeight as well, but it doesn't seem to have much of an effect. :-(
    If anybody has any insight on how I might achieve this, I would greatly appreciate the help.
    Thanks,
    Charles

    This code snippet may help. In this example m_transform transforms virtual to screen coordinates. getViewport() calls getParent() repeatedly on the component until a JScrollPane is found.
    * Zooms the view in by the specified factor about the specified point.
    * @author      PHeist (12/01)
    public void      zoom
    Point          point,
    double          dFactor
    This slick three step transformation performs a window-viewport zoom around
    the given point. Great! But it's not what we want. Although it looks cool,
    what we really want to do is scale then change the outer viewport, otherwise
    the scrollpane scrollbars will never be in the right place.
    m_transform.translate (newCenter.getX(), newCenter.getY());
    m_transform.scale (dFactor, dFactor);
    m_transform.translate (-newCenter.getX(), -newCenter.getY());
    Point2D centerPoint = new Point2D.Double ();
    try
         m_transform.inverseTransform (point, centerPoint);
    catch (NoninvertibleTransformException nte)
         nte.printStackTrace ();
    m_transform.scale (dFactor, dFactor);
    Dimension newD = new Dimension ((int) (m_model.getWidth() * m_transform.getScaleX()),
         (int) (m_model.getHeight() * m_transform.getScaleY()));
    setPreferredSize (newD);
    setSize (newD);
    JViewport viewport = getViewport ();
    if (null != viewport)
         Point2D newViewPosition = m_transform.transform (centerPoint, centerPoint);
         viewport.setViewPosition (new Point ((int) newViewPosition.getX() - (viewport.getWidth() / 2),
         (int) newViewPosition.getY() - (viewport.getHeight() / 2)));
    repaint ();
    Pete ([email protected], www.compoze.com)

  • Image background and plot in XYGRAPH whith same zoom and panning values

    Hello!.
    I need to write an application that takes an image file (jpeg, bitmap, etc) and applies it inside a labview window.  I need to be able to zoomin on a selected area and pan in every direction whith the same value of plots. 
      Thanks, any help would be much appreciated.
    Solved!
    Go to Solution.

    Daniel ,thanks for the reply but may problem is that the when make zoom in the back picture the above plot zoom no change. I will make to copy programatically the zoom picture in the XYGRAPH zoom. But the zoom in the GRAPHXY (i belive) is maked only whith the graphpalette. This is the real problem
    Thank for the help, sorry by my bad English!.

  • Zoom Radar Graph/Plot

    Hello,
    is there a way to zoom in/out in a radar plot. (http://zone.ni.com/reference/en-XX/help/371361J-01/lvpict/radar_plot/)
    Thanks in advance!

    as the output of this vi is a picture control, you can use the zoomfactor property-node:
    "..\National Instruments\LabVIEW 2014\examples\Graphics and Sound\Picture Plots\Simple Radar Plot.vi"
    ♜♖ LabView 8.6 - LabView 2014 ♖♜

  • Disappearing plot line when zoomed

    I am having a problem with my CNiGraph plot line disappearing when the axes min and max are explicitly defined and they are substantially smaller than they would be if the graph were autoscaled.  I am using measurement studio 8.6.1.465 and NiDaqmx 9.0.2 on windows XP.  I am controlling axis scale either by SetAutoScale() or SetMinMax().  My code is rather large, so I am including snippets of what I am doing below.    
    I noticed a thread with a similar problem at:
    http://forums.ni.com/ni/board/message?board.id=232&message.id=3769&query.id=1275984#M3769 
    Please help!  I have tried window invalidation, turning on/off immediate updates to the graph, setting axes visible/invisible, etc.
    -drew 
    Setup code:
            CNiPlot plot = m_pGraph->GetPlots().Add();
            CNiCursor cursor = m_pGraph->GetCursors().Add();
            //cursor.SetSnapMode(CNiCursor:napPointsOnPlot);
            cursor.SetSnapMode(CNiCursor:napNearestPoint);
            cursor.SetVisible(true);
            cursor.SetPointStyle(CNiCursor:ointCross);
            cursor.SetCrosshairStyle(CNiCursor::CrosshairNone);
            cursor.SetColor(CNiColor(255,255,255));
            cursor.SetPlot(plot);
            CNiAxes axes = m_pGraph->GetAxes();
            CNiAxis xAxis, yAxis;
            xAxis = axes.Item(1);
            yAxis = axes.Item(2);
            yAxis.FormatString = ".##e";
            xAxis.FormatString = "hh:nn:ss";
            CNiColor lineColor(m_plotArray[i]->m_lineColor);
            plot.LineColor = lineColor;
            plot.XAxis.GetTicks().SetMajorGrid(true);
            plot.YAxis.GetTicks().SetMajorGrid(true);
            plot.XAxis.GetTicks().SetMajorGridColor(CNiColor(60,60,60));
            plot.YAxis.GetTicks().SetMajorGridColor(CNiColor(60,60,60));
        m_pGraph->ChartLength = m_graphLength;
        m_pGraph->ChartStyle = CNiGraph::ChartStrip;
        m_pGraph->SetImmediateUpdates(true);
    Graphing:
    CNiReal64Matrix newData;
    m_pGraph->GetPlots().Item(i+1).ChartXY(newData);
    m_pGraph->GetCursors().Item(i+1).SetPosition(newData(0,maxCol),
                                                                        newData(1,maxCol));
    Solved!
    Go to Solution.

    I managed to fix this problem, noticing that panning the graph caused the line to redraw properly.  I added a very small amount of 'jitter' to the X axis each time after ChartXY is called. Since autoscale mode seems to refresh just fine, i only introduce jitter if the axis min/max is set explicitly:
    if (!m_pGraph->Axes.Item("XAxis").GetAutoScale()){
            static double plusMinus = 1.0;
            m_pGraph->Axes.Item("XAxis").SetMinMax(m_pGraph->Axes.Item("XAxis").GetMinimum()+(plusMinus*0.000000001),
                                                    m_pGraph->Axes.Item("XAxis").GetMaximum()+(plusMinus*0.000000001));
            plusMinus *= -1.0;
    It seems this is a bug in the graph control since there is no problem with the cursor drawing properly and I should not need to write code like this to keep my plot lines from disappearing?
    -drew

  • How to make JScrollPane scroll faster?

    Hi,
    I have tried to develop on a program to zoom in or zoom out the image�a graph which is plotted using the method draw from Graphics2D. In the program, I am given about 1000 points, which are supposed to be plotted one by one suing the draw method, which later form a graph.
    I have put the JPanel, where the output of the graph is displayed, into a JscrollPane to enable scrolling of large image. However, when I am trying to scroll the image, it happen to me that the scrolling is extremely slow. When I click at the scrolling bar to scroll down the image, it take some time before the image is scrolled down.
    My doubt will be is there any method to make the scrolling on the JscrollPane to become faster?does this involve double buffering?
    Thank you.

    This may not be the answer to your problem, but I thought I would throw it out there. One reason it might scroll slowly is because by default the JScrollPane only moves 1 pixel for every click of the scroll bar. You can adjust this by having your JPanel implement the Scrollable interface.
    Here is a code sample -
    // implement Scrollable interface
    public Dimension getPreferredScrollableViewportSize()
    return getPreferredSize();
    public int getScrollableBlockIncrement( Rectangle r, int orientation, int direction )
    return 10;
    public boolean getScrollableTracksViewportHeight()
    return false;
    public boolean getScrollableTracksViewportWidth()
    return false;
    public int getScrollableUnitIncrement( Rectangle r, int orientation, int direction )
    return 10;
    Whatever number you have your getScrollableUnitIncrement and getScrollableBlockIncrement methods return is how many pixels your component will scroll for each click of the scroll bar.
    Give this a try.

  • Problem with jpanel zooming

    friends,
    i have a jpanel with image as background and i am adding jlabels dynamically to the jpanel. i have to move the jlabel on the image so i added mouse listener to jlabel. now i want to add zooming functionality to the jpanel.
    now if zoom out jpanel everything works well but jlabel mouse listener location is not changing so if i click on jlabel its not activating listener - i need to click outside of jlabel/jpanel (its original location when its 100% zoom) to activate the listener. how can i correct this ?
    thanks in advance
    i will add example after i cutdown (its part of big application)

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.net.*;
    import java.util.ArrayList;
    import java.util.List;
    import javax.imageio.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.border.*;
    public class PP3 extends JFrame {
        private JButton btnStart;
        private JButton btnStop;
        private JLabel logoLabel;
        private JSlider zoom;
        private JPanel mainPanel;
        private JPanel btnPanel;
        private JScrollPane jspane;
        private BackPanel3 secondPanel;
        private boolean start = false;
        public PP3() {
            initComponents();
            setVisible(true);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
        private void initComponents() {
            logoLabel = new JLabel();
            mainPanel = new JPanel();
            btnPanel = new JPanel();
            btnStart = new JButton();
            btnStop = new JButton();
            zoom = new JSlider(0,100,100);
            setBackground(Color.white);
            setLayout(new BorderLayout());
            mainPanel.setBackground(Color.white);
            mainPanel.setBorder(new EtchedBorder());
            mainPanel.setPreferredSize(new Dimension(650, 600));
            mainPanel.setLayout(new CardLayout());
            jspane = new JScrollPane(getSecondPanel());
            mainPanel.add(jspane,"Second Panel");
            add(mainPanel, BorderLayout.CENTER);
            btnPanel.setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(2,2,2,2);
            gbc.weighty = 1.0;
            gbc.gridwidth = gbc.REMAINDER;
            btnPanel.setBackground(Color.white);
            btnPanel.setBorder(new EtchedBorder());
            btnPanel.setPreferredSize(new Dimension(150, 600));
            btnStart.setText("Start Labelling");
            btnPanel.add(btnStart, gbc);
            btnStart.setEnabled(true);
            btnStart.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent ae){
                    start = true;
                    btnStart.setEnabled(false);
                    btnStop.setEnabled(true);
                    if(secondPanel != null){
                        secondPanel.setStart(start);
                        Cursor moveCursor = new Cursor(Cursor.TEXT_CURSOR);
                        secondPanel.setCursor(moveCursor);
            btnStop.setText("Done Labelling");
            btnPanel.add(btnStop, gbc);
            btnStop.setEnabled(false);
            btnStop.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent ae){
                    start = false;
                    btnStart.setEnabled(true);
                    btnStop.setEnabled(false);
                    if(secondPanel != null){
                        secondPanel.setStart(start);
                        Cursor moveCursor = new Cursor(Cursor.DEFAULT_CURSOR);
                        secondPanel.setCursor(moveCursor);
            final JLabel zoomLabel = new JLabel("Zoom");
            zoomLabel.setBorder(BorderFactory.createEtchedBorder());
            gbc.weighty = 0;
            gbc.weightx = 1.0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            btnPanel.add(zoomLabel, gbc);
            btnPanel.add(zoom, gbc);
            zoom.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent ce) {
                    JSlider source = (JSlider)ce.getSource();
                    if(secondPanel != null) {
                        secondPanel.setZoomFactor((double)source.getValue());
                        zoomLabel.setText("Zoom = " + source.getValue()/100.0);
            String id = "<html><nobr>show label</nobr><br><center>locations";
            JCheckBox check = new JCheckBox(id, secondPanel.showLocations);
            check.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    secondPanel.toggleShowLocations();
            gbc.weighty = 1.0;
            gbc.fill = GridBagConstraints.NONE;
            btnPanel.add(check, gbc);
            add(btnPanel, BorderLayout.EAST);
            pack();
        public JPanel getSecondPanel() {
            if(secondPanel == null) {
                secondPanel = new BackPanel3("images/cougar.jpg", 850, 1100);
                secondPanel.setStart(false);
            return secondPanel;
        public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new PP3();
    class BackPanel3 extends JPanel implements MouseListener,
                                               MouseMotionListener{
        String imgPath = null;
        BufferedImage image;
        private int width = 0;
        private int height = 0;
        private double zoomFactor = 1.0;
        private boolean start = false;
        private boolean same = false;
        Cursor hourglassCursor = new Cursor(Cursor.MOVE_CURSOR);
        // choose a declaration according to your java version
        List<JLabel> labels;     // declaration for j2se 1.5+
    //    List labels;           // j2se 1.4-
        JLabel lastSelected;
        boolean showLocations;
        JLabel selectedLabel;
        boolean dragging;
        Point offset;
        int count = 0;
        private static String SELECTED = "selected";
        public BackPanel3(String path, int width, int height){
            setLayout(null);
            this.width = width;
            this.height = height;
            setPreferredSize(new Dimension(width,height));
            addMouseListener(this);
            addMouseMotionListener(this);
            // chose an instantiation according to your java version
            labels = new ArrayList<JLabel>();    // j2se 1.5+
    //        labels = new ArrayList();          // j2se 1.4-
            lastSelected = new JLabel();
            lastSelected.putClientProperty(SELECTED, Boolean.FALSE);
            showLocations = true;
            dragging = false;
            offset = new Point();
            this.imgPath = path;
            setImage();
        public void setImage(){
            try{
                image = getImage(imgPath);
            }catch(Exception e){
                System.out.println(" (init) ERROR: " + e);
                e.printStackTrace();
        public void setStart(boolean flag){
            start = flag;
        public void setZoomFactor(double zoom){
            zoomFactor = (zoom/100);
            setPreferredSize(new Dimension((int)(850*zoomFactor), (int)(1100*zoomFactor)));
            repaint();
            revalidate();
        public double getZoomFactor(){
            return zoomFactor;
        public void toggleShowLocations() {
            showLocations = !showLocations;
            repaint();
        public void mouseClicked(MouseEvent e) {
            if(start){
                JLabel msgLabel = new JLabel("Test " + count++);
                this.add(msgLabel);
                Dimension d = msgLabel.getPreferredSize();
                msgLabel.setBounds(e.getX(), e.getY(), d.width, d.height);
                labels.add(msgLabel);
                msgLabel.putClientProperty(SELECTED, Boolean.FALSE);
                return;
        public void mousePressed(MouseEvent e) {
            Point p = e.getPoint();
            for(int j = 0; j < labels.size(); j++) {
                JLabel label = (JLabel)labels.get(j);
                Rectangle bounds = label.getBounds();
                AffineTransform at =
                    AffineTransform.getScaleInstance(zoomFactor, zoomFactor);
                Shape xs = at.createTransformedShape(bounds);
                if(xs.contains(p)) {
                    selectedLabel = label;
                    Rectangle r = xs.getBounds();
                    offset.x = p.x - r.x;
                    offset.y = p.y - r.y;
                    dragging = true;
                    break;
        public void mouseReleased(MouseEvent e) {
            dragging = false;
        public void mouseDragged(MouseEvent me){
            if(dragging) {
                Rectangle bounds = selectedLabel.getBounds();
                AffineTransform at =
                    AffineTransform.getScaleInstance(1.0/zoomFactor, 1.0/zoomFactor);
                Point2D p = at.transform(me.getPoint(), null);
                int x = (int)(p.getX() - offset.x);
                int y = (int)(p.getY() - offset.y);
                selectedLabel.setLocation(x, y);
                repaint();
        public void mouseMoved(MouseEvent me){
            if(labels.size() == 0)
                return;
            Point p = me.getPoint();
            boolean hovering = false;
            boolean selectionChanged = false;
            for(int j = 0; j < labels.size(); j++) {
                final JLabel label = (JLabel)labels.get(j);
                Rectangle r = label.getBounds();
                AffineTransform at =
                    AffineTransform.getScaleInstance(zoomFactor, zoomFactor);
                Shape scaledBounds = at.createTransformedShape(r);
                if(scaledBounds.contains(p)) {
                    hovering = true;
                    if(!((Boolean)label.getClientProperty(SELECTED)).booleanValue()) {
                        label.putClientProperty("selected", Boolean.TRUE);
                        setCursor(hourglassCursor);
                        if(lastSelected != label)  // for only one JLabel
                            lastSelected.putClientProperty(SELECTED, Boolean.FALSE);
                        lastSelected = label;
                        selectionChanged = true;
                        break;
            // reset lastSelected when there is no selection/hovering
            if(!hovering &&
                ((Boolean)lastSelected.getClientProperty(SELECTED)).booleanValue()) {
                lastSelected.putClientProperty(SELECTED, Boolean.FALSE);
                setCursor(Cursor.getDefaultCursor());
                selectionChanged = true;
            if(selectionChanged)
                repaint();
        public void mouseEntered(MouseEvent e) { }
        public void mouseExited(MouseEvent e) { }
        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.scale(zoomFactor, zoomFactor);
            g2.drawImage(image, 0, 0, this);
            if(showLocations) {
                // show bounds of the actual JLabel children
                // components as they exist on this component
                AffineTransform at = AffineTransform.getScaleInstance(1.0/zoomFactor,
                                                                      1.0/zoomFactor);
                g2.setPaint(Color.blue);
                Component[] c = getComponents();
                for(int j = 0; j < c.length; j++)
                    g2.draw(at.createTransformedShape(c[j].getBounds()));
            // show selected label
            g2.setPaint(Color.red);
            for(int j = 0; j < labels.size(); j++) {
                JLabel label = (JLabel)labels.get(j);
                if(((Boolean)label.getClientProperty("selected")).booleanValue()) {
                    g2.draw(label.getBounds());
                    break;
        protected BufferedImage getImage(String path){
            try{
                URL imgURL = BackPanel3.class.getResource(path);
                if (imgURL == null &&
                       (path.indexOf(":\\") > 0 || path.indexOf(":/") > 0))
                    imgURL = new URL("file:///"+path);
                return getImage(imgURL);
            }catch(MalformedURLException mue){
                System.out.println("error "+mue);
            return null;
        protected BufferedImage getImage(URL url){
            try{
                if (url != null) {
                    BufferedImage source = ImageIO.read(url);
                    double xScale = (double)width / source.getWidth();
                    double yScale = (double)height / source.getHeight();
                    double scale = Math.min(xScale, yScale);
                    int w = (int)(scale*source.getWidth());
                    int h = (int)(scale*source.getHeight());
                    BufferedImage scaled = new BufferedImage(w, h, source.getType());
                    Graphics2D g2 = scaled.createGraphics();
                    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                        RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                    // scales faster than getScaledInstance
                    AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
                    g2.drawRenderedImage(source, at);
                    g2.dispose();
                    return scaled;
                }else{
                    return null;
            }catch(IOException ioe){
                System.out.println("read error "+ioe);
                return null;
    }

  • One more nugget: Chart zoom with the "Mouse Over" effect

    Hello all.
    Just read my signature first, it might explain a lot. I do not intend to compete with Darren and I don't think this "nugget" (at least it supposed to be one) will amaze any of the LV veterans and this forum is rich of them. But maybe it will bring some new ideas to some of you or maybe it will be useful for some LV beginners (like me). It is very likely, my code will have some lapses, but please be gentle pointing that out to me. If you feel a need, you can always optimize the code and develope it further. Just don't forget to share!
    So back to the point.
    I am developing a project using LV. In my program there is a waveform chart which has to show 4 plots. Depending on the length of the X Scale, it sometimes gets hard to see the plots clearly because of their density.So I decided that I need a tool, which would zoom the chart in. And this is what I have came up with after a few "Google" searches to check which part of the bike is already invented and also a bit of programming by myself. 
    Maybe you guys (at least the veterans) know the BetterVIEW Consulting LV example where they have implemented the Mouse Over effect. So a part of their example has been used in this tool and part of the credit must go to them. I thank them a lot
    This tool uses a cluster and its property of visibility to show/hide the cluster depending on if the current position of the mouse cursor is in the desired range or not. The program also gets the image of the chart and returns the subset of the image. The subset is taken for the area arounf the mouse cursor. So if you move the mouse, the zoomed in area will also chage in response. After that, the subset of the image is zoomed in for better view. 
    The user might chage the zoom factor during the execution. Also it is possible to turn the zoom option On or Off if you don't wish to see it for the moment. 
    This is how the front panel looks like:
    And this is the image of the block diagram (see the attached files for the vi, the VI Snippet tool distorts the code too much, so I haven't added it):
    I haven't found anything the same in the forum. Yet I'm a newbie here and I don't have that much experience surfing it. If it wouldn't be something new (in the forum, not necessarily to some of you personally), just ignore the thread. I hope this was worth your time and your attention. 
    Good coding
    Message Edited by Giedrius.S on 02-11-2010 12:46 PM
    While evaluating my code please have in mind that I am a LV novice. Therefore sometimes my code might violate some coding rules that I have to learn about myself. But how else could I do that...
    Chart zoom with "Mouse Over" effect
    Attachments:
    Zoom.vi ‏198 KB
    Mouse_pos.vi ‏20 KB
    Check_pos.vi ‏18 KB

    Very nice Giedrius.
    It takes guts to "step up to the chalk board" so I will do what i can to give you some ideas to think about. This is similar to the type of feedback I offer durring our in-house code reviews.
    1) The floating property nodes outside the loop are not sequenced by wires so they could execute after the loop starts. Sometimes this could cause weird errors. Seq with the error cluster.
    2) Property nodes can be re-sized so you can apply more than one property setting in the same call. Property node have to execute in the UI thread (which is single threaded) so using a single nodes will force a single context switch rather than one for each.
    3) Setting the same property repeatedly in a loop just burns CPU. THe Scale min for both X an Y can be moved outside the loop ?
    4) THe Wait Until Next ms" function does not get used in any of my code. It is not a way to get a fixed wait but rather a random wait. If you code completes 1 ms after the next multiple, the delay is double less 1 ms. If you have multiple loops using them and it f the delay for each are not unique prime numbers, then the "Wait until next ms multiple" is a good (cough cough) way of getting them all to wake up at the same time and fight for the CPU.
    5)An Event Struture to monitor mouse enter/leave and mouse move (this would have to be a sepearte loop) is easier on the CPU than polling.
    6) Is that math in the case to handle the Chart position on the FP? If so then using the property nodes for the chart to find its postion will let you code adapt to GUI changes.
    7) Right to left wires are not well recieved.
    8) A Bundle by Name is prefered over a "Bundle" since it is self documenting. I know the Picture function so I can see that is the rectangle you are specifying but reader not famliar with that function would not be able to "READ" the code without poking at it.
    9) THe event structure would also help with setting the Zoom factor. Only poke it when you have to.
    That is all that comes to mind at the moment.
    Again thank you!
    Ben
    Ben Rayner
    I am currently active on.. MainStream Preppers
    Rayner's Ridge is under construction

  • Charts: how do I determine when the mouse is in the plot area

    I'm trying to implement logic that will do the following:
    Panning plot within plot display area by clicking and dragging mouse
    If the user clicks and drags in the chart plot area (the region where the chart plot actually displays, not including the axes, legends, titles, etc.), I want to be able to provide the effect of panning the plot (e.g. similar to grabbing and dragging a map in Google maps) within the plot display. This makes the most sense, of course, if the user has zoomed in to some level and the entire plot is no longer fully visible within the display.
    Zooming on a plot
    If the user places the mouse somewhere in the chart plot area and uses their mouse wheel, I want to be able to provide the effect of zooming in and out of the plot. The plot area itself must remain at its original size, just the representation of the plot needs to simulate the effect of being zoomed in or out on.
    Thoughts, suggestions, ...
    To make the zoom and pan effect, my thought was to adjust the axes bounds as appropriate to simulate these effects. The trick for some of what I'm planning on doing is finding out where the mouse is in the plot area (not the whole chart) so that I can find the x,y offsets from the plot origin (which appears to be in the upper left - at the chart level anyway). For panning, I don't think I care what the offset is, just that it's within the plot. For zooming, I may need to know where the mouse is in the plot so that the zooming could be centered on that location in the plot. This makes me think that it would also be helpful to find out how to translate the mouse x,y pixel position to a corresponding x,y value in the plot data domain.
    I've been experimenting with attaching event handlers to detect various mouse actions and what information can be gleaned from these events. So far I have not found anything that allows me to determine the bounds of the plot region in the overall chart. I can get the mouse x,y position, but I don't know where it is in relation to the plot area bounds. I don't want to initiate a pan of a plot if the user happens to drag their mouse somewhere outside the plot area (i.e. over an axis, legend, etc.). Also, it would not make sense to start a zoom on the chart unless the mouse is over the plot.
    Please let me know if this seems to be a reasonable approach, and if not, please suggest any ideas for alternatives. Any help, ideas and suggestions regarding how to solve these issues and/or determine this information would be welcome.

    I experimented a bit and it seems the plot-content is the Group containing, well, the content of the plot. So in a line chart it's the smallest rectangle containing all the lines and the graphic at the data point (little circles, by default). What you probably need instead is the chart-plot-background.
    Here's a quick example of a panning chart. There are probably better ways to manage the mouse dragging (it behaves somewhat badly if you drag out of the plot area and then back in, for example) but it gives you the basic idea. My original idea of adding a mouse directly to the plot area failed as the event doesn't get propagated to the plot region if you click on part of the plot content (a line, for example).
    import java.util.Random;
    import javafx.application.Application;
    import javafx.beans.property.DoubleProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.geometry.Point2D;
    import javafx.scene.Scene;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart.Data;
    import javafx.scene.chart.XYChart.Series;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.Region;
    import javafx.stage.Stage;
    public class PanningChart extends Application {
      @Override
      public void start(Stage primaryStage) {
        final NumberAxis xaxis = new NumberAxis("x", 0, 10, 1);
        final NumberAxis yaxis = new NumberAxis("y", 0, 100, 10);
        final LineChart<Number, Number> chart = new LineChart<>(xaxis, yaxis);
        chart.setAnimated(false);
        chart.setData(createData());
        final Region plotArea = (Region) chart.lookup(".chart-plot-background");
        final DoubleProperty lastMouseX = new SimpleDoubleProperty();
        final DoubleProperty lastMouseY = new SimpleDoubleProperty();
        chart.setOnMousePressed(new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent event) {
            final double x = event.getX();
            final double y = event.getY();
            if (plotArea.getBoundsInParent().contains(new Point2D(x, y))) {
              lastMouseX.set(x);
              lastMouseY.set(y);
        chart.setOnMouseDragged(new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent event) {
            final double x = event.getX();
            final double y = event.getY();
            if (plotArea.getBoundsInParent().contains(new Point2D(x, y))) {
              moveAxis(xaxis, x, lastMouseX);
              moveAxis(yaxis, y, lastMouseY);
        final BorderPane root = new BorderPane();
        root.setCenter(chart);
        primaryStage.setScene(new Scene(root, 600, 400));
        primaryStage.show();
      private void moveAxis(NumberAxis axis, double mouseLocation,
          DoubleProperty lastMouseLocation) {
        double scale = axis.getScale();
        double delta = (mouseLocation - lastMouseLocation.get()) / scale;
        axis.setLowerBound(axis.getLowerBound() - delta);
        axis.setUpperBound(axis.getUpperBound() - delta);
        lastMouseLocation.set(mouseLocation);
      private ObservableList<Series<Number, Number>> createData() {
        final ObservableList<Data<Number, Number>> data = FXCollections
            .observableArrayList();
        final Random rng = new Random();
        for (int x = 0; x <= 10; x++) {
          data.add(new Data<Number, Number>(x, rng.nextDouble() * 100));
        return FXCollections.singletonObservableList(new Series<Number, Number>(data));
      public static void main(String[] args) {
        launch(args);
    998038 wrote:On a slightly different (but related) subject, where can I find an up-to-date source of information that describes the IDs and class names that JavaFX uses? I assume the ".plot-content" is pertaining to the ID of the chart plot area (or plot "child" of the chart?). Where can I find the names of the various objects that can be "looked up"?I generally try to avoid lookups as they feel a bit fragile. However occasionally there seems to be no other way, as in this case. The [url http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html]CSS reference guide documents the css class substructure of each Node type.

Maybe you are looking for