Пользовательские формы Java Swing (2D-графика) - PullRequest
2 голосов
/ 20 марта 2010

Мне нужно рисовать нестандартные фигуры. Теперь, когда пользователь нажимает на несколько точек на панели, я создаю форму, используя многоугольник.

public void mouseClicked(MouseEvent e) {
            polygon.addPoint(e.getX(), e.getY());
            repaint();
        }

Но я не знаю, является ли это лучшим способом рисования пользовательских фигур.

В должна быть возможность редактировать нарисованную фигуру :

  • изменить размер
  • изменить цвет заливки
  • изменить цвет обводки
  • скопировать / вставить
  • переместить одну точку многоугольника
  • ...

Я видел людей, создающих собственный класс, реализующий класс Shape и использующий GeneralPath. Но опять же, я понятия не имею, если это хороший способ.

Теперь я могу создать свою собственную форму с помощью многоугольника (или с помощью GeneralPath), но я понятия не имею, как прикрепить все функции редактирования к моей собственной форме (функции редактирования, которые я имею в виду, изменение размера, перемещение и т. Д.) сверху) .

Я надеюсь, что кто-нибудь может показать мне способ сделать это или, возможно, написать немного кода, чтобы продемонстрировать это.

Заранее спасибо !!

Ответы [ 3 ]

5 голосов
/ 20 марта 2010

Отвечая на ваш вопрос, я бы определенно сделал то, что вы описываете как решение AWT - таким образом вы можете отслеживать созданные объекты и позволять пользователю загружать их на редактируемый холст и, скорее всего, каждый из них. формы, создаваемые пользователем, будут «слоем», а не контейнером качания слоев, а объектом, который будет хранить и отслеживать, какие фигуры нарисованы и иметь возможность перерисовывать их - главное, что нужно иметь в виду, это «Порядок прорисовки». По сути, вы можете сделать это, назначив каждому объекту или группе объектов, которые являются вашими «фигурами», Z = [0-100] и т. Д. (100, может быть любым числом), которые определяют порядок каждого объекта / фигур. втянуты и, таким образом, как они лежали друг на друга.

В основном вам понадобится класс фигур, в котором хранится

Должна быть возможность редактировать нарисованный форма:

изменить размер изменить цвет заливки изменить цветной штрих скопируйте / вставьте его одна точка многоугольника ...

Вы обрисовали в общих чертах и ​​объект / менеджер хранения, который будет перечислять объекты / экземпляры класса формы, которые создаются. Эти классы будут более или менее содержаться в контейнере java.awt.Canvas, который будет обрабатывать всю графику.

В основном вы хотите использовать awt вместо Swing, потому что Swing не безопасен для потоков - таким образом, вы не «рисуете себя в углу» на ранних этапах разработки. Другая причина заключается в том, что это реализация, которая должна реагировать и взаимодействовать так, как привыкли пользователи. Swing построен на AWT и добавляет значительную сложность, которая не нужна подобному приложению. В общем, вы собираетесь создать класс Custom, который является именно тем, что имел в виду объект Canvas. обеспечить, и если бы Sun сохранил этот такт раньше, они бы не попали в беспорядок, которым оказался Swing ... Сообщество разработчиков - и я в том числе - были на пути к тому, чтобы создать многое из того, что Swing предлагал в «гладком» и компонентном дизайне, но то, что мы создавали, было полностью на основе AWT , Когда Swing вышел на сцену, Java как платформа с графическим интерфейсом была очень сложной, и Sun и Java пошли по скользкому пути ...

Кроме того, вы должны решить, чего вы в конечном итоге хотите, в части контроля над тем, что вы создаете здесь. Если вам это нужно быстро и вам не нужно вносить изменения в него в будущем, есть множество примеров с открытым исходным кодом, которые могут это сделать - большинство бесплатно. Если вы хотите сделать это самостоятельно, то надеюсь, что того, о чем я говорил выше, и кода резиновой ленты, приведенного ниже, будет достаточно, чтобы помочь вам получить более глубокое понимание Java как GUI. Я лично надеюсь, что вы возьмете это на себя - этот язык отчаянно нуждается в большем количестве «ключевых» людей, которые действительно понимают язык и его дизайн, а не только как «работать» с такими фреймворками, как Hibernate и Spring ...

Удачи, надеюсь, это поможет,

WM

Что касается кода выбора "Rubber-band", то это мой код, который я использовал в прошлом, просто считайте его GLP и используйте его по мере необходимости ...

