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

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


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


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


[java]  view plain copy
  1. /* 
  2.  * Copyright 2013 (raistlic@gmail.com) 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16. import java.awt.Color;  
  17. import java.awt.Dimension;  
  18. import java.awt.Graphics;  
  19. import java.awt.Image;  
  20. import java.awt.Insets;  
  21. import javax.swing.JPanel;  
  22.   
  23.   
  24. /** 
  25.  * 
  26.  * @author raistlic 
  27.  */  
  28. public class JImagePanel extends JPanel {  
  29.     
  30.   private static final Color GRID_1 = Color.GRAY.brighter();  
  31.   private static final Color GRID_2 = GRID_1.brighter();  
  32.   private static final int GRID_SIZE = 10;  
  33.     
  34.   private Image image;  
  35.     
  36.   public void setImage(Image image) {  
  37.       
  38.     // although not checked, this method should be called with-in EDT.  
  39.       
  40.     this.image = image;  
  41.     revalidate();  
  42.     repaint();  
  43.   }  
  44.     
  45.   @Override  
  46.   public Dimension getPreferredSize() {  
  47.       
  48.     if( image == null )  
  49.       return getMinimumSize();  
  50.     else {  
  51.         
  52.       Insets i = getInsets();  
  53.       return new Dimension(  
  54.               i.left + i.right + image.getWidth(this),   
  55.               i.top + i.bottom + image.getHeight(this));  
  56.     }  
  57.   }  
  58.     
  59.   @Override  
  60.   protected void paintComponent(Graphics g) {  
  61.       
  62.     super.paintComponent(g);  
  63.       
  64.     int width = getWidth();  
  65.     int height = getHeight();  
  66.       
  67.     g.setColor(GRID_1);  
  68.     g.fillRect(00, width, height);  
  69.       
  70.     g.setColor(GRID_2);  
  71.     for(int x=0, y=0, line=0; y<height; ) {  
  72.         
  73.       g.fillRect(x, y, GRID_SIZE, GRID_SIZE);  
  74.       x += 2 * GRID_SIZE;  
  75.       if( x > width ) {  
  76.           
  77.         y += GRID_SIZE;  
  78.         line = (line + 1) % 2;  
  79.         x = line * GRID_SIZE;  
  80.       }  
  81.     }  
  82.       
  83.     Insets i = getInsets();  
  84.     g.drawImage(image, i.left, i.top, this);  
  85.   }  
  86. }  

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


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


[java]  view plain copy
  1. /* 
  2.  * Copyright 2013 (raistlic@gmail.com) 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16. import java.awt.Component;  
  17. import java.awt.Dimension;  
  18. import java.awt.Point;  
  19. import java.awt.event.MouseEvent;  
  20. import java.awt.event.MouseListener;  
  21. import java.awt.event.MouseMotionListener;  
  22. import javax.swing.JViewport;  
  23.   
  24. /** 
  25.  * 
  26.  * @author raistlic 
  27.  */  
  28. public class JDragableViewport extends JViewport {  
  29.     
  30.   public JDragableViewport() {  
  31.       
  32.     MouseDragHandler handler = this.new MouseDragHandler();  
  33.     addMouseListener(handler);  
  34.     addMouseMotionListener(handler);  
  35.   }  
  36.     
  37.   @Override  
  38.   public void setViewPosition(Point p) {  
  39.       
  40.     p.x = Math.max(0, p.x);  
  41.     p.y = Math.max(0, p.y);  
  42.       
  43.     Component v = getView();  
  44.     if( v != null ) {  
  45.         
  46.       Dimension d = v.getPreferredSize();  
  47.       Dimension size = getSize();  
  48.       p.x = Math.min(d.width - size.width, p.x);  
  49.       p.y = Math.min(d.height - size.height, p.y);  
  50.     }  
  51.       
  52.     super.setViewPosition(p);  
  53.   }  
  54.     
  55.   private class MouseDragHandler implements MouseListener, MouseMotionListener {  
  56.       
  57.     private Point cursor = new Point();  
  58.     private Point view = new Point();  
  59.   
  60.     @Override  
  61.     public void mouseClicked(MouseEvent e) {}  
  62.   
  63.     @Override  
  64.     public void mouseReleased(MouseEvent e) {}  
  65.   
  66.     @Override  
  67.     public void mouseEntered(MouseEvent e) {}  
  68.   
  69.     @Override  
  70.     public void mouseExited(MouseEvent e) {}  
  71.   
  72.     @Override  
  73.     public void mouseMoved(MouseEvent e) {}  
  74.   
  75.     @Override  
  76.     public void mouseDragged(MouseEvent e) {  
  77.         
  78.       Point p = e.getPoint();  
  79.       int dx = cursor.x - p.x;  
  80.       int dy = cursor.y - p.y;  
  81.       view.x += dx;  
  82.       view.y += dy;  
  83.         
  84.       setViewPosition(view);  
  85.         
  86.       cursor = p;  
  87.       view = getViewPosition();  
  88.     }  
  89.       
  90.     @Override  
  91.     public void mousePressed(MouseEvent e) {  
  92.         
  93.       cursor = e.getPoint();  
  94.       view = getViewPosition();  
  95.     }  
  96.   }  
  97. }  

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


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


