Verschiebbare Elemente in einem rollbaren Container: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
Zeile 104: Zeile 104:
 
     }
 
     }
 
}</code=java>
 
}</code=java>
*****************************************************
+
--------------------------------------------------
 
<code=java>package graphic;
 
<code=java>package graphic;
  
Zeile 203: Zeile 203:
 
     }
 
     }
 
}</code=java>
 
}</code=java>
*****************************************************
+
--------------------------------------------------
 
<code=java>package graphic;
 
<code=java>package graphic;
  
Zeile 318: Zeile 318:
 
     }
 
     }
 
}</code=java>
 
}</code=java>
*****************************************************
+
--------------------------------------------------
 
<code=java>package graphic;
 
<code=java>package graphic;
  
Zeile 533: Zeile 533:
 
     }
 
     }
 
}</code=java>
 
}</code=java>
*****************************************************
+
--------------------------------------------------
 
<code=java>package sample;
 
<code=java>package sample;
  

Version vom 3. März 2009, 10:36 Uhr

Vielleicht möchtest du dieses Beispiel als Ausgangspunkt nehmen, um verschiebbare Elemente in einem Rollbaren Container zu implementieren: <code=java>package graphic;

/**

* Model.java
*/

import java.awt.*; import java.util.*; import java.util.List;

public class Model {

   private List<Element> elements;
   private Rectangle bounds;
   private Element activeElement;
   public Model() {
       elements = new ArrayList<Element>();
       bounds = new Rectangle();
   }
   public List<Element> getElements() {
       return elements;
   }
   public void setElements(final List<Element> elements) {
       this.elements = elements;
   }
   public Rectangle getBounds() {
       return bounds;
   }
   public void setBounds(Rectangle bounds) {
       this.bounds = bounds;
   }
   public Element getActiveElement() {
       return activeElement;
   }
   public void setActiveElement(final Element activeElement) {
       this.activeElement = activeElement;
   }
   /**
    *
    * @param rect The bounds of any element
    * @return The smallest rectangle enclosing all elements
    */
   protected Rectangle getBounds(final Rectangle rect) {
       bounds = new Rectangle(rect);
       for (Element element : elements) {
           Rectangle elementBounds = new Rectangle(element.getBounds());
           elementBounds.x -= 5;
           elementBounds.y -= 5;
           elementBounds.width += 10;
           elementBounds.height += 10;
           bounds = bounds.union(elementBounds);
       }
       for (Element element : elements) {
           Rectangle elementBounds = element.getBounds();
           elementBounds.translate(-bounds.x, -bounds.y);
       }
       return bounds;
   }
   /**
    *
    * @param hitPoint the location to be analized for intersection with any element
    * @return the list of elements containing hitPoint within their bounds
    */
   protected List<Element> getElementsAt(final Point hitPoint) {
       List<Element> elementsAt = new ArrayList<Element>();
       for (Element element : elements) {
           Rectangle elementBounds = element.getBounds();
           if (elementBounds.contains(hitPoint)) {
               elementsAt.add(element);
           }
       }
       return elementsAt;
   }
   /**
    *
    * @param location the location of the element
    * @return the element added to this Model
    */
   protected Element add(final Point location) {
       Element newElement = new Element();
       Rectangle newBounds;
       newBounds = new Rectangle(location.x, location.y, 0, 0);
       newElement.setBounds(newBounds);
       newElement.getBounds().width = newElement.getMinimumSize().width;
       newElement.getBounds().height = newElement.getMinimumSize().height;
       elements.add(newElement);
       return newElement;
   }


   @Override
   public String toString() {
       return "number of elements: " + elements.size();
   }

}</code=java>


<code=java>package graphic;

/**

* Element.java
*/

import java.awt.*; import javax.swing.JDialog; import javax.swing.JScrollPane; import javax.swing.JTextArea;

public class Element {