Во-первых, интерфейс прослушивателя:

/*
 * RubberBandListener.java
 *
 * Created on August 18, 2005, 3:27 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */
package com.ges.util;

import java.util.EventListener;
import java.awt.Rectangle;

/**
 *
 * @author mstemen
 */
public interface RubberBandListener extends EventListener {

    public abstract void notifyBounds(Rectangle boundingBox);
}

Вот класс, который является пользовательским компонентом AWT - он должен быть в любом Swing / AWT, вероятно, даже SWT

/*
 * RubberBandSelect.java
 *
 * Created on August 18, 2005, 9:11 AM
 * By Matthew Stemen/Wintermute Studios for util like use
 *
 */
package com.ges.util;

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

/**
 *
 * @author mstemen
 */
public class RubberBandSelect extends Component {

    /** Creates a new instance of RubberBandSelect */
    private Point startPoint = null;
    private Point endPoint = null;
    private Graphics hostGraphics = null;
    private Component hostComponent = null;
    private Color bandColor = Color.ORANGE.darker().darker();
    private boolean started = false;
    private boolean eraseSomething = false;
    private int startX, endX, startY, endY = 0;
    private Rectangle boundingBox;
    private StringBuilder QuadrantMessage = null;
    private HashSet<RubberBandListener> listeners =
        new HashSet<RubberBandListener>();
    private int width = 0;
    private int height = 0;

    public RubberBandSelect(Component c) {
        hostComponent = c;
        hostGraphics = c.getGraphics();
    }

    public void addListener(RubberBandListener l) {
        listeners.add(l);
    }

    public void paint(Graphics g) {
        draw();
    }

    public void erase() {
        if (eraseSomething) {
//            hostComponent.repaint();
            draw();
            eraseSomething = false;
        }
    }

    private void draw() {
        hostGraphics = hostComponent.getGraphics();
        if (hostGraphics != null) {
            try {
                /// hostGraphics.setXORMode( hostComponent.getBackground() );
                erase();
                drawRubberBand();
                eraseSomething = false;
            } finally {
//                hostGraphics.dispose();
            }
        }
    }

    private void drawRubberBand() {
        if (!started) {
            return;
        }

        hostGraphics = hostComponent.getGraphics();
        if (hostGraphics == null) {
            return;
        }

        if (startPoint == null || endPoint == null) {
            return;
        }

        hostGraphics.setColor(bandColor);

        if (endX > startX && endY > startY) {
            boundingBox = new Rectangle(startX, startY, endX - startX, endY - startY);
            hostGraphics.drawRect(startX, startY, endX - startX, endY - startY);

            QuadrantMessage = new StringBuilder("Drawing in Q - IV X1=");
            width = endX - startX;
            height = endY - startY;
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
        } else if (endX < startX && endY < startY) {
            boundingBox = new Rectangle(endX, endY, startX - endX, startY - endY);
            hostGraphics.drawRect(endX, endY, startX - endX, startY - endY);
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
            QuadrantMessage = new StringBuilder("Drawing in Q - II X1=");
            width = startX - endX;
            height = startY - endY;

        } else if (endX > startX && endY < startY) {
            boundingBox = new Rectangle(startX, endY, endX - startX, startY - endY);
            hostGraphics.drawRect(startX, endY, endX - startX, startY - endY);
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
            QuadrantMessage = new StringBuilder("Drawing in Q - I X1=");
            width = endX - startX;
            height = startY - endY;
        } else if (endX < startX && endY > startY) {
            boundingBox = new Rectangle(endX, startY, startX - endX, endY - startY);
            hostGraphics.drawRect(endX, startY, startX - endX, endY - startY);
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
            QuadrantMessage = new StringBuilder("Drawing in Q - III X1=");
            width = startX - endX;
            height = endY - startY;
        }


    }

    public void assignToCompoent(Component c) {
        this.hostComponent = c;
        hostGraphics = c.getGraphics();
    }

    public void update(Graphics g) {
        drawRubberBand();
    }

    public Point getStartPoint() {
        return startPoint;
    }

    public void setStartPoint(Point startPoint) {
        this.startPoint = startPoint;
        startX = (int) startPoint.getX();
        startY = (int) startPoint.getY();
        QuadrantMessage = new StringBuilder();
        // UDTMgr.getMgr().sendStatusMessage( "RubberBandSelect--Started:  point is: X=" + startX + " Y=" + startY );
        // drawRubberBand();
        // started = true;
    }

