11

JScrollPane のコンポーネントよりも大きなビューポートを持つ JScrollPane を作成すると、そのコンポーネントが左上に表示されます。

コンポーネントを中央に表示するようにこの動作を変更する方法はありますか?

以下のプログラム例。


明確化:

(幅、高さ) = (cw、ch) のコンポーネントがあります。

(幅、高さ) = (vw、vh) のビューポートを持つ JScrollPane があります。

コンポーネントが大きくなったり小さくなったりすることがあります。スクロールバーを使用して、ビューポートの中心点に対してコンポーネントの中心点を配置する方法が欲しいので、コンポーネントの寸法の一方または両方がビューポートよりも小さい場合、コンポーネントはビューポートの中心に表示されます。

デフォルトのスクロール区画の動作では、ビューポートの左上隅を基準にしてコンポーネントの左上隅が配置されます。

私が求めているのは、基準点を変更する方法だけです。デフォルトの JScrollPane でこれを行うのがどれほど簡単かはわかりません。簡単でない場合は、できることを学び、別のアプローチを考えます。


package com.example.test.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SimpleScroller extends JFrame {
    static class Thingy extends JPanel
    {
        private double size = 20.0;

        @Override public Dimension getPreferredSize() {
            int isize = (int) this.size;
            return new Dimension(isize, isize);
        }
        @Override protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            int[] x = {0, 100, 100, 0, 0, 75, 75, 25, 25, 50};
            int[] y = {0, 0, 100, 100, 25, 25, 75, 75, 50, 50};

            Graphics2D g2d = (Graphics2D) g;
            AffineTransform at0 = g2d.getTransform();
            g2d.scale(size/100, size/100);
            g.drawPolyline(x, y, x.length);
            g2d.setTransform(at0);
        }
        public void setThingySize(double size) { 
            this.size = size;
            revalidate();
            repaint();
        }
        public double getThingySize() { return this.size; }
    }

    public SimpleScroller(String title) { 
        super(title);
        final Thingy thingy = new Thingy();
        setLayout(new BorderLayout());      
        add(new JScrollPane(thingy), BorderLayout.CENTER);

        final SpinnerNumberModel spmodel = 
            new SpinnerNumberModel(thingy.getThingySize(),
                10.0, 2000.0, 10.0);
        spmodel.addChangeListener(new ChangeListener() {
            @Override public void stateChanged(ChangeEvent e) {
                thingy.setThingySize((Double) spmodel.getNumber());
            }           
        });
        add(new JSpinner(spmodel), BorderLayout.NORTH);
    }
    public static void main(String[] args) {
        new SimpleScroller("simple scroller").start();
    }
    private void start() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }
}
4

4 に答える 4

12
  1. JPanelaをスクロールペインに入れる
  2. パネルのレイアウトを に設定しますGridBagLayout
  3. 制約なしで 1 つのコンポーネントをパネルに配置します。中心になります。

これはNested Layout Exampleで使用されている手法で、赤/オレンジのイメージを親の中央に配置します。

于 2012-05-07T17:35:54.830 に答える
4

追加したJPanelJScrollPaneを追加しただけTHINGY JPanelです。これがあなたが望んでいたものであることを願っています:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SimpleScroller extends JFrame {
    static class Thingy extends JPanel
    {
        private double size = 20.0;

        @Override public Dimension getPreferredSize() {
            int isize = (int) this.size;
            return new Dimension(isize, isize);
        }
        @Override protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            int[] x = {0, 100, 100, 0, 0, 75, 75, 25, 25, 50};
            int[] y = {0, 0, 100, 100, 25, 25, 75, 75, 50, 50};

            Graphics2D g2d = (Graphics2D) g;
            AffineTransform at0 = g2d.getTransform();
            g2d.scale(size/100, size/100);
            g.drawPolyline(x, y, x.length);
            g2d.setTransform(at0);
        }
        public void setThingySize(double size) { 
            this.size = size;
            revalidate();
            repaint();
        }
        public double getThingySize() { return this.size; }
    }

    public SimpleScroller(String title) { 
        super(title);
        final Thingy thingy = new Thingy();
        setLayout(new BorderLayout());  
        JPanel panel = new JPanel();
        panel.add(thingy);
        JScrollPane scroll = new JScrollPane();
        scroll.setViewportView(panel);  
        add(scroll, BorderLayout.CENTER);

        final SpinnerNumberModel spmodel = 
            new SpinnerNumberModel(thingy.getThingySize(),
                10.0, 2000.0, 10.0);
        spmodel.addChangeListener(new ChangeListener() {
            @Override public void stateChanged(ChangeEvent e) {
                thingy.setThingySize((Double) spmodel.getNumber());
            }           
        });
        add(new JSpinner(spmodel), BorderLayout.NORTH);
    }
    public static void main(String[] args) {
        new SimpleScroller("simple scroller").start();
    }
    private void start() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }
}

出力は次のとおりです。

シンプルなスクローラー

于 2012-05-07T17:49:42.117 に答える
3

両方のコメントを受け入れますが

はい...私は本当にそれを任意に配置したいのですが

がある

JViewportでのちらつきやジャンプを回避するための重要な方法

JViewport.setScrollMode(JViewport.BLIT_SCROLL_MODE); JViewport.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); JViewport.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);

  • GlassPaneを使用します(目的のポイントまたは/および寸法に配置するための設定は非常に簡単です)

少なくとも直接ではなく、JViewportにペイントしたくありません。実際のコードは、私の例のようにJPanelからサブクラス化されたコンポーネントですが、他のGUI要素も含まれています。

  • JXLayer(Java6)またはJLayer(Java7)に実装されたJXLayerのメソッドの一部を直接使用できます

  • 難しすぎるかもしれませんが、すべての場合で、JLabelで何でもオーバーレイできます

知らせ

デフォルトでMouseEvent、J(X)Layer、およびJLabelとKeyEventsを使用するという私の提案はすべてありますが、--->から別のJComponentへのイベントの再ディスパッチには問題はありません。

編集

待ってください:いいえ、JScrollPaneの中央にスパイラル(「ヘビ」と呼ばれるもの)をペイントしたくありません。コンポーネントをペイントして、コンポーネントをJScrollPaneの中央に表示したいと思います。

  • デフォルトでは、JPanelはJViewportよりも幅が広い可能性があります

a)JPanelはDimensionを返します

b)JViewportリターンディメンション

  • その後、問題なく、ちらつきやフリーズ

a)JPanel(ポイント)からJViewport(ポイント)の中心に寸法を中央揃えできます。

b)JComponentがある場合は、JViewportを任意のgetBounds()に移動して、JScrollPane内のJPanelからJComponentまたはPointを返すことができます。

于 2012-05-07T17:50:10.423 に答える
3

Andrew からの提案では、ビューをビューポートよりも小さくすることはできません (それでも中央に配置されます)。

最もクリーンな方法は、ViewportLayout をオーバーライドして、レイアウト マネージャーから直接行うことです。ソースには次の実装があります。

http://www.randelshofer.ch/multishow

ジョブを完全に実行するクラス ZoomableViewportLayout を探します。

于 2013-06-18T10:37:46.753 に答える