Java Swing Изменение размера компонентов

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(Новая: In this part of the Java Swing tutorial, we will create a resizable component. == Resizable component == Resizable components are most often used when creating charts, diagrams and si...)
(нарушало авторские права)
 
Строка 1: Строка 1:
-
In this part of the Java Swing tutorial, we will create a resizable component.
 
-
== Resizable component ==
 
-
 
-
Resizable components are most often used when creating charts, diagrams and similar. The most common resizable component is a chart in a spreadsheet application. For example, when we create a chart in a OpenOffice application. The chart can be moved over the grid widget of the application and resized.
 
-
 
-
In order to create a component that can be freely dragged over a panel, we need a panel with absolute positioning enabled.
 
-
We must not use a layout manager.
 
-
In our example, we will create a component (a JPanel) that we can freely move over a parent window and resize.
 
-
 
-
In order to distinguish which component has a focus, we draw 8 small rectangles on the border of our resizable component.
 
-
This way we know, that the component has focus. The rectangles serve as a dragging points, where we can draw the component and start resizing. I have learnt to use resizable components from <a href="http://www.jroller.com/santhosh/category/Swing">this</a> blog.
 
-
 
-
<source lang="java">
 
-
package resizablecomponent;
 
-
 
-
import java.awt.Color;
 
-
import java.awt.Dimension;
 
-
import java.awt.event.MouseAdapter;
 
-
import java.awt.event.MouseEvent;
 
-
 
-
import javax.swing.JFrame;
 
-
import javax.swing.JPanel;
 
-
 
-
 
-
/* ResizableComponent.java */
 
-
 
-
public class ResizableComponent extends JFrame {
 
-
 
-
private JPanel panel = new JPanel(null);
 
-
private Resizable resizer;
 
-
 
-
 
-
public ResizableComponent() {
 
-
 
-
    add(panel);
 
-
 
-
    JPanel area = new JPanel();
 
-
    area.setBackground(Color.white);
 
-
    resizer = new Resizable(area);
 
-
    resizer.setBounds(50, 50, 200, 150);
 
-
    panel.add(resizer);
 
-
 
-
 
-
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
-
    setSize(new Dimension(350, 300));
 
-
    setTitle("Resizable Component");
 
-
    setLocationRelativeTo(null);
 
-
 
-
    addMouseListener(new MouseAdapter() {
 
-
      public void mousePressed(MouseEvent me) {
 
-
 
-
        requestFocus();
 
-
        resizer.repaint();
 
-
      }
 
-
    });
 
-
}
 
-
 
-
public static void main(String[] args) {
 
-
    ResizableComponent rc = new ResizableComponent();
 
-
    rc.setVisible(true);
 
-
}
 
-
}
 
-
</source>
 
-
 
-
The <b>ResizableComponent</b> sets up the panel and the component.
 
-
 
-
<source lang="java">
 
-
private JPanel panel = new JPanel(null);
 
-
</source>
 
-
 
-
We have already mentioned, that we cannot use any layout manager. We must use absolute positioning for resizable component.
 
-
By providing null to the constructor, we create a panel with absolute positioning.
 
-
 
-
<source lang="java">
 
-
addMouseListener(new MouseAdapter() {
 
-
  public void mousePressed(MouseEvent me) {
 
-
 
-
    requestFocus();
 
-
    resizer.repaint();
 
-
  }
 
-
});
 
-
</source>
 
-
 
-
If we press on the parent panel, e.g outside the resizable component, we grab focus and repaint the component. The rectangles over the border will disappear.
 
-
 
-
<source lang="java">
 
-
package resizablecomponent;
 
-
 
-
import java.awt.Color;
 
-
import java.awt.Component;
 
-
import java.awt.Cursor;
 
-
import java.awt.Graphics;
 
-
import java.awt.Insets;
 
-
import java.awt.Rectangle;
 
-
import java.awt.event.MouseEvent;
 
-
 
-
import javax.swing.SwingConstants;
 
-
import javax.swing.border.Border;
 
-
 
-
// ResizableBorder.java
 
-
 
