JScrollPane的“跳转"开始使用滚动条时 [英] JScrollPane "jumping" when scrollbars start being used

查看:71
本文介绍了JScrollPane的“跳转"开始使用滚动条时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,下面是一长段示例代码,但这是问题所在:

Sorry, this is a long piece of sample code below, but here's the issue:

我有一个正在积极画画的背景(我可能很聪明,只画了一次就可以缩放,但这也显示了问题).

I have a background that I'm actively drawing (I could probably be smart and draw it once and just scale it, but this shows the problem just as well).

您可以使用鼠标滚轮来放大和缩小图像.

You can use the mouse wheel to zoom in and out on the image.

想法是进行谷歌地图"缩放,使其在鼠标指针下方缩放.我注意到的是,直到图像足够大到可以同时使用两个滚动条时,它似乎才真正起作用.在此之前,您只会使图像变大,但会锁定到原点.

The idea is to do a "google map" zoom where it zooms under the mouse pointer. What I've noticed is that it doesn't seem to actuall behave until the image is big enough to use both scroll bars. Until then, you get the image simply getting bigger, but locked to the origin.

正确"的行为应该是移动视图位置,即使滚动条尚未被超大图像使用.

The "correct" behavior should be that the viewposition is moved, even though the scrollbars aren't yet being utilized by an oversized image.

我不确定如何解决这个问题(或者这是否正确和预期),而不在图像后面绘制更大的背景,以至于它不能填满视口.

I'm not sure how to get around this (or if this is correct and expected) without drawing a much larger background behind the image so it more than fills the viewport.

由于(我认为)同一问题,一个或另一个滚动条啮合后会跳".

It "jumps" after one or the other scroll bars engages due to (I think) the same issue.

有想法吗?

package com.hostigr.raw.io.client.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;

public class TestFrame extends JFrame {

    public static void main(String[] arg) {
            new TestFrame();
    }

    public TestFrame() {
        initComponents();
        setVisible(true);
    }

    private void initComponents() {
        setLayout(new BorderLayout());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 600);
        setPreferredSize(new Dimension(600, 600));

        add(new TopPanel());

    }

    private class TopPanel extends JPanel {
        JScrollPane scrollPane;

        public TopPanel() {
            setPreferredSize(new Dimension(500,500));
            scrollPane = new JScrollPane(new InteriorPanel());
            scrollPane.setPreferredSize(new Dimension(500,500));
            scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(10,490));
            scrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(490,10));
            scrollPane.setWheelScrollingEnabled(false);
            scrollPane.setHorizontalScrollBarPolicy(
                    JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
            scrollPane.setVerticalScrollBarPolicy(
                    JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            add(scrollPane);

        }
    }

    private class InteriorPanel extends JPanel {
        private double scale = 10.0;
        private final double scaleModifier = 0.1;
        private final int width = 10;
        private Point loc = new Point(0,0);
        private final int SIZE = 10;

        public InteriorPanel() {
            super(true);
            setPreferredSize(new Dimension((int)(scale * width * SIZE),
                    (int)(scale * width * SIZE)));
            this.addMouseWheelListener(new MapMouseWheelListener());
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2D = (Graphics2D) g;
            g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
            g2D.scale(scale,scale);

            for (int row = 0; row <= SIZE; row++) {
                for (int col = 0; col < SIZE; col++) {
                    if ((col + row) % 2 == 0) {
                        g2D.setColor(Color.white);
                    } else {
                        g2D.setColor(Color.black);
                    }
                    g2D.fillRect(col * width, row * width, width, width);
                }
            }

        }

        private void incrementScale(int notches) {
            double modifier = 0;
            double prevScale = scale;
            if (notches != 0) {
                modifier = 1.0 + -notches / Math.abs(notches) * scaleModifier;
            }
            scale = scale * Math.pow(modifier, Math.abs(notches));
            /*if (scale * width < 1) {
                scale = 1.0/width;
            } else if (scale * width * 3 > parentHeight || scale * width * 3 > parentWidth) {
                if (parentHeight > parentWidth) {
                    scale = parentWidth / 3.0 / width;
                } else {
                    scale = parentHeight / 3.0 / width;
                }
            } else if (scale * width * SIZE < parentWidth) {
                scale = parentWidth / (double)SIZE / width;
            } else if (scale * width * SIZE < parentHeight) {
                scale = parentHeight / (double)SIZE / width;
            }*/

            this.repaint();
            setPreferredSize(new Dimension((int)(scale * width * SIZE),
                    (int)(scale * width * SIZE)));

            JViewport viewport = ((JViewport)(getParent().getParent().getComponent(0)));
            Point orig = viewport.getViewPosition();
            viewport.setViewPosition(new Point(
                    orig.x - (int)Math.round(loc.x*(1 - scale/prevScale)),
                    orig.y - (int)Math.round(loc.y*(1 - scale/prevScale))));
            System.out.println(orig + "\n  " + loc + "\n  " + (1 - scale / prevScale));
            revalidate();
        }

        private class MapMouseWheelListener implements MouseWheelListener {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                loc = e.getPoint();
                incrementScale(e.getWheelRotation());
            }
        }
    }
}

推荐答案

对我来说就像JViewPort#scrollRectToVisible(Rectangle r)一样

     viewport.scrollRectToVisible(new Rectangle(new Point(
     orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
     orig.y - (int) Math.round(loc.y * (1 - scale / prevScale)))));

编辑并使用正确的Swing重绘规则,则您的codeBlock必须以revalidate(); + repaint();

EDIT and with correct Swing repaint's rulles, then yout codeBlock must ends with revalidate(); + repaint();

        setPreferredSize(new Dimension((int) (scale * width * SIZE), 
        (int) (scale * width * SIZE)));
        JViewport viewport = ((JViewport) (getParent().getParent().getComponent(0)));
        Point orig = viewport.getViewPosition();
        /*viewport.setViewPosition(new Point(
                orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
                orig.y - (int) Math.round(loc.y * (1 - scale / prevScale))));*/
        viewport.scrollRectToVisible(new Rectangle(new Point(
                orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
                orig.y - (int) Math.round(loc.y * (1 - scale / prevScale)))));
        System.out.println(orig + "\n  " + loc + "\n  " + (1 - scale / prevScale));

        revalidate();
        repaint();

这篇关于JScrollPane的“跳转"开始使用滚动条时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