您的位置:首页 > 其它

可以托拽的图片显示控件,JViewport 用法演示

2013-08-16 09:32 274 查看
有人发贴问,一个 JPanel 里的图片太大了,超出了 JPanel 的大小范围,“我想拖动鼠标按住JPanel,拖动JPanel,把那些显示不了的线段“拖回来”。”

这是 JViewport 的典型应用场景,很多人会用 JScrollPane,但是对 JViewport 可能不熟悉,其实 JScrollPane 是整合了几个 JViewport,JScrollBar,以及特别设计的布局的一个控件,其中的 JViewport 单独拿出来也很好用,下面就是示例代码。

为了显示图片,先做一个 panel,如下

/*
* Copyright 2013 (raistlic@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import javax.swing.JPanel;

/**
*
* @author raistlic
*/
public class JImagePanel extends JPanel {

private static final Color GRID_1 = Color.GRAY.brighter();
private static final Color GRID_2 = GRID_1.brighter();
private static final int GRID_SIZE = 10;

private Image image;

public void setImage(Image image) {

// although not checked, this method should be called with-in EDT.

this.image = image;
revalidate();
repaint();
}

@Override
public Dimension getPreferredSize() {

if( image == null )
return getMinimumSize();
else {

Insets i = getInsets();
return new Dimension(
i.left + i.right + image.getWidth(this),
i.top + i.bottom + image.getHeight(this));
}
}

@Override
protected void paintComponent(Graphics g) {

super.paintComponent(g);

int width = getWidth();
int height = getHeight();

g.setColor(GRID_1);
g.fillRect(0, 0, width, height);

g.setColor(GRID_2);
for(int x=0, y=0, line=0; y<height; ) {

g.fillRect(x, y, GRID_SIZE, GRID_SIZE);
x += 2 * GRID_SIZE;
if( x > width ) {

y += GRID_SIZE;
line = (line + 1) % 2;
x = line * GRID_SIZE;
}
}

Insets i = getInsets();
g.drawImage(image, i.left, i.top, this);
}
}


绘制代码中间有大段画格子(类似PS里面对透明部分的表现)的,如果不需要可以无视。

然后做一个可以“鼠标托拽改变其中控件显示位置”的 JViewport:

/*
* Copyright 2013 (raistlic@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JViewport;

/**
*
* @author raistlic
*/
public class JDragableViewport extends JViewport {

public JDragableViewport() {

MouseDragHandler handler = this.new MouseDragHandler();
addMouseListener(handler);
addMouseMotionListener(handler);
}

@Override
public void setViewPosition(Point p) {

p.x = Math.max(0, p.x);
p.y = Math.max(0, p.y);

Component v = getView();
if( v != null ) {

Dimension d = v.getPreferredSize();
Dimension size = getSize();
p.x = Math.min(d.width - size.width, p.x);
p.y = Math.min(d.height - size.height, p.y);
}

super.setViewPosition(p);
}

private class MouseDragHandler implements MouseListener, MouseMotionListener {

private Point cursor = new Point();
private Point view = new Point();

@Override
public void mouseClicked(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

@Override
public void mouseMoved(MouseEvent e) {}

@Override
public void mouseDragged(MouseEvent e) {

Point p = e.getPoint();
int dx = cursor.x - p.x;
int dy = cursor.y - p.y;
view.x += dx;
view.y += dy;

setViewPosition(view);

cursor = p;
view = getViewPosition();
}

@Override
public void mousePressed(MouseEvent e) {

cursor = e.getPoint();
view = getViewPosition();
}
}
}


可以发现,它就是一个普通的 JViewport,加了两个鼠标相关的 listener。

然后写一个小测试,用于打开图片文件并察看:

/*
* Copyright 2013 (raistlic@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;

/**
*
* @author raistlic
*/
public class ImageViewDemo extends JPanel {

public static void main(String[] args) {

SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {

try {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

JFrame f = new JFrame("Image View Demo");

f.setContentPane(new ImageViewDemo());

f.setSize(800, 600);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
catch (Exception e) {

e.printStackTrace();
}
}
});
}

private static final String LABEL_OPEN_FILE = "Open Image File";
private static final Iterable<String> SUPPORTED_FILE_EXT = Arrays.asList(

".jpg", ".png"
);

private JImagePanel imagePanel;
private Action openAction;
private JTextField pathField;
private JFileChooser fileChooser;

ImageViewDemo() {

super(new BorderLayout(5, 5));

imagePanel = new JImagePanel();
openAction = new OpenImageFileAction(LABEL_OPEN_FILE);
pathField = new JTextField();
pathField.setEditable(false);
pathField.setOpaque(false);

initLayout();
}

private void initLayout() {

JViewport viewPort = new JDragableViewport();
viewPort.setView(imagePanel);

add(viewPort, BorderLayout.CENTER);

JPanel control = new JPanel(new GridBagLayout());

GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
gbc.gridx = 0;
gbc.gridy = 0;
control.add(pathField, gbc);

gbc.weightx = 0;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx += 1;
control.add(new JButton(openAction), gbc);

control.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

add(control, BorderLayout.SOUTH);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
}

private JFileChooser getFileChooser() {

if( fileChooser == null ) {

fileChooser = new JFileChooser();
fileChooser.setFileFilter(new FileFilter() {

@Override
public boolean accept(File f) {

assert f != null;

if( f.isDirectory() ) {

return true;
}
else {

String fname = f.getName().toLowerCase();
for(String s : SUPPORTED_FILE_EXT)
if( fname.endsWith(s) )
return true;

return false;
}
}

@Override
public String getDescription() {

return "Image Files";
}
});
fileChooser.setDialogTitle(LABEL_OPEN_FILE);
}
return fileChooser;
}

private class OpenImageFileAction extends AbstractAction {

private OpenImageFileAction(String name) {

super(name);
}

@Override
public void actionPerformed(ActionEvent e) {

JFileChooser jfc = getFileChooser();
int openResult = jfc.showOpenDialog(ImageViewDemo.this);
if( openResult == JFileChooser.APPROVE_OPTION ) {

try {

File file = jfc.getSelectedFile();
BufferedImage image = ImageIO.read(file);
imagePanel.setImage(image);
pathField.setText(file.getAbsolutePath());
}
catch (IOException ex) {

JOptionPane.showMessageDialog(ImageViewDemo.this, "Failed to open Image : " + ex.getMessage());
}
}
}
}
}


代码有些凌乱,作为演示用的小测试也将就了……

下面是Win 7下的运行截图:



鼠标可以在图片的任意位置开始托拽,来改变显示的区域。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