viewport编程

第13章 滚动

  本章介绍Swing的滚动体系结构,这个体系结构包括两个轻量Swing容器、一个Scrollable接口、和一个JScrollBar类。其中,这两个轻量Swing容器是JViewport和JScrollPane,设计这个Scrollable接口来支持有特殊滚动需求的组件。
  JViewport实例很少被实例化,也很少被直接使用,然而,本章仍将用相当大的篇幅来介绍JViewport类,因为它是Swing滚动体系结构的基础组件。
  设计JScrollPane组件来替代AWT的重量组件ScrollPane。JScrollPane在AWT的ScrollPane基础上做了许多改进,包括具有配置行头部的能力和具有指定在滚动窗格角部组件的能力。
  Scrollable接口是为表格、树、文本组件和列表等包含数据行或数据列的可滚动组件而设计的。
  JScrollBar组件是一个用来实现手动滚动的滚动条。虽然Swing的JScrollPane组件在大多数滚动情况是足够用了,但是,有时为了性能或资源的考,还必须实现手动滚动。在这种情况下,可以用JScrollBar组件来滚动容器的内容。

13.1 JViewport

  JViewport类是Swing滚动体系结构的基础。就如它的名字所指出的那样,JViewport的实例提供一个视口,视图的特定区域可以显示在这个视口中。可以操纵由视口显示的视图的位置,以便在不同的时刻,使不同的视图区域出现在这个视口中。
  图13-1所示的小应用程序包含JViewport的一个实例,它的视图是JLabel的一个实例。该标签配备了一幅比显示图像的视口还要大的图像。这个小应用程序提供了四个用于调整视口中视图位置的按钮。
  图13-1中的左图显示这个小应用程序开始时的样子。右图显示出在反复激活up和left按钮后,这个小应用程序的梯子。应该强调的是,反复激活按钮不是滚动视口中视图最理想的方式,但是它说明了一个视口是怎样调整其视图位置的。
  这个小应用程序创建JViewport的一个实例和JLabel的一个实例。通过调用JVieweport.setView()来指定这个标签作为视口的视图。这个小应用程序还创建了一个ControlPanel实例(它是JPanel的一个扩展),这个实例包含了四个用于滚动标签的按钮。

例13-1 用JViewport的一个实例来滚动一幅图像


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JViewport viewport = new JViewport();
JPanel view = new JPanel();

view.add(new JLabel(
new ImageIcon("anjinAndMariko.gif")));

viewport.setView(view);

contentPane.add(new ControlPanel(viewport),
BorderLayout.NORTH);
contentPane.add(viewport, BorderLayout.CENTER);
}
}
class ControlPanel extends JPanel {
private JViewport viewport;

private JButton[] buttons = {
new JButton("up"), new JButton("down"),
new JButton("left"), new JButton("right")
};

public ControlPanel(JViewport vp) {
viewport = vp;

for(int i=0; i < buttons.length; ++i) {
add(buttons[i]);

buttons[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scroll(e.getActionCommand());
}
});
}
}
private void scroll(String actionCmd) {
Point vp = viewport.getViewPosition();

if(actionCmd.equals("up")) vp.y += 5;
else if(actionCmd.equals("down")) vp.y -= 5;
else if(actionCmd.equals("left")) vp.x += 5;
else if(actionCmd.equals("right")) vp.x -= 5;

viewport.setViewPosition(vp);
}
}


13.1.1 拖动视口中的视图

 

例13-2 拖动视口中的视图


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JLabel label = new JLabel(new ImageIcon("pic.gif"));
JViewport vp = new JViewport();
ViewportDragListener listener =
new ViewportDragListener(vp);

vp.setView(label);
vp.addMouseListener(listener);
vp.addMouseMotionListener(listener);