-
public class ResizableBorder implements Border {
 
-
private int dist = 8;
 
-
 
-
int locations[] =
 
-
{
 
-
  SwingConstants.NORTH, SwingConstants.SOUTH, SwingConstants.WEST,
 
-
  SwingConstants.EAST, SwingConstants.NORTH_WEST,
 
-
  SwingConstants.NORTH_EAST, SwingConstants.SOUTH_WEST,
 
-
  SwingConstants.SOUTH_EAST
 
-
};
 
-
 
-
int cursors[] =
 
-
{
 
-
  Cursor.N_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR,
 
-
  Cursor.E_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR,
 
-
  Cursor.SW_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR
 
-
};
 
-
 
-
public ResizableBorder(int dist) {
 
-
  this.dist = dist;
 
-
}
 
-
 
-
public Insets getBorderInsets(Component component) {
 
-
    return new Insets(dist, dist, dist, dist);
 
-
}
 
-
 
-
public boolean isBorderOpaque() {
 
-
    return false;
 
-
}
 
-
 
-
public void paintBorder(Component component, Graphics g, int x, int y,
 
-
                        int w, int h) {
 
-
    g.setColor(Color.black);
 
-
    g.drawRect(x + dist / 2, y + dist / 2, w - dist, h - dist);
 
-
 
-
    if (component.hasFocus()) {
 
-
 
-
 
-
      for (int i = 0; i < locations.length; i++) {
 
-
        Rectangle rect = getRectangle(x, y, w, h, locations[i]);
 
-
        g.setColor(Color.WHITE);
 
-
        g.fillRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
 
-
        g.setColor(Color.BLACK);
 
-
        g.drawRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
 
-
      }
 
-
    }
 
-
}
 
-
 
-
private Rectangle getRectangle(int x, int y, int w, int h, int location) {
 
-
    switch (location) {
 
-
    case SwingConstants.NORTH:
 
-
        return new Rectangle(x + w / 2 - dist / 2, y, dist, dist);
 
-
    case SwingConstants.SOUTH:
 
-
        return new Rectangle(x + w / 2 - dist / 2, y + h - dist, dist,
 
-
                              dist);
 
-
    case SwingConstants.WEST:
 
-
        return new Rectangle(x, y + h / 2 - dist / 2, dist, dist);
 
-
    case SwingConstants.EAST:
 
-
        return new Rectangle(x + w - dist, y + h / 2 - dist / 2, dist,
 
-
                              dist);
 
-
    case SwingConstants.NORTH_WEST:
 
-
        return new Rectangle(x, y, dist, dist);
 
-
    case SwingConstants.NORTH_EAST:
 
-
        return new Rectangle(x + w - dist, y, dist, dist);
 
-
    case SwingConstants.SOUTH_WEST:
 
-
        return new Rectangle(x, y + h - dist, dist, dist);
 
-
    case SwingConstants.SOUTH_EAST:
 
-
        return new Rectangle(x + w - dist, y + h - dist, dist, dist);
 
-
    }
 
-
    return null;
 
-
}
 
-
 
-
public int getCursor(MouseEvent me) {
 
-
    Component c = me.getComponent();
 
-
    int w = c.getWidth();
 
-
    int h = c.getHeight();
 
-
 
-
    for (int i = 0; i < locations.length; i++) {
 
-
        Rectangle rect = getRectangle(0, 0, w, h, locations[i]);
 
-
        if (rect.contains(me.getPoint()))
 
-
            return cursors[i];
 
-
    }
 
-
 
-
    return Cursor.MOVE_CURSOR;
 
-
}
 
-
}
 
-
 
-
</source>
 
-
 
-
The <b>ResizableBorder</b> is responsible for drawing the border of the component and determining the type of the cursor to use.
 
-
 
-
<source lang="java">
 
-
int locations[] =
 
-
{
 
-
  SwingConstants.NORTH, SwingConstants.SOUTH, SwingConstants.WEST,
 
-
  SwingConstants.EAST, SwingConstants.NORTH_WEST,
 
-
  SwingConstants.NORTH_EAST, SwingConstants.SOUTH_WEST,
 
-
  SwingConstants.SOUTH_EAST
 
-
};
 
-
</source>
 
-
 
-
These are locations, where we will draw rectangles. These locations are grabbing points, where we can grab the
 
-
component and resize it.
 
-
 
-
<source lang="java">
 
-
g.setColor(Color.black);
 
