- ベストアンサー
JScrollPaneのノブ移動量について
お世話になっております。 JScrollPaneのスクロール移動量について質問があります。 矢印部分や、トラック部分のスクロール移動量については setBlockIncrementと、setUnitIncrementで移動量を設定できますが ノブ(つまみ部分)のスクロール移動量を変更することは出来ますでしょうか。 ご存知の方がいたら、教えて頂けないでしょうか。 お手数をお掛けいたしますが、宜しくお願いいたします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
やってみました。 public class ScrollByOneLine extends JFrame implements ChangeListener { public static void main(String[] args) { (new ScrollByOneLine()).setVisible(true); } private JTextArea textArea; private JScrollPane scrollPane; private JButton moreTextButton = new JButton("More text!"); private StringBuffer text = new StringBuffer("0 Silly random text.\n"); private Point orig = new Point(0, 0); private JViewport view; public ScrollByOneLine() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); getContentPane().setLayout(new BorderLayout()); this.textArea = new JTextArea() { @Override public boolean getScrollableTracksViewportHeight() { return false; } @Override public boolean getScrollableTracksViewportWidth() { return false; } }; this.scrollPane = new JScrollPane(this.textArea); getContentPane().add(this.scrollPane, BorderLayout.CENTER); //追加:JViewportを追加し、イベントリスナを設定(イベントの定義箇所によっては不要) view = this.scrollPane.getViewport(); view.addChangeListener(this); //JTextAreaの状態に変更があったら //stateChangedを呼ぶ ※このサンプルでは、「相当」呼び出されています。例外も発生します。 肝はstateChangedメソッドの処理だけなので、どのイベントで呼び出すかは、 ご自身で実装されるプログラムに適したところで呼んでください this.moreTextButton.addActionListener(this); getContentPane().add(this.moreTextButton, BorderLayout.SOUTH); setSize(400, 300); } @Override public void stateChanged(ChangeEvent e){ JViewport jv = this.scrollPane.getViewport(); Point p = jv.getViewPosition(); int ptm = this.textArea.viewToModel(p); //左上のオフセットが取れました try{ Rectangle mtv = this.textArea.modelToView(ptm); System.out.println("ChangeViewState" + p + " ptm :"+ ptm + " mtv:" + mtv.getX() + ", " + mtv.getY()); //デバッグ ★ p.setLocation(mtv.getX(), mtv.getY()); //★ this.scrollPane.getViewport().setViewPosition(p); }catch(Exception ex){ ex.printStackTrace(); //現状、JTextAreaが空のとき、modelToViewで例外 } } 肝はstateChangedメソッドです。流れは以下のとおりです。 1)getViewport().getViewPosition()で、左上の座標を取得(Point型) 2)その座標を、viewToModelでoffsetにします 3)その座標をmodelToView(Rectange型)にすると、フォントの左上の座標になるので、 4)3)のRectangle型をPoint型にして 5)4)をgetViewport().setViewPosition((4)の座標)にセットする これを処理させるイベントは、 scrollPane.getVerticalScrollBar().addMouseListener(this);(縦スクロールバーのマウスイベント) あるいは、 viewPoint.addChangeListener(JViewpointの状態変更通知イベント) のいずれかが該当すると思います。 注意 ・タブを全角スペースに置き換えています ・例外を強引に処理しています ・modelToViewは、BadLocationExceptionを返すので、try~catchで囲む必要があります ・示したプログラムは、JTextAreaが空の場合、★でNullPointerExceptionが返ると思います 流用元(やっていることはぜんぜん違うことです。ViewPointというクラスの話などが参考になりました)。 http://stackoverflow.com/questions/2039373/maintaing-jtextarea-scroll-position
その他の回答 (2)
- hirotn
- ベストアンサー率59% (147/246)
FontMetricsのクラスドキュメントを参照してみたところ、 http://docs.oracle.com/javase/jp/6/api/java/awt/FontMetrics.html >このクラスの各メソッドでの実装は効率的ではないため、通常は、より効率的なツールキット特有の実装でオーバーライドされていることに注意してください。 という記述が気になっており、getHeight()のみで、フォントの高さを取得できるのかが気になるところです。 特に、文字とメソッドが示す位置の関係と得たい数値の計算方法は、上記クラスドキュメントを必読と考えます。 ざっくり見て、getHeight()+getAscent()+getDescent()くらいは必要かもしれないです。 http://www.geocities.jp/inu_poti/java/canvas/font.html も参考になるかと存じます。
補足
度々のご回答ありがとうございます。 フォントの高さの設定を色々と変更して実施してみましたが やはり思った通りにいきません。 メモ帳のスクロールのようにJTextPaneも動かしたいのですが…。 Javaではそのように設定するのは無理なのでしょうか。
- hirotn
- ベストアンサー率59% (147/246)
JSCrollPaneのスクロールバーはJSCrollBarになります。 そのスクロール量は、BoundedRangeModelで定義されます。 http://docs.oracle.com/javase/jp/6/api/javax/swing/BoundedRangeModel.html ノブ(つまみ)は、setExtentがあたります。 定義は上記クラスのドキュメントを参照してください。指定できる値の範囲について説明があります。
補足
ご回答ありがとうございます。 JTextpaneにJScrollPaneを割り当てて スクロールバーを表示しています。 ノブでのスクロールは、1行ずつ(フォントの高さ分ずつ) スクロールするように設定したく以下のように設定しました。 FontMetrics fo = text.getFontMetrics(text.getFont()); slp.getVerticalScrollBar().getModel().setExtent(fo.getHeight()); ノブを動かした際に1行ずつテキストエリアが表示される ことを期待していたのですが、ゆっくりスクロールバーを 動かすと前の行のフォントが半分くらい見えてしまい、 意図した動きをしてくれません。 1行ずつ表示する方法があれば教えて頂けないでしょうか。
お礼
お世話になっております。 ご連絡が遅くなってしまい、大変申し訳ありません。 JViewportに対して、Pointをセットするやり方は 非常に参考になりました。 本当にありがとうございました。 今後ともよろしくお願いいたします。