Java Swing 自定义形状(2D 图形)

标签 java swing drawing 2d

我需要绘制自定义形状。现在,当用户单击面板上的多个点时,我会使用多边形创建一个形状。

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

但我不知道这是否是绘制自定义形状的最佳方式。

应该可以编辑绘制的形状:

  • 调整大小
  • 改变它的填充颜色
  • 改变描边颜色
  • 复制/粘贴
  • 移动多边形的一个点
  • ...

我见过有人创建自己的类来实现 Shape 类并使用 GeneralPath。但我还是不知道这是否是一个好方法。

现在我可以使用多边形(或使用 GeneralPath)创建我自己的形状,但我不知道如何将所有编辑功能附加到我自己的形状(编辑功能我指的是调整大小、移动等从上面)

我希望有人能告诉我一个方法来做到这一点,或者写一些代码来证明这一点。

提前致谢!

最佳答案

在回答您的问题时,我肯定会做您描述的 AWT 解决方案——这样您就可以跟踪创建的对象并能够允许用户将它们重新加载到编辑 Canvas 上,并且很可能每个用户创建的形状将是一个“层”,而不是 Layer Swing Container,而是一个对象,该对象将存储和跟踪绘制的形状并能够重新绘制它们——要记住的主要事情是“绘制顺序”。基本上,您可以通过将作为“形状”的每个对象或对象组分配给 Z=[0-100] 等(100,可以是任何数字)来确定每个对象/形状的顺序被吸引进来,因此它们如何相互重叠。

基本上你需要一个形状类来存储

It should be possible to edit a drawn shape:

resize change its fill color change the stroke color copy/paste it move a single point of the polygon ...

您概述了一个存储对象/管理器,它将枚举所创建的形状类对象/实例。这些类将或多或少包含在实际处理所有图形的 java.awt.Canvas 容器中。

大多数情况下,由于 Swing 不是线程安全的,因此您希望在 Swing 上使用 awt——这样您就不会在设计的早期“把自己画在角落里”。另一个原因是这是一个需要以用户习惯的方式响应和交互的实现。 Swing 构建于 AWT 之上,并增加了像这样的应用程序不需要的大量复杂性。总而言之,您将创建一个类 Custom 组件,这正是 Canvas 对象的意思 提供,如果 Sun 早点保持这种机智,他们就不会进入 结果 Swing 变得一团糟……开发人员社区——包括我自己——在创建 Swing 在“灵活”和基于组件的设计方面提供的许多功能方面进展顺利,但我们正在构建的是完全基于 AWT 的.当 Swing 出现时,作为 GUI 平台的 Java 变得非常复杂,并使 Sun 和 Java 走上了一条湿滑的道路......

此外,您还必须决定您最终想要什么,以及如何控制您在这里创建的内容。如果您快速需要它并且不太关心将来修改它,那么有很多开源示例可以做到这一点——大多数是免费的。如果您想自己动手,那么希望我上面所说的内容和下面的橡皮筋代码足以让您到达那里并对作为 GUI 的 Java 有更深入的了解。我个人希望您自己承担——这种语言迫切需要更多真正了解该语言及其设计的“核心”人员,而不仅仅是如何“工作”Hibernate 和 Spring 等框架...

祝你好运,希望对你有所帮助,

西马

就“橡皮筋”选择代码而言,这是我过去使用过的代码,只需将其视为 GLP 并在需要时使用它...

首先是监听器接口(interface):

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

关于Java Swing 自定义形状(2D 图形),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2483533/

相关文章:

java - 如何对 Spring 存储库进行单元测试

java - 学习 Java Swing(是否使用 GUI 构建器?)

java - 如何在处理结束时显示 "Loading..."消息自动关闭(类似于Progress Bar)?

java - 在 Canvas 上及时移动点,Android 中的速度(java)

java - 从同一包中的主类访问无状态 session bean

java - 如何在 NetBeans GUI Builder 中实现所见即所得?

Java Swing - TableLayout - 未从布局中删除的组件

php - 在 PDF 文件中绘图

ios - 三角形与 Quartz 2D 绘图完美对齐

java - 传递带有异常的枚举 - Java