   private Rectangle bounds;
   private String text;
   private Dimension minimumSize;
   private Color color;
   private JTextArea tTemp;
   private JDialog dTemp;
   public Element() {
       bounds = new Rectangle();
       text = "";
       minimumSize = new Dimension(113, 50);
       color = Color.WHITE;
       tTemp = new JTextArea();
       dTemp = new JDialog();
       dTemp.add(new JScrollPane(tTemp));
   }
   public Rectangle getBounds() {
       return bounds;
   }
   public void setBounds(final Rectangle bounds) {
       this.bounds = bounds;
   }
   public String getText() {
       return text;
   }
   public void setText(final String text) {
       this.text = text;
   }
   public Dimension getMinimumSize() {
       return minimumSize;
   }
   public void setMinimumSize(final Dimension minimumSize) {
       this.minimumSize = minimumSize;
   }
   /**
    *
    * @return the background color of this element
    */
   public Color getColor() {
       return color;
   }
   /**
    *
    * @param color the background color of this element
    */
   public void setColor(final Color color) {
       this.color = color;
   }
   /**
    *
    * resize the element according to its text bounds
    */
   protected void pack() {
       // tTemp and dTemp are used for size calculation only:
       tTemp.setText(this.getText());
       dTemp.pack();
       Rectangle textBounds = new Rectangle(tTemp.getBounds());
       //respecting minimum size:
       if (textBounds.width < this.getMinimumSize().width) {
           textBounds.width = this.getMinimumSize().width;
       }
       if (textBounds.height < this.getMinimumSize().height) {
           textBounds.height = this.getMinimumSize().height;
       }
       //this coordinates:
       textBounds.x = this.getBounds().x;
       textBounds.y = this.getBounds().y;
       this.setBounds(textBounds);
   }
   @Override
   public String toString() {
       return text;
   }

}</code=java>


<code=java>package graphic;

/**

* Graphic.java
*/

import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.List;

public class Graphic extends JComponent {

   private Model model;
   private JTextArea renderer;
   private transient Stroke normalStroke,  activeStroke;
   private Controller controller;
   //
   private Dimension preferredSize;
   public Graphic() {
       setFocusable(true);
       setControl(new Controller());
       setModel(new Model());
       controller.setView(this);
       normalStroke = new BasicStroke(1);
       activeStroke = new BasicStroke(3);
       renderer = new JTextArea();
       renderer.setFocusable(false);
       preferredSize = new Dimension();
   }
   public Model getModel() {
       return model;
   }
   /**
    * Use this method to set the model that you loaded from file
    * @param model the model to be used by this graphic
    */
   public void setModel(final Model model) {
       this.model = model;
       controller.setModel(model);
   }
   public Stroke getActiveStroke() {
       return activeStroke;
   }
   public void setActiveStroke(final Stroke activeStroke) {
       this.activeStroke = activeStroke;
   }
   public Stroke getNormalStroke() {
       return normalStroke;
   }
   public void setNormalStroke(final Stroke normalStroke) {
       this.normalStroke = normalStroke;
   }
   /**
    * 
    * @return the controller for user interactions
    */
   public Controller getController() {
       return controller;
   }
   private void setControl(Controller controller) {
       this.controller = controller;
       InputMap map = new ComponentInputMap(this);
       map.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.ALT_MASK), "add");
       ActionMap am = new ActionMap();
       am.put("add", controller.getAction(Controller.ADD));
       setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, map);
       setActionMap(am);
   }
   @Override
   public Dimension getPreferredSize() {
       Rectangle bounds = null;
       List<Element> elements = model.getElements();
       if (elements.size() == 0) {
           bounds = new Rectangle();
       } else {
           bounds = model.getBounds(elements.get(0).getBounds());
       }
       preferredSize.width = bounds.width;
       preferredSize.height = bounds.height;
       return preferredSize;
   }
   @Override
   protected void paintComponent(final Graphics g) {
       super.paintComponent(g);
       Graphics2D g2d = (Graphics2D) g;
       for (Element element : model.getElements()) {
           g2d.setStroke(normalStroke);
           renderer.setText(element.getText());
           Rectangle bounds = element.getBounds();
           g2d.setColor(element.getColor());
           g2d.fillRect(bounds.x - 3, bounds.y, bounds.width + 6, bounds.height);
           g2d.setColor(Color.BLACK);
           renderer.setBackground(element.getColor());
           SwingUtilities.paintComponent(g2d, renderer, this, bounds);
           if (element == model.getActiveElement()) {
               g2d.setStroke(activeStroke);
           }
           g2d.drawRect(bounds.x - 3, bounds.y, bounds.width + 6, bounds.height);
       }
   }

}</code=java>


