JComponentBounds

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen

Die Klasse und ein Anwendungsbeispiel

JComponentBounds

Die Klasse "JComponentBounds" erlaubt es, JComponents zu verschieben und in der Grösse zu verändern. Die Klasse "PictureDemo" weiter unten zeigt ein Anwendungsbeispiel. <code=java> /*

* JComponentBounds.java
*
* This class aims at making any JComponent resizable
* simply by putting it inside a JInternalFrame.
* The wrapped JComponent is made moveable
* by means of a MouseInputAdapter.
* The class includes a "snap to grid" option.
*
* author: Andre Uhres
* update April 15, 2010 at 6:00
* update December 21, 2010 at 15:00
*/

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

public class JComponentBounds extends JInternalFrame {

   public static final int FOCUS_GAINED = 97531;
   private JComponent componentsContainer;
   private boolean focused;
   private JComponent comp;
   private static final Color TRANSPARENT = new Color(0.0f, 0.0f, 0.0f, 0.0f);
   public static final int MARGIN = 5;
   private KeyAdapter kl;
   private MouseInputAdapter ml;
   private ComponentAdapter cl;
   private boolean snapToGrid;
   public JComponentBounds() {
       this(new JLabel("jComponentBounds"));
   }
   public JComponentBounds(final JComponent comp) {
       this(comp, 0, 0, false);
   }
   public JComponentBounds(final JComponent comp, final boolean focused) {
       this(comp, 0, 0, focused);
   }
   public JComponentBounds(final JComponent comp, final int x, final int y,
           final boolean focused) {
       super();
       this.comp = comp;
       this.focused = focused;
       setBounds(x, y,
               comp.getPreferredSize().width, comp.getPreferredSize().height);
       setResizable(true);
       setVisible(true);
       setOpaque(false);
       setBackground(TRANSPARENT);
       ((BasicInternalFrameUI) getUI()).setNorthPane(null);
       setBorder(BorderFactory.createEmptyBorder(
               MARGIN, MARGIN, MARGIN, MARGIN));
       comp.setFocusable(true);
       add(comp);
       ml = new MouseInputAdapter() {
           private Point p1;
           @Override
           public void mousePressed(final MouseEvent e) {
               p1 = e.getPoint();
               componentsContainer = (JComponent) getParent();
               e.setSource(JComponentBounds.this);
               //componentsContainer might use the mousePressed event
               //to take hidden components to the top:
               componentsContainer.dispatchEvent(e);
           }
           @Override
           public void mouseReleased(final MouseEvent e) {
               componentsContainer = (JComponent) getParent();
               e.setSource(JComponentBounds.this);
               //componentsContainer might use the mouseReleased event
               //to take hidden components to the top:
               componentsContainer.dispatchEvent(e);
           }
           @Override
           public void mouseDragged(final MouseEvent e) {
               if (!JComponentBounds.this.isFocused()) {
                   return;
               }
               //drag operation:
               Point p2 = e.getPoint();
               Point loc = getLocation();
               loc.translate(p2.x - p1.x, p2.y - p1.y);
               setLocation(loc);
               componentsContainer = (JComponent) getParent();
               //auto scroll:
               componentsContainer.scrollRectToVisible(
                       new Rectangle(loc.x, loc.y, getWidth(), getHeight()));
               //componentsContainer might use the focusGained event
               //to keep the dragged component in front:
               FocusListener[] focusListeners = componentsContainer.getFocusListeners();
               if (focusListeners != null && focusListeners.length > 0) {
                   FocusListener fl = focusListeners[0];
                   fl.focusGained(
                           new FocusEvent(JComponentBounds.this,
                           JComponentBounds.FOCUS_GAINED));
               }
           }
       };
       kl = new KeyAdapter() {
           @Override
           public void keyPressed(final KeyEvent e) {
               componentsContainer = (JComponent) getParent();
               //componentsContainer might use the keyPressed event
               //to delete the component:
               componentsContainer.dispatchEvent(e);
           }
       };
       cl = new ComponentAdapter() {
           @Override
           public void componentResized(final ComponentEvent e) {
               ((JComponent) e.getSource()).revalidate();
               componentsContainer = (JComponent) getParent();
               //componentsContainer might use the componentResized event
               //to transfer focus to the resizing component:
               if(componentsContainer != null){
                   componentsContainer.dispatchEvent(e);
               }
           }
           @Override
           public void componentMoved(final ComponentEvent e) {
               ((JComponent) e.getSource()).revalidate();
           }
       };
       addAllListeners();
   }
   /* Move and resize this component.
    * This method has been overridden to implement the "snap to grid" option.
    */
   @Override
   public void reshape(final int x, final int y,
           final int width, final int height) {
       if (snapToGrid) {
           //convert all parameters to multiples of MARGIN:
           int gridx = x / MARGIN * MARGIN;
           int gridy = y / MARGIN * MARGIN;
           int gridwidth = width / MARGIN * MARGIN;
           int gridheight = height / MARGIN * MARGIN;
           //if not horizontally on the grid, round up the grid width:
           if (gridx != x && gridwidth != width) {
               gridwidth += MARGIN;
           }
           //if not vertically on the grid, round up the grid height:
           if (gridy != y && gridheight != height) {
               gridheight += MARGIN;
           }
           //snap to the grid:
           super.reshape(gridx, gridy, gridwidth, gridheight);
       } else {
           super.reshape(x, y, width, height);
       }
   }
   public boolean isSnapToGrid() {
       return snapToGrid;
   }
   public void setSnapToGrid(final boolean snapToGrid) {
       this.snapToGrid = snapToGrid;
   }
   private void addAllListeners() {
       comp.addMouseListener(ml);
       comp.addMouseMotionListener(ml);
       comp.addKeyListener(kl);
       addComponentListener(cl);
   }
   public void removeAllListeners() {
       comp.removeMouseListener(ml);
       comp.removeMouseMotionListener(ml);
       comp.removeKeyListener(kl);
       removeComponentListener(cl);
   }
   public void setComponent(final JComponent comp) {
       //remove old component:
       removeAllListeners();
       remove(this.comp);
       //add new component:
       this.comp = comp;
       comp.setFocusable(true);
       add(comp);
       addAllListeners();
   }
   public void setFocused(final boolean focused) {
       this.focused = focused;
       repaint();
   }
   public boolean isFocused() {
       return focused;
   }
   public Rectangle getComponentRect() {
       Insets insets = getInsets();
       Rectangle rect = getBounds();
       rect.x += insets.left;
       rect.y += insets.top;
       rect.width -= (insets.right + insets.left);
       rect.height -= (insets.top + insets.bottom);
       return rect;
   }

} </code=java>