contentPane.add(vp, BorderLayout.CENTER);
}
}
class ViewportDragListener extends MouseAdapter
implements MouseMotionListener {
private JViewport viewport;
private Point last = new Point(), scrollTo = new Point();

public ViewportDragListener(JViewport viewport) {
this.viewport = viewport;
}
public void mousePressed(MouseEvent e) {
last.x = e.getPoint().x;
last.y = e.getPoint().y;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
Point drag = e.getPoint();
Point viewPos = viewport.getViewPosition();
Point offset = new Point(drag.x-last.x, drag.y-last.y);
last.x = drag.x;
last.y = drag.y;

if(viewport.contains(drag)) {
scrollTo.x = viewPos.x - offset.x;
scrollTo.y = viewPos.y - offset.y;
viewport.setViewPosition(scrollTo);
}
}
}


13.1.2 使用scrollRectToVisible

 

例13-3 使用scrollRectToVisible()


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Test extends JApplet {
private JButton buttons[] = {
new JButton(), new JButton(), new JButton(),
new JButton(), new JButton(), new JButton(),
new JButton(), new JButton(), new JButton(),
new JButton(), new JButton(), new JButton(),
new JButton(), new JButton(), new JButton(),
new JButton(), new JButton(), new JButton(),
};
public Test() {
Container contentPane = getContentPane();
JViewport viewport = new JViewport();
JPanel view = new JPanel();
JPanel controlPanel = new ControlPanel(buttons);

view.setLayout(new GridLayout(0,3));

for(int i=0; i < buttons.length; ++i) {
buttons[i].setText("button # " + i);
buttons[i].setPreferredSize(new Dimension(150,50));
view.add(buttons[i]);
}

viewport.setView(view);

contentPane.add(controlPanel, BorderLayout.NORTH);
contentPane.add(viewport, BorderLayout.CENTER);
}
}
class ControlPanel extends JPanel {
private JComboBox combo = new JComboBox();

public ControlPanel(final JButton[] buttons) {
add(combo);

for(int i=0; i < buttons.length; ++i) {
combo.addItem("button number " + i);
}
combo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
int index = combo.getSelectedIndex();
JButton button = buttons[index];
Dimension size = button.getSize();

buttons[index].scrollRectToVisible(
new Rectangle(0,0, size.width,size.height));
}
});
}
}


13.1.3 JViewport属性

 

13.1.4 JViewport事件

 

例13-4 对JViewport变化事件的响应


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JViewport viewport = new JViewport();
JPanel view = new JPanel();

view.add(new JLabel(
new ImageIcon("anjinAndMariko.gif")));

viewport.setView(view);

contentPane.add(new ControlPanel(viewport),
BorderLayout.NORTH);
contentPane.add(viewport, BorderLayout.CENTER);
contentPane.add(new StatusPanel(viewport),
BorderLayout.SOUTH);
}
}
class StatusPanel extends JPanel {
private JLabel extentLabel = new JLabel(),
viewPositionLabel = new JLabel(),
viewSizeLabel = new JLabel();
private JViewport viewport;

public StatusPanel(JViewport vp) {
viewport = vp;

setBorder(BorderFactory.createEtchedBorder());
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

extentLabel.setAlignmentX(0.5f);
viewPositionLabel.setAlignmentX(0.5f);
viewSizeLabel.setAlignmentX(0.5f);

add(extentLabel);
add(viewPositionLabel);
add(viewSizeLabel);

viewport.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
Dimension extent = viewport.getExtentSize();
Point viewPosition = viewport.getViewPosition();
Rectangle viewSize = viewport.getViewRect();

extentLabel.setText("View Extent: " +
extent.toString());
viewPositionLabel.setText("View Position: " +
viewPosition.toString());
viewSizeLabel.setText("View Size: " +
viewSize.toString());
revalidate();
}
});
}
}
class ControlPanel extends JPanel {
private JViewport viewport;

private JButton[] buttons = {
new JButton("up"), new JButton("down"),
new JButton("left"), new JButton("right"),
};

public ControlPanel(JViewport vp) {
viewport = vp;

for(int i=0; i < buttons.length; ++i) {
add(buttons[i]);

buttons[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scroll(e.getActionCommand());
}
});
}
}
private void scroll(String actionCmd) {
Point vp = viewport.getViewPosition();

if(actionCmd.equals("up")) vp.y += 5;
else if(actionCmd.equals("down")) vp.y -= 5;
else if(actionCmd.equals("left")) vp.x += 5;
else if(actionCmd.equals("right")) vp.x -= 5;

viewport.setViewPosition(vp);
}
}


