ComponentsContainer

Aus Byte-Welt Wiki
Wechseln zu: Navigation, Suche

ComponentsContainer hat Null-Layout und ist dazu gedacht um JComponentBounds aufzunehmen (bewegliche und in der Größe veränderbare Komponenten).

Er kann versteckte Komponenten durch Mausklick nach vorne bringen (setComponentZOrder).

Die aktuelle Komponente kann gelöscht werden wenn sie fokusiert ist (entweder durch Betätigen der Löschtaste oder über das Kontextmenü).

Der ComponentsContainer kann seinen Inhalt skalieren zu dem Zweck ihn zu drucken; das geschieht in der "print"-Methode:

@Override
public void print(final Graphics g) {
    ((Graphics2D) g).scale(scale, scale);
    super.print(g);
}

Dabei kann der Skalieringsfaktor über die Methode setScale(..) angepasst werden.

Eine Demo ist in der main Methode enthalten:

ComponentsContainer.jpg

/*
 * ComponentsContainer.java
 *
 * Uses the class JComponentBounds:
 * http://wiki.byte-welt.net/wiki/JComponentBounds
 *
 *ComponentsContainer has Null-Layout and is supposed to contain
 *JComponentBounds (moveable and resizable).
 *It takes hidden components to front with mouse click (setComponentZOrder).
 *The current JComponentBounds can be deleted if focused (using delete key
 *or popup menu option).
 *The container can scale its contents for printing.
 * 
 * This class includes main method for demo only.
 * 
 * author: Andre Uhres
 * updated: September 17, 2008 at 17:30
 * updated: December 21, 2010 at 15:00
 */
import bounds.JComponentBounds;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
 
public class ComponentsContainer extends JPanel {
 
    private JComponentBounds current;
    private boolean takeHiddenToFront;
    private JPopupMenu popup;//popup menu to delete the component
    private JMenuItem itemDelete;
    private double scale = 1.0d;//scale factor for printing
 
    public ComponentsContainer() {
        super(null);
 
        setBackground(Color.WHITE);
        //the following MouseListener serves to take hidden Components 
        //to front (changeFocus) and to show a popup menu
        //for component deletion:
        MouseAdapter mouseAdapter = new MouseInputAdapter() {
 
            @Override
            public void mousePressed(final MouseEvent e) {
                takeHiddenToFront = true;
            }
 
            @Override
            public void mouseReleased(final MouseEvent e) {
                if (e.isPopupTrigger() && current != null
                        && current.isFocused()) {
                    popup.show(ComponentsContainer.this,
                            current.getX(), current.getY());
                    return;
                }
                changeFocus(e.getSource(), e.getPoint());
            }
        };
        addMouseListener(mouseAdapter);
        //the following ComponentAdapter serves to transfer the focus
        //to the resizing JComponentBounds (changeFocus)
        ComponentAdapter componentAdapter = new ComponentAdapter() {
 
            @Override
            public void componentResized(final ComponentEvent e) {
                if (e.getSource() instanceof JComponentBounds) {
                    JComponentBounds source = (JComponentBounds) e.getSource();
                    takeHiddenToFront(true);
                    while (!source.isFocused()
                            && source != changeFocus(source, new Point(0, 0))) {
                        clearFocus();
                    }
                }
            }
        };
        addComponentListener(componentAdapter);
        //the following KeyListener serves to delete 
        //the component last clicked and being in front:
        addKeyListener(new KeyAdapter() {
 
            @Override
            public void keyPressed(final KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_DELETE) {
                    delete();
                }
            }
        });
        //the following FocusListener serves to keep
        //the dragged component in front:
        addFocusListener(new FocusAdapter() {
 
            @Override
            public void focusGained(FocusEvent e) {
                if (e.getSource() instanceof JComponentBounds
                        && e.getID() == JComponentBounds.FOCUS_GAINED) {
                    takeHiddenToFront = false;
                }
            }
        });
        popup = new JPopupMenu();
        itemDelete = new JMenuItem();
        popup.add(itemDelete);
        itemDelete.setAction(new Delete("Delete component"));
    }
 
    /*
     * If ComponentsContainer was clicked: remove any focus from the components.
     * Otherwise take a hidden component to front (if any and if takeHiddenToFront is true)
     * and finally set focus to the current component (if any).
     */
    public JComponentBounds changeFocus(final Object source, final Point position) {
        clearFocus();
        if (source instanceof ComponentsContainer) {
            return null;
        }
        //search for the most deeply hidden component at the given position:
        JComponentBounds f = (JComponentBounds) source;
        position.translate(f.getX(), f.getY());
        Component component = null;
        Component[] comps = getComponents();
        for (int i = 0; i < comps.length; i++) {
            Rectangle rect = comps[i].getBounds();
            if (rect.contains(position)) {
                component = comps[i];
            }
        }
        //If a component was found and takeHiddenToFront is true, set the component
        //to be the current component and take it to front:
        if (component != null && takeHiddenToFront) {
            current = (JComponentBounds) component;
            setComponentZOrder(current, 0);
        }
        //Set focus to the current component:
        if (current != null) {
            current.setFocused(true);
        }
        repaint();
        return current;
    }
 
    public void clearFocus() {
        Component[] comps = getComponents();
        for (int i = 0; i < comps.length; i++) {
            ((JComponentBounds) comps[i]).setFocused(false);//remove focus
        }
    }
 
    @Override
    public void print(final Graphics g) {
        ((Graphics2D) g).scale(scale, scale);
        super.print(g);
    }
 
    private void delete() {
        if (current != null && current.isFocused()) {
            remove(current);
            revalidate();
            repaint();
            current = null;
        }
    }
 
    public void setScale(final double scale) {
        this.scale = scale;
    }
 
    public JComponentBounds getCurrent() {
        return current;
    }
 
    public void setCurrent(final JComponentBounds current) {
        this.current = current;
    }
 
    public void takeHiddenToFront(final boolean b) {
        takeHiddenToFront = b;
    }
 
    private class Delete extends AbstractAction {
 
        Delete(final String name) {
            super(name);
        }
 
        @Override
        public void actionPerformed(final ActionEvent e) {
            Object source = e.getSource();
            if (source == itemDelete) {
                delete();
            }
        }
    }
 
    //main method for demo only:
    public static void main(final String[] args) {
        JFrame f = new JFrame("ComponentsContainer Demo");
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.setSize(700, 600);
        f.setLocationRelativeTo(null);
        JButton button = new JButton("Hello");
        JScrollPane scrollpane = new JScrollPane(new JTable(4, 4));
        scrollpane.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        JLabel label = new JLabel("Test Label");
        label.setPreferredSize(new Dimension(100, 50));
        label.setOpaque(true);
        label.setBackground(Color.YELLOW);
        final JComponentBounds labelBounds = new JComponentBounds(label);
        labelBounds.setMinimumSize(new Dimension(50, 20));
        ComponentsContainer container = new ComponentsContainer();
        container.add(labelBounds);
        container.add(new JComponentBounds(button, 150, 50, true));
        container.add(new JComponentBounds(scrollpane, 100, 100, true));
        f.add(container);
        f.setVisible(true);
    }
}