PictureDemo

Die Klasse "PictureDemo" ermöglicht das Laden eines Bildes durch einen Klick auf das Fenster.

PictureDemo1.jpg

Das geladene Bild kann man anschließend in der Größe und Position verändern.

PictureDemo.jpg

<code=java> /*

* PictureDemo.java
*/

import container.JComponentBounds; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.io.*; import java.util.*; import javax.imageio.*; import javax.swing.*;


//Model class PictureStorage extends Observable {

   private BufferedImage data;
   public PictureStorage() {
   }
   public void loadPicture(final String filename) {
       System.out.println("loading " + filename);
       SwingWorker<BufferedImage, Void> loadPicture = new SwingWorker<BufferedImage, Void>() {
           @Override
           protected BufferedImage doInBackground() throws Exception {
               try {
                   data = ImageIO.read(new File(filename));
               } catch (IOException ex) {
                   System.out.println(ex);
               }
               return data;
           }
           @Override
           protected void done() {
               setChanged();
               notifyObservers(data); //sends change notification to the view
           }
       };
       loadPicture.execute();
   }

}

//View class GUI extends JFrame implements Observer {

   private PictureDemo demo;
   private JComponent picture;
   private JComponentBounds pictureBounds;
   private GUI frame;
   private Image image;
   public GUI(final PictureDemo demo) {
       super();
       this.demo = demo;
       this.init();
   }
   private void init() {
       frame = this;
       setTitle("Demo: click to load picture");
       setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       setSize(800, 600);
       setLocationRelativeTo(null);
       addMouseListener(new MouseAdapter() {
           @Override
           public void mousePressed(final MouseEvent e) {
               FileDialog fileDialog = new FileDialog(frame);
               fileDialog.setVisible(true);
               String dir = fileDialog.getDirectory();
               String file = fileDialog.getFile();
               if (dir != null && file != null) {
                   demo.loadPicture(dir + file);
               }
           }
       });
       //configure picture:
       setLayout(null);
       picture = new JLabel() {
           @Override
           protected void paintComponent(final Graphics g) {
               super.paintComponent(g);

// g.drawImage(image, 0, 0, this);

               g.drawImage(image, 0, 0, pictureBounds.getWidth(), pictureBounds.getHeight(), this);
           }
       };
       picture.setPreferredSize(new Dimension(100, 100));
       pictureBounds = new JComponentBounds(picture, 10, 10, true);
       pictureBounds.setMinimumSize(new Dimension(40, 20));

// pictureBounds.setSnapToGrid(true);

       add(pictureBounds);
   }
   public void update(final Observable observable, final Object arg) {
       image = (Image) arg;
       if (image == null) {
           JOptionPane.showMessageDialog(this, "Picture not found");
       } else {
           pictureBounds.setSize(image.getWidth(null), image.getHeight(null));
           picture.setOpaque(true);
           picture.setBackground(Color.LIGHT_GRAY);
           picture.repaint();
       }
   }

}

//Controller public class PictureDemo {

   private PictureStorage model;
   public PictureDemo() {
       model = new PictureStorage();
       GUI gui = new GUI(this);
       model.addObserver(gui);
       gui.setVisible(true);
   }
   public void loadPicture(final String file) {
       model.loadPicture(file);
   }
   public static void main(final String[] args) {
       Runnable gui = new Runnable() {
           @Override
           public void run() {
               PictureDemo pictureDemo = new PictureDemo();
           }
       };
       //GUI must start on EventDispatchThread:
       SwingUtilities.invokeLater(gui);
   }

} </code=java>