13.1.5 JViewport类总结

 

13.1.6 AWT兼容

 

例13-5 使用JScrollPane


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JLabel view = new JLabel(new ImageIcon("cutlery.jpg",
"A picture of cutlery"));
JScrollPane sp = new JScrollPane(view);

contentPane.add(sp);
}
}


13.2 JScrollPane

 

13.2.1 滚动窗格的头部

 

例13-6 为滚动窗格的头部指定视图


import java.awt.*;
import javax.swing.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JLabel columnHeaderView = new JLabel(
new ImageIcon("horizontalRuler.jpg",
"horizontal ruler"));
JLabel rowHeaderView = new JLabel(
new ImageIcon("verticalRuler.jpg",
"vertical ruler"));
JLabel view = new JLabel(
new ImageIcon("grapes.jpg",
"grapes"));

JScrollPane sp = new JScrollPane(view);

sp.setColumnHeaderView(columnHeaderView);
sp.setRowHeaderView(rowHeaderView);

sp.setViewportBorder(
BorderFactory.createRaisedBevelBorder());

contentPane.add(sp);
}
}


例13-7 设置头部视口


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
JViewport columnHeaderViewport = new JViewport();
JViewport rowHeaderViewport = new JViewport();

JLabel columnHeaderView = new JLabel(
new ImageIcon("horizontalRuler.jpg"));
JLabel rowHeaderView = new JLabel(
new ImageIcon("verticalRuler.jpg"));
JLabel view = new JLabel(
new ImageIcon("strawberry.jpg"));

JScrollPane sp = new JScrollPane(view);

sp.setToolTipText(
"Drag the headers to drag the picture!");

HeaderViewDragListener verticalHeaderListener =
new HeaderViewDragListener(sp,
SwingConstants.VERTICAL);

HeaderViewDragListener horizontalHeaderListener =
new HeaderViewDragListener(sp,
SwingConstants.HORIZONTAL);

columnHeaderViewport.addMouseListener(
horizontalHeaderListener);
columnHeaderViewport.addMouseMotionListener(
horizontalHeaderListener);

rowHeaderViewport.addMouseListener(
verticalHeaderListener);
rowHeaderViewport.addMouseMotionListener(
verticalHeaderListener);

// headers must be set before header views
sp.setColumnHeader(columnHeaderViewport);
sp.setRowHeader(rowHeaderViewport);

sp.setColumnHeaderView(columnHeaderView);
sp.setRowHeaderView(rowHeaderView);

contentPane.add(sp);
}
}
class HeaderViewDragListener extends MouseAdapter
implements MouseMotionListener,
SwingConstants {
private Point last = new Point();
private JScrollPane scrollpane;
private int orientation;

public HeaderViewDragListener(JScrollPane sp, int orient) {
scrollpane = sp;
orientation = orient;
}
public void mousePressed(MouseEvent e) {
last.x = e.getPoint().x;
last.y = e.getPoint().y;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
JViewport headerViewport = (JViewport)e.getSource();
JViewport scrollpaneViewport = scrollpane.getViewport();
Dimension viewSize = scrollpaneViewport.getViewSize(),
extent = scrollpaneViewport.getExtentSize();

Point drag = e.getPoint();
Point offset = new Point(drag.x-last.x, drag.y-last.y);
Point headerPosition = new Point(), viewportPosition;

viewportPosition = scrollpaneViewport.getViewPosition();

if(orientation == HORIZONTAL) {
int nextX = viewportPosition.x - offset.x;
int rightEdge = extent.width + nextX;

if(nextX > 0 && rightEdge < viewSize.width) {
headerPosition.x = nextX;
viewportPosition.x = nextX;
}
}
if(orientation == VERTICAL) {
int nextY = viewportPosition.y - offset.y;
int bottomEdge = extent.height + nextY;

if(nextY > 0 && bottomEdge < viewSize.height) {
headerPosition.y = nextY;
viewportPosition.y = nextY;
}
}
headerViewport.setViewPosition(headerPosition);
scrollpaneViewport.setViewPosition(viewportPosition);

last.x = drag.x;
last.y = drag.y;
}
}


 

