JComponentBounds

Aus Byte-Welt Wiki
Wechseln zu: Navigation, Suche

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.

/*
 * 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;
    }
}

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

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