    public Point getEndPoint() {
        return endPoint;
    }

    public void setEndPoint(Point endPoint) {

        this.endPoint = endPoint;
        clear();
        endX = (int) endPoint.getX();
        endY = (int) endPoint.getY();
        // UDTMgr.getMgr().sendStatusMessage( "RubberBandSelect--Streching: points are: X=" + startX + " Y=" + startY + " Ending Point is: X=" + endX + " Y="+ endY );

        draw();
        notifyListeners();
        started = true;
    }

    public Color getBandColor() {
        return bandColor;
    }

    public void setBandColor(Color bandColor) {
        this.bandColor = bandColor;
    }

    public void setForeground(Color color) {
        this.bandColor = color;

    }

    private void clear() {
        hostGraphics = hostComponent.getGraphics();
        if (hostGraphics == null) {
            return;
        }
        // hostGraphics.setXORMode( hostComponent.getBackground() );
        try {
            // hostGraphics.setXORMode( hostComponent.getBackground() );
            drawRubberBand();
        } finally {
//            hostGraphics.dispose();
        }
    }

    public void breakBand() {
        startPoint = null;
        endPoint = null;
        started = false;
        boundingBox = new Rectangle(0, 0, 0, 0);
        if (hostGraphics != null) {
            hostGraphics.dispose();
        }
        clear();
        hostComponent.repaint();
        // UDTMgr.getMgr().sendStatusMessage( "RubberBandSelect-- Broke band, click to restart" );
    }

    public boolean isStarted() {
        return started;
    }

    public void notifyListeners() {
        Iterator<RubberBandListener> it = listeners.iterator();

        while (it.hasNext()) {
            it.next().notifyBounds(boundingBox);
        }
    }

    public void redraw(Graphics g) {
        if (startPoint == null || endPoint == null) {
            return;
        }

        g.setColor(bandColor);
//        hostGraphics.setPaintMode();
        // hostComponent.repaint();
        // four way case state to determine what quadrant to draw in
        if (endX > startX && endY > startY) {
            boundingBox = new Rectangle(startX, startY, endX - startX, endY - startY);
            g.drawRect(startX, startY, endX - startX, endY - startY);

            QuadrantMessage = new StringBuilder("Drawing in Q - IV X1=");
            width = endX - startX;
            height = endY - startY;
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
        } else if (endX < startX && endY < startY) {
            boundingBox = new Rectangle(endX, endY, startX - endX, startY - endY);
            g.drawRect(endX, endY, startX - endX, startY - endY);
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
            QuadrantMessage = new StringBuilder("Drawing in Q - II X1=");
            width = startX - endX;
            height = startY - endY;

        } else if (endX > startX && endY < startY) {
            boundingBox = new Rectangle(startX, endY, endX - startX, startY - endY);
            g.drawRect(startX, endY, endX - startX, startY - endY);
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
            QuadrantMessage = new StringBuilder("Drawing in Q - I X1=");
            width = endX - startX;
            height = startY - endY;
        } else if (endX < startX && endY > startY) {
            boundingBox = new Rectangle(endX, startY, startX - endX, endY - startY);
            g.drawRect(endX, startY, startX - endX, endY - startY);
            //UDTMgr.getMgr().sendStatusMessage( "Drawing Rect: " + "(X1=" + startX + ",Y1=" + startY + ") (X2=" + endX + ",Y2=" + endY + ")"  );
            QuadrantMessage = new StringBuilder("Drawing in Q - III X1=");
            width = startX - endX;
            height = endY - startY;
        }
    }

    public Rectangle getBoundingBox() {
        return boundingBox;
    }
}
3 голосов
/ 20 марта 2010

Проект ImageJ имеет особенно хорошую реализацию инструмента Многоугольник с регулируемыми вершинами, как видно здесь и здесь .

alt text

2 голосов
/ 20 марта 2010

Вы смотрели на класс Graphics в Java (есть также класс Polygon)? Существуют методы рисования и заливки полигонов, и каждый из них может принимать массив координат по оси X и по оси Y Используя эти массивы, вы сможете довольно легко изменить положение точек. Как будто вы можете изменить их все одинаково для изменения размера или скопировать и вставить, просто переместив все точки одинаково Изменить цвет так же просто, как заполнить его новым цветом и перекрасить.

...