13.2.2 滚动窗的角部

 

例13-8 指定滚动窗格的角部的组件


import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JLabel columnHeaderView = new JLabel(
new ImageIcon("horizontalRuler.jpg"));
JLabel rowHeaderView = new JLabel(
new ImageIcon("verticalRuler.jpg"));
JLabel view = new JLabel(
new ImageIcon("anjinAndMariko.gif"));

JScrollPane sp = new JScrollPane(view);

JPanel corners[] = {
new JPanel(), new JPanel(),
new JPanel(), new JPanel()
};
String cornerConstants[] = {
ScrollPaneConstants.UPPER_LEFT_CORNER,
ScrollPaneConstants.LOWER_LEFT_CORNER,
ScrollPaneConstants.UPPER_RIGHT_CORNER,
ScrollPaneConstants.LOWER_RIGHT_CORNER,
};
Border border = BorderFactory.createEtchedBorder();

for(int i=0; i < corners.length; ++i) {
corners[i].setBorder(border);
sp.setCorner(cornerConstants[i], corners[i]);
}

sp.setColumnHeaderView(columnHeaderView);
sp.setRowHeaderView(rowHeaderView);
contentPane.add(sp);
}
}


13.2.3 JViewport属性

 

13.2.4 JViewport事件

 

13.2.5 JViewport类总结

 

例13-9 透明和不透明滚动窗格


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
public void init() {
Container contentPane = new CustomContentPane();
JLabel view1 = new JLabel(
new ImageIcon("gjMedium.gif"));
JLabel view2 = new JLabel(
new ImageIcon("anjinAndMariko.gif"));

JScrollPane sp1 = new JScrollPane(view1);
JScrollPane sp2 = new JScrollPane(view2);

setContentPane(contentPane);
sp1.setPreferredSize(new Dimension(250,250));
sp2.setPreferredSize(new Dimension(250,250));

contentPane.add(sp1);
contentPane.add(sp2);
}
}
class CustomContentPane extends JPanel {
private ImageIcon rain = new ImageIcon("rain.gif");

public CustomContentPane() {
setLayout(new FlowLayout());
}
public void paintComponent(Graphics g) {
int rainw = rain.getIconWidth();
int rainh = rain.getIconHeight();

Dimension size = getSize();

for(int row=0; row < size.height; row += rainh)
for(int col=0; col < size.width; col += rainw)
rain.paintIcon(this,g,col,row);
}
}


13.2.6 AWT兼容

 

13.3 Scrollable接口

 

例13-10 跟踪视口宽度


import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

public class Test extends JApplet {
private JTextArea textArea = new JTextArea();

public void init() {
Container contentPane = getContentPane();

readFile();

contentPane.add(new ControlPanel(), BorderLayout.NORTH);
contentPane.add(new JScrollPane(textArea),
BorderLayout.CENTER);
}
private void readFile() {
DefaultEditorKit kit = new DefaultEditorKit();

try {
kit.read(new FileReader("Test.java"),
textArea.getDocument(), 0);
}
catch(Exception ex) { ex.printStackTrace(); }
}
class ControlPanel extends JPanel {
public ControlPanel() {
final JCheckBox cb = new JCheckBox("wrap");

add(cb);

cb.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if(cb.isSelected())
textArea.setLineWrap(true);
else
textArea.setLineWrap(false);
}
});
}
}
}


13.4 JScrollBar

 

 

13.4.1 使用Swing的JScrollBar类进行手动滚动

 

13.4.2 块增量和单元增量

 

13.4.3 JScrollBar属性

 