<code=java>package graphic;

/**

* Controller.java
*/

import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.util.List; import java.beans.*; import java.io.*;

public class Controller extends MouseInputAdapter {

   private WindowListener saveOnClose = (WindowListener) EventHandler.create(
           WindowListener.class, this, "saveModel", null, "windowClosing");
   private DocumentListener documentHandler = (DocumentListener) EventHandler.create(
           DocumentListener.class, this, "processText", null);
   private Action addAction;
   private Model model;
   private Graphic graphic;
   private JTextArea editor;
   //
   private Point hitPoint;
   private String filename = "Graphic.xml";
   private boolean userEditing;
   public final static int ADD = 0;
   public Controller() {
       hitPoint = new Point(20, 20);
       userEditing = true;
       //
       addAction = new AbstractAction("Element") {
           public void actionPerformed(ActionEvent e) {
               addElement();
           }
       };
   }
   /**
    * 
    * @return a WindowListener for saving the model on windowClosing
    */
   public WindowListener getSaveOnClose() {
       return saveOnClose;
   }
   /**
    * Use this method to set actions to buttons and menu items
    * @param action the constant identifying the action
    * @return the action identified by the parameter
    */
   public Action getAction(final int action) {
       switch (action) {
           case ADD:
               return addAction;
           default:
               return null;
       }
   }
   protected void setModel(final Model model) {
       this.model = model;
       Element activeElement = model.getActiveElement();
       if (activeElement != null) {
           editor.setText(activeElement.getText());
       }
   }
   protected void setView(final Graphic graphic) {
       this.graphic = graphic;
       graphic.addMouseListener(this);
       graphic.addMouseMotionListener(this);
   }
   /**
    * This method should be called after the model is set
    * @param editor the JTextArea used for text editing
    */
   public void setEditor(final JTextArea editor) {
       if (model == null) {
           throw new RuntimeException("Model ist not set");
       }
       this.editor = editor;
       editor.getDocument().addDocumentListener(documentHandler);
       Element activeElement = model.getActiveElement();
       if (activeElement != null) {
           editor.setText(activeElement.getText());
       }
   }
   @Override
   public void mouseDragged(final MouseEvent evt) {
       Element activeElement = model.getActiveElement();
       if (activeElement != null) {
           Point dragPoint = evt.getPoint();
           int dx = dragPoint.x - hitPoint.x;
           int dy = dragPoint.y - hitPoint.y;
           activeElement.getBounds().translate(dx, dy);
           hitPoint = dragPoint;
           graphic.repaint();
       }
   }
   @Override
   public void mousePressed(final MouseEvent evt) {
       hitPoint = evt.getPoint();
       List<Element> hitElements = model.getElementsAt(hitPoint);
       Element hitElement = null;
       if (hitElements.size() > 0) {
           hitElement = hitElements.get(0);
       }
       model.setActiveElement(hitElement);
       editText(hitElement);
   }
   @Override
   public void mouseReleased(final MouseEvent evt) {
       graphic.revalidate();
       graphic.repaint();
   }
   private void scrollToVisible(final Element element) {
       if (element != null) {
           Rectangle bounds = new Rectangle(element.getBounds());
           bounds.x -= 10;
           bounds.y -= 10;
           bounds.width += 20;
           bounds.height += 20;
           graphic.scrollRectToVisible(bounds);
       }
   }
   private void addElement() {
       Element added = model.add(hitPoint);
       graphic.revalidate();
       scrollToVisible(added);
       graphic.repaint();
   }
   /**
    * Save the Model to file
    */
   public void saveModel() {
       try {
           XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(filename)));
           encoder.writeObject(model);
           encoder.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
   /**
    * Load the Model from file
    * @return the Model loaded
    */
   public Model loadModel() {
       XMLDecoder decoder = null;
       Object result = null;
       try {
           decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream(filename)));
           result = decoder.readObject();
           decoder.close();
       } catch (FileNotFoundException ex) {
       }
       return (Model) result;
   }
   /**
    * Update the active element while the user is typing text into editor area.
    * Called by internal DocumentListener.
    * Generally there is no reason to call this method from client application.
    *
    */
   public void processText() {
       if (userEditing) {
           Element activeElement = model.getActiveElement();
           if (activeElement != null) {
               activeElement.setText(editor.getText());
               activeElement.pack();
               //refresh the view:
               graphic.revalidate();
               scrollToVisible(activeElement);
               graphic.repaint();
           } else {
               JOptionPane.showMessageDialog(graphic, "Please select an element " +
                       "before typing text,\n or else the text will be lost.",
                       "Controller message", JOptionPane.ERROR_MESSAGE);
           }
       }
   }
   /**
    *
    * @param element the element whose text is to be displayed in the editor area
    */
   private void editText(final Element element) {
       userEditing = false;
       editor.setText(element == null ? "" : element.getText());
       graphic.repaint();
       Runnable action = new Runnable() {
           public void run() {
               userEditing = true;
           }
       };
       SwingUtilities.invokeLater(action);
   }

}</code=java>