-
g.drawRect(x + dist / 2, y + dist / 2, w - dist, h - dist);
 
-
</source>
 
-
 
-
In the <b>paintBorder()</b> method, we draw the border of the resizable component.
 
-
The upper code draws the outer border of the component.
 
-
 
-
<source lang="java">
 
-
if (component.hasFocus()) {
 
-
 
-
  for (int i = 0; i < locations.length; i++) {
 
-
    Rectangle rect = getRectangle(x, y, w, h, locations[i]);
 
-
    g.setColor(Color.WHITE);
 
-
    g.fillRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
 
-
    g.setColor(Color.BLACK);
 
-
    g.drawRect(rect.x, rect.y, rect.width - 1, rect.height - 1);
 
-
  }
 
-
}
 
-
 
-
</source>
 
-
 
-
The eight rectangles are drawn only in case that the resizable component has currently focus.
 
-
 
-
Finally, the <b>getCursor()</b> methods gets the cursor type for the grab point in question.
 
-
 
-
<source lang="java">
 
-
package resizablecomponent;
 
-
 
-
import java.awt.BorderLayout;
 
-
import java.awt.Component;
 
-
import java.awt.Cursor;
 
-
import java.awt.Point;
 
-
import java.awt.Rectangle;
 
-
import java.awt.event.MouseEvent;
 
-
 
-
import javax.swing.JComponent;
 
-
import javax.swing.event.MouseInputAdapter;
 
-
import javax.swing.event.MouseInputListener;
 
-
 
-
// Resizable.java
 
-
 