例13-11 为JScrollBar的实例指定单增量和块增量


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Test extends JApplet {
private JScrollBar vsb = new JScrollBar(JScrollBar.VERTICAL);
private SSPanel panel = new SSPanel();

public Test() {
Container contentPane = getContentPane();

contentPane.add(panel, BorderLayout.CENTER);
contentPane.add(vsb, BorderLayout.EAST);

vsb.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(
AdjustmentEvent e) {
JScrollBar sb = (JScrollBar)e.getSource();
showScrollBarValues();
panel.setTopIndexByPixelValue(e.getValue());
panel.repaint();
}
});
}
public void paint(Graphics g) {
Dimension pref = panel.getPreferredSize();
Dimension size = panel.getSize();
int extent = size.height, max = pref.height;
int value = Math.max(0,
Math.min(vsb.getValue(), max - extent));

vsb.setVisible(extent < max);
vsb.setUnitIncrement(panel.getUnitHeight());
vsb.setBlockIncrement(extent - vsb.getUnitIncrement());
vsb.setValues(value, extent, 0, max);

showScrollBarValues();
super.paint(g);
}
private void showScrollBarValues() {
showStatus("min: " + vsb.getMinimum() +
", max: " + vsb.getMaximum() +
", visible amount: " +
vsb.getVisibleAmount() +
", value: " + vsb.getValue());
}
}
class SSPanel extends JPanel {
private int topIndex = 0;
private int fh;

private String[] data = {
"Brown, Ted: 000-00-0001", "Brown, Ted: 000-00-0002",
"Brown, Ted: 000-00-0003", "Brown, Ted: 000-00-0004",
"Brown, Ted: 000-00-0005", "Brown, Ted: 000-00-0006",
"Brown, Ted: 000-00-0007", "Brown, Ted: 000-00-0008",
"Brown, Ted: 000-00-0009", "Brown, Ted: 000-00-00010",
"Brown, Ted: 000-00-00011", "Brown, Ted: 000-00-00012",
"Brown, Ted: 000-00-00013", "Brown, Ted: 000-00-00014",
"Brown, Ted: 000-00-00015", "Brown, Ted: 000-00-00016",
"Brown, Ted: 000-00-00017", "Brown, Ted: 000-00-00018",
"Brown, Ted: 000-00-00019", "Brown, Ted: 000-00-00020",
"Brown, Ted: 000-00-00021", "Brown, Ted: 000-00-00022",
"Brown, Ted: 000-00-00023", "Brown, Ted: 000-00-00024",
"Brown, Ted: 000-00-00025", "Brown, Ted: 000-00-00026",
"Brown, Ted: 000-00-00027", "Brown, Ted: 000-00-00028",
"Brown, Ted: 000-00-00029", "Brown, Ted: 000-00-00030",
};
public void paintComponent(Graphics g) {
Color color = g.getColor();
super.paintComponent(g);
g.setColor(color);

Dimension size = getSize();
Insets insets = getInsets();
int y = insets.top;

for(int i = topIndex; i < data.length; ++i, y += fh) {
g.drawString(data[i], 0, y);

if(y + fh > size.height - insets.bottom)
break;
}
}
public void setTopIndexByPixelValue(int pixelValue) {
topIndex = pixelValue / fh;
}
public int getUnitHeight() {
return fh;
}
public Dimension getPreferredSize() {
Dimension dim = new Dimension();
Graphics g = getGraphics();

try {
FontMetrics fm = g.getFontMetrics();
fh = fm.getHeight();

dim.width = fm.stringWidth(data[data.length-1]);
dim.height = fm.getHeight() * (data.length + 1);
}
finally {
g.dispose();
}
return dim;
}
}


13.4.4 JScrollBar事件

 

例13-12 使用JScrollBar的valueIsAdjusting属性


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
public Test() {
Container contentPane = getContentPane();
JScrollBar sb = new JScrollBar();

contentPane.add(sb, BorderLayout.EAST);

sb.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(
AdjustmentEvent e) {
JScrollBar jsb = (JScrollBar)e.getAdjustable();

if(jsb.getValueIsAdjusting())
showStatus("adjusting ...");
else
showStatus(Integer.toString(e.getValue()));
}
});
}
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值