JScrollPane - масштаб относительно положения мыши

Мне нужно рассчитать новую позицию окна просмотра при увеличении изображения.

Пользовательский интерфейс построен следующим образом:

  • ImagePanel рисует изображение
  • ImagePanelWrapper - это JPanel, оборачивающая вокруг imagePanel
  • JScrollPane содержит ImagePanelWrapper

При увеличении или уменьшении коэффициент масштабирования ImagePanel изменяется, и предпочтительный размер ImagePanel пересчитывается. Поэтому изображение на этой панели перемещается, даже если ImagePanel остается в той же точке просмотра.

Следующие методы вызываются, когда пользователь удерживает нажатой клавишу CTRL и использует колесо мыши. Данная точка является местоположением курсора, предоставленным MouseWheelListener. Благодаря функциональности этих методов изображение уже остается в том же верхнем левом положении при увеличении или уменьшении.

Проблема в том, что я просто не могу понять, как двигаться относительно мыши, как, например, Paint.NET. Есть идеи?

/**
 * 
 */
public void zoomOut(Point point) {
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 0.9f);
    Point pos = this.getViewport().getViewPosition();

    int newX = (int) (pos.x * 0.9f);
    int newY = (int) (pos.y * 0.9f);
    this.getViewport().setViewPosition(new Point(newX, newY));

    this.imagePanel.revalidate();
    this.imagePanel.repaint();
}

/**
 * 
 */
public void zoomIn(Point point) {
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 1.1f);
    Point pos = this.getViewport().getViewPosition();

    int newX = (int) (pos.x * 1.1f);
    int newY = (int) (pos.y * 1.1f);
    this.getViewport().setViewPosition(new Point(newX, newY));

    this.imagePanel.revalidate();
    this.imagePanel.repaint();
}

2 ответа

Решение

Если эти предположения верны:

  • Указанная точка указана относительно левого верхнего угла области просмотра.
  • Размеры области просмотра меньше, чем у базовой панели изображений.

Затем область просмотра можно отрегулировать так, чтобы курсор находился над той же точкой на изображении до и после операции масштабирования, если перемещать следующим образом:

 /**
 * 
 */
public void zoomOut(Point point) {
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 0.9f);
    Point pos = this.getViewport().getViewPosition();

    int newX = (int)(point.x*(0.9f - 1f) + 0.9f*pos.x);
    int newY = (int)(point.y*(0.9f - 1f) + 0.9f*pos.y);
    this.getViewport().setViewPosition(new Point(newX, newY));

    this.imagePanel.revalidate();
    this.imagePanel.repaint();
}

/**
 * 
 */
public void zoomIn(Point point) {
    this.imagePanel.setZoom(this.imagePanel.getZoom() * 1.1f);
    Point pos = this.getViewport().getViewPosition();

    int newX = (int)(point.x*(1.1f - 1f) + 1.1f*pos.x);
    int newY = (int)(point.y*(1.1f - 1f) + 1.1f*pos.y);
    this.getViewport().setViewPosition(new Point(newX, newY));

    this.imagePanel.revalidate();
    this.imagePanel.repaint();
}

Вот математика для полноты картины:

Вы должны быть в состоянии получить местоположение указателя мыши, используя point.x а также point.y - обратитесь к Point документация здесь. В соответствии с MouseMotionEvent документация здесь, point.x а также point.y относительно компонента под мышью (JScrollPane).

Вы можете включить эти значения в свой расчет. Это то, что вы искали?

Другие вопросы по тегам