-
public class Resizable extends JComponent {
 
-
 
-
public Resizable(Component comp) {
 
-
  this(comp, new ResizableBorder(8));
 
-
}
 
-
 
-
public Resizable(Component comp, ResizableBorder border) {
 
-
  setLayout(new BorderLayout());
 
-
  add(comp);
 
-
  addMouseListener(resizeListener);
 
-
  addMouseMotionListener(resizeListener);
 
-
  setBorder(border);
 
-
}
 
-
 
-
private void resize() {
 
-
    if (getParent() != null) {
 
-
      ((JComponent)getParent()).revalidate();
 
-
    }
 
-
}
 
-
 
-
MouseInputListener resizeListener = new MouseInputAdapter() {
 
-
  public void mouseMoved(MouseEvent me) {
 
-
    if (hasFocus()) {
 
-
        ResizableBorder border = (ResizableBorder)getBorder();
 
-
        setCursor(Cursor.getPredefinedCursor(border.getCursor(me)));
 
-
    }
 
-
  }
 
-
 
-
  public void mouseExited(MouseEvent mouseEvent) {
 
-
      setCursor(Cursor.getDefaultCursor());
 
-
  }
 
-
 
-
  private int cursor;
 
-
  private Point startPos = null;
 
-
 
-
  public void mousePressed(MouseEvent me) {
 
-
    ResizableBorder border = (ResizableBorder)getBorder();
 
-
    cursor = border.getCursor(me);
 
-
    startPos = me.getPoint();
 
-
    requestFocus();
 
-
    repaint();
 
-
  }
 
-
 
-
  public void mouseDragged(MouseEvent me) {
 
-
 
-
    if (startPos != null) {
 
-
 
-
      int x = getX();
 
-
      int y = getY();
 
-
      int w = getWidth();
 
-
      int h = getHeight();
 
-
 
-
      int dx = me.getX() - startPos.x;
 
-
      int dy = me.getY() - startPos.y;
 
-
 
-
      switch (cursor) {
 
-
        case Cursor.N_RESIZE_CURSOR:
 
-
          if (!(h - dy < 50)) {
 
-
            setBounds(x, y + dy, w, h - dy);
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.S_RESIZE_CURSOR:
 
-
          if (!(h + dy < 50)) {
 
-
            setBounds(x, y, w, h + dy);
 
-
            startPos = me.getPoint();
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.W_RESIZE_CURSOR:
 
-
          if (!(w - dx < 50)) {
 
-
            setBounds(x + dx, y, w - dx, h);
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.E_RESIZE_CURSOR:
 
-
          if (!(w + dx < 50)) {
 
-
            setBounds(x, y, w + dx, h);
 
-
            startPos = me.getPoint();
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.NW_RESIZE_CURSOR:
 
-
          if (!(w - dx < 50) && !(h - dy < 50)) {
 
-
            setBounds(x + dx, y + dy, w - dx, h - dy);
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.NE_RESIZE_CURSOR:
 
-
          if (!(w + dx < 50) && !(h - dy < 50)) {
 
-
            setBounds(x, y + dy, w + dx, h - dy);
 
-
            startPos = new Point(me.getX(), startPos.y);
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.SW_RESIZE_CURSOR:
 
-
          if (!(w - dx < 50) && !(h + dy < 50)) {
 
-
            setBounds(x + dx, y, w - dx, h + dy);
 
-
            startPos = new Point(startPos.x, me.getY());
 
-
            resize();
 
-
          }
 
-
          break;
 
-
 
-
        case Cursor.SE_RESIZE_CURSOR:
 
-
          if (!(w + dx < 50) && !(h + dy < 50)) {
 
-
            setBounds(x, y, w + dx, h + dy);
 
-
            startPos = me.getPoint();
 
-
            resize();
 
-
          }
 
-
        break;
 
-
 
-
        case Cursor.MOVE_CURSOR:
 
-
          Rectangle bounds = getBounds();
 
-
          bounds.translate(dx, dy);
 
-
          setBounds(bounds);
 
-
          resize();
 
-
        }
 
-
 
-
 
-
        setCursor(Cursor.getPredefinedCursor(cursor));
 
-
      }
 
-
    }
 
-
 
-
  public void mouseReleased(MouseEvent mouseEvent) {
 
-
    startPos = null;
 
-
  }
 
-
};
 
-
}
 
-
 
-
</source>
 
-
 
-
The <b>Resizable</b> class represents the component, that is being resized and moved on the window.
 
-
 
-
<source lang="java">
 
-
private void resize() {
 
-
    if (getParent() != null) {
 
-
      ((JComponent)getParent()).revalidate();
 
-
    }
 
-
}
 
-
</source>
 
-
 
-
The <b>revalidate()</b> method
 
-
will cause the component to be redrawn.
 
-
 
-
 
-
<source lang="java">
 
-
MouseInputListener resizeListener = new MouseInputAdapter() {
 
-
  public void mouseMoved(MouseEvent me) {
 
-
    if (hasFocus()) {
 
-
        ResizableBorder border = (ResizableBorder)getBorder();
 
-
        setCursor(Cursor.getPredefinedCursor(border.getCursor(me)));
 
-
    }
 
-
}
 
-
</source>
 
-
 
-
We change the cursor type, when we hover the cursor over the grip points. The cursor type changes only if the component has focus.
 
-
 
-
<source lang="java">
 
-
public void mousePressed(MouseEvent me) {
 
-
  ResizableBorder border = (ResizableBorder)getBorder();
 
-
    cursor = border.getCursor(me);
 
-
    startPos = me.getPoint();
 
-
    requestFocus();
 
-
    repaint();
 
-
}
 
-
</source>
 
-
 
-
If we click on the resizable component, we change the cursor, get the starting point of dragging, give focus to the component and redraw it.
 
-
 
-
<source lang="java">
 
-
int x = getX();
 
-
int y = getY();
 
-
int w = getWidth();
 
-
int h = getHeight();
 
-
 
-
int dx = me.getX() - startPos.x;
 
-
int dy = me.getY() - startPos.y;
 
-
</source>
 
-
 
-
In the <b>mouseDragged()</b> method, we determine the x, y coordinates of the cursor, width and height of the
 
-
component. We calculate the distances, that we make during the mouse drag event. 
 
-
 
-
<source lang="java">
 
-
case Cursor.N_RESIZE_CURSOR:
 
-
  if (!(h - dy < 50)) {
 
-
  setBounds(x, y + dy, w, h - dy);
 
-
  resize();
 
-
  }
 
-
  break;
 
-
 
-
</source>
 
-
 
-
For all resizing we ensure, that the component is not smaller than 50 px. Otherwise, we could make it so small, that we would eventually hide the component. The <b>setBounds()</b> method relocates and resizes the component.
 
-
 
-
[[image: java_swing_resizablecomponent.png | center]]
 
-
 
-
[[Категория:Java]]
 

Текущая версия на 11:27, 7 апреля 2009