[java]  view plain copy
  1. /* 
  2.  * Copyright 2013 (raistlic@gmail.com) 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16. import java.awt.BorderLayout;  
  17. import java.awt.GridBagConstraints;  
  18. import java.awt.GridBagLayout;  
  19. import java.awt.Insets;  
  20. import java.awt.event.ActionEvent;  
  21. import java.awt.image.BufferedImage;  
  22. import java.io.File;  
  23. import java.io.IOException;  
  24. import java.util.Arrays;  
  25. import javax.imageio.ImageIO;  
  26. import javax.swing.AbstractAction;  
  27. import javax.swing.Action;  
  28. import javax.swing.BorderFactory;  
  29. import javax.swing.JButton;  
  30. import javax.swing.JFileChooser;  
  31. import javax.swing.JFrame;  
  32. import javax.swing.JOptionPane;  
  33. import javax.swing.JPanel;  
  34. import javax.swing.JTextField;  
  35. import javax.swing.JViewport;  
  36. import javax.swing.SwingUtilities;  
  37. import javax.swing.UIManager;  
  38. import javax.swing.filechooser.FileFilter;  
  39.   
  40. /** 
  41.  * 
  42.  * @author raistlic 
  43.  */  
  44. public class ImageViewDemo extends JPanel {  
  45.     
  46.   public static void main(String[] args) {  
  47.       
  48.     SwingUtilities.invokeLater(new Runnable() {  
  49.   
  50.       @Override  
  51.       public void run() {  
  52.           
  53.         try {  
  54.             
  55.           UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());  
  56.             
  57.           JFrame f = new JFrame("Image View Demo");  
  58.             
  59.           f.setContentPane(new ImageViewDemo());  
  60.             
  61.           f.setSize(800600);  
  62.           f.setLocationRelativeTo(null);  
  63.           f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  64.           f.setVisible(true);  
  65.         }  
  66.         catch (Exception e) {  
  67.             
  68.           e.printStackTrace();  
  69.         }  
  70.       }  
  71.     });  
  72.   }  
  73.     
  74.   private static final String LABEL_OPEN_FILE = "Open Image File";  
  75.   private static final Iterable<String> SUPPORTED_FILE_EXT = Arrays.asList(  
  76.             
  77.           ".jpg"".png"  
  78.   );  
  79.     
  80.   private JImagePanel imagePanel;  
  81.   private Action openAction;  
  82.   private JTextField pathField;  
  83.   private JFileChooser fileChooser;  
  84.     
  85.   ImageViewDemo() {  
  86.       
  87.     super(new BorderLayout(55));  
  88.       
  89.     imagePanel = new JImagePanel();  
  90.     openAction = new OpenImageFileAction(LABEL_OPEN_FILE);  
  91.     pathField = new JTextField();  
  92.     pathField.setEditable(false);  
  93.     pathField.setOpaque(false);  
  94.       
  95.     initLayout();  
  96.   }  
  97.     
  98.   private void initLayout() {  
  99.       
  100.     JViewport viewPort = new JDragableViewport();  
  101.     viewPort.setView(imagePanel);  
  102.       
  103.     add(viewPort, BorderLayout.CENTER);  
  104.       
  105.     JPanel control = new JPanel(new GridBagLayout());  
  106.       
  107.     GridBagConstraints gbc = new GridBagConstraints();  
  108.     gbc.insets = new Insets(5555);  
  109.     gbc.fill = GridBagConstraints.HORIZONTAL;  
  110.     gbc.weightx = 1.0;  
  111.     gbc.gridx = 0;  
  112.     gbc.gridy = 0;  
  113.     control.add(pathField, gbc);  
  114.       
  115.     gbc.weightx = 0;  
  116.     gbc.fill = GridBagConstraints.NONE;  
  117.     gbc.gridx += 1;  
  118.     control.add(new JButton(openAction), gbc);  
  119.       
  120.     control.setBorder(BorderFactory.createEmptyBorder(5555));  
  121.       
  122.     add(control, BorderLayout.SOUTH);  
  123.     setBorder(BorderFactory.createEmptyBorder(5555));  
  124.   }  
  125.     
  126.   private JFileChooser getFileChooser() {  
  127.       
  128.     if( fileChooser == null ) {  
  129.         
  130.       fileChooser = new JFileChooser();  
  131.       fileChooser.setFileFilter(new FileFilter() {  
  132.   
  133.         @Override  
  134.         public boolean accept(File f) {  
  135.             
  136.           assert f != null;  
  137.             
  138.           if( f.isDirectory() ) {  
  139.               
  140.             return true;  
  141.           }  
  142.           else {  
  143.               
  144.             String fname = f.getName().toLowerCase();  
  145.             for(String s : SUPPORTED_FILE_EXT)  
  146.               if( fname.endsWith(s) )  
  147.                 return true;  
  148.               
  149.             return false;  
  150.           }  
  151.         }  
  152.   
  153.         @Override  
  154.         public String getDescription() {  
  155.             
  156.           return "Image Files";  
  157.         }  
  158.       });  
  159.       fileChooser.setDialogTitle(LABEL_OPEN_FILE);  
  160.     }  
  161.     return fileChooser;  
  162.   }  
  163.     
  164.   private class OpenImageFileAction extends AbstractAction {  
  165.       
  166.     private OpenImageFileAction(String name) {  
  167.         
  168.       super(name);  
  169.     }  
  170.   
  171.     @Override  
  172.     public void actionPerformed(ActionEvent e) {  
  173.         
  174.       JFileChooser jfc = getFileChooser();  
  175.       int openResult = jfc.showOpenDialog(ImageViewDemo.this);  
  176.       if( openResult == JFileChooser.APPROVE_OPTION ) {  
  177.           
  178.         try {  
  179.             
  180.           File file = jfc.getSelectedFile();  
  181.           BufferedImage image = ImageIO.read(file);  
  182.           imagePanel.setImage(image);  
  183.           pathField.setText(file.getAbsolutePath());  
  184.         }  
  185.         catch (IOException ex) {  
  186.             
  187.           JOptionPane.showMessageDialog(ImageViewDemo.this"Failed to open Image : " + ex.getMessage());  
  188.         }  
  189.       }  
  190.     }  
  191.   }  
  192. }  

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

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




鼠标可以在图片的任意位置开始托拽,来改变显示的区域

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值