<code=java>package sample;

/*

* GraphicDemo.java
*
*/

import java.awt.*; import javax.swing.*; import graphic.*;

public class GraphicDemo extends JFrame {

   private JButton btAdd;
   private JTextArea editor;
   private JScrollPane scrollEditor;
   private JScrollPane scroller;
   private JSplitPane splitPane;
   private JToolBar toolbar;
   private Graphic graphic;
   private Controller controller;
   public GraphicDemo() {
       super("GraphicDemo");
       graphic = new Graphic();
       controller = graphic.getController();
       addWindowListener(controller.getSaveOnClose());
       initComponents();
       scroller.setViewportView(graphic);
       controller.setEditor(editor);
       Model modelLoaded = controller.loadModel();
       if (modelLoaded != null) {
           //set the model loaded from file:
           graphic.setModel(modelLoaded);
       }
       splitPane.setResizeWeight(1);//1 = top component gets all extra space
       Runnable setDividerLocation = new Runnable() {
           public void run() {
               splitPane.setDividerLocation(0.8d);
               editor.requestFocusInWindow();
           }
       };
       SwingUtilities.invokeLater(setDividerLocation);
   }
   private void initComponents() {
       toolbar = new JToolBar();
       btAdd = new JButton();
       splitPane = new JSplitPane();
       scroller = new JScrollPane();
       scrollEditor = new JScrollPane();
       editor = new JTextArea();
       setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       toolbar.setRollover(true);
       btAdd.setAction(controller.getAction(Controller.ADD));
       btAdd.setText("Element");
       btAdd.setFocusable(false);
       btAdd.setHorizontalTextPosition(SwingConstants.CENTER);
       btAdd.setVerticalTextPosition(SwingConstants.BOTTOM);
       toolbar.add(btAdd);
       getContentPane().add(toolbar, BorderLayout.PAGE_START);
       splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
       splitPane.setTopComponent(scroller);
       scrollEditor.setViewportView(editor);
       splitPane.setBottomComponent(scrollEditor);
       getContentPane().add(splitPane, BorderLayout.CENTER);
       Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
       setBounds((screenSize.width-800)/2, (screenSize.height-600)/2, 800, 600);
   }
   public static void main(final String[] args) {
       Runnable gui = new Runnable() {
           @Override
           public void run() {
               try {
                   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
               } catch (Exception ex) {
                   ex.printStackTrace();
               }
               new GraphicDemo().setVisible(true);
           }
       };
       //GUI must start on EventDispatchThread:
       SwingUtilities.invokeLater(gui);
   }

}</code=java>