2012-05-07 27 views
11

Nếu bạn tạo một JScrollPane có một khung nhìn lớn hơn thành phần JScrollPane, nó sẽ hiển thị thành phần đó ở phía trên bên trái.Swing: tạo một JScrollPane hiển thị thành phần của nó được căn giữa?

Có cách nào để thay đổi hành vi này để nó hiển thị thành phần được căn giữa không?

chương trình mẫu bên dưới.


:

Tôi có một thành phần trong đó có (chiều rộng, chiều cao) = (cw, ch).

Tôi có JScrollPane với chế độ xem có (chiều rộng, chiều cao) = (vw, vh).

Thành phần có thể trở nên lớn hơn hoặc nhỏ hơn. Tôi muốn một cách để sử dụng thanh cuộn để định vị điểm trung tâm của thành phần liên quan đến điểm trung tâm của khung nhìn, vì vậy nếu một hoặc cả hai kích thước của thành phần nhỏ hơn khung nhìn, thành phần hiển thị ở trung tâm của chế độ xem.

Vị trí hành vi scrollpane mặc định ở góc trên bên trái của thành phần tương ứng với góc trên bên trái của chế độ xem.

Tất cả những gì tôi hỏi là cách thay đổi điểm tham chiếu. Tôi không chắc việc này dễ dàng như thế nào với JScrollPane mặc định, vì vậy nếu nó không dễ, thì tôi sẽ học những gì tôi có thể và nghĩ ra một cách tiếp cận khác.


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); 
    } 
} 
+0

Vui lòng, đăng Mã, mà bạn đang kéo tóc :-). Cảm ơn thần, vì điều đó "Tôi không kéo tóc của tôi (chưa)", Ví dụ sẽ tốt, một cái gì đó để thử trên, sẽ được nhiều đánh giá cao :-) –

+0

Tôi không kéo tóc của tôi (chưa) và bạn don ' Tôi muốn tôi đăng mã tôi có, nhưng tôi có thể đưa ra một ví dụ. –

+0

bạn có muốn vẽ con rắn này ở trung tâm của JScrollPane – mKorbel

Trả lời

12
  1. Đặt một JPanel vào cuộn cửa sổ
  2. Đặt cách bố trí của bảng điều khiển để một GridBagLayout.
  3. Đặt một thành phần vào bảng điều khiển mà không bị ràng buộc. Nó sẽ được căn giữa.

Đây là kỹ thuật được sử dụng trong Nested Layout Example, đặt hình ảnh màu đỏ/màu da cam vào giữa của phụ huynh.

+0

Tôi nghĩ rằng OP muốn vẽ một cái gì đó cho JViewport và có thể để thiết lập một cái gì đó đến điểm mong muốn – mKorbel

+0

Tôi không muốn vẽ cho JViewport, ít nhất là không trực tiếp - Mã thực của tôi là một thành phần được phân lớp từ JPanel, như trong ví dụ của tôi, nhưng nó cũng có các phần tử GUI khác trong nó. –

+0

@Andrew Thompson (@Jason S) là OP phổ biến với các câu hỏi quá rộng :-) – mKorbel

4

tôi chỉ cần thêm một JPanel đến JScrollPane mà tôi thêm THINGY JPanel. Hy vọng đây là những gì bạn muốn:

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); 
    } 
} 

Đây là kết quả:

SIMPLE SCROLLER

+1

+1 ... hoạt động chính xác như thế nào Tôi muốn nó hoạt động theo chiều ngang, không phải theo chiều dọc. –

3

Chấp nhận cả bình luận của bạn, nhưng

có ...mặc dù tôi thực sự muốn tùy tiện vị trí của nó

phương pháp quan trọng để tránh nhấp nháy hoặc nhảy trên JViewport

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

  • sử dụng GlassPane (rất đơn giản để thiết lập vị thế của mình cho đến điểm mong muốn hoặc/và Dimmension)

Tôi không muốn vẽ cho JViewport, tại ít nhất là không trực tiếp - Mã thực của tôi là một thành phần được phân lớp từ JPanel, như trong ví dụ của tôi, nhưng nó cũng có các phần tử GUI khác trong nó.

  • bạn có thể sử dụng JXLayer (Java6) hoặc các bộ phận của các phương pháp từ JXLayer thực hiện để các JLayer (Java7) trực tiếp

  • có thể là quá khó, nhưng trong tất cả các trường hợp, bạn có thể che phủ bất cứ điều gì với JLabel

Thông báo

tất cả các đề nghị của tôi để tiêu thụ MouseEvent theo mặc định, J (X) Layer và JLabel với KeyEvents quá, nhưng không có vấn đề với các sự kiện redispatch từ ---> khác JComponent

EDIT

chờ đợi: không, tôi không muốn vẽ hình xoắn ốc (cái mà bạn gọi là "rắn") ở trung tâm của JScrollPane; Tôi muốn vẽ thành phần của tôi và có thành phần của tôi được hiển thị ở trung tâm của JScrollPane.

  • JPanel của bạn có thể rộng hơn JViewport theo mặc định

a) JPanel trả Dimension

b) JViewport trở Dimension

  • sau đó mà không cần bất kỳ vấn đề, nhấp nháy hay đóng băng

a) bạn có thể tập trung Dimmension từ JPanel (Point) đến trung tâm của JViewport (Point)

b) nếu là có JComponent bạn có thể di chuyển JViewport cho bất kỳ getBounds() tha trở JComponent hoặc điểm từ JPanel bên trong JScrollPane

3

Với đề xuất từ ​​Andrew, bạn không thể có chế độ xem nhỏ hơn chế độ xem (và vẫn ở giữa).

Cách sạch nhất là thực hiện trực tiếp từ trình quản lý bố cục, ghi đè ViewportLayout. Có một thực hiện trong nguồn:

http://www.randelshofer.ch/multishow

Look cho lớp ZoomableViewportLayout, mà không được công việc một cách hoàn hảo.

Các vấn đề liên quan