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

2024-05-26

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

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

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

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

  • resize
  • 改变它的填充颜色
  • 更改描边颜色
  • 复制/粘贴它
  • 移动多边形的单个点
  • ...

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

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

我希望有人可以向我展示一种方法来做到这一点,或者编写一些代码来演示这一点。

提前致谢!!


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

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

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

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

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

大多数情况下,您希望使用 awt 而不是 Swing,因为 Swing 不是线程安全的——这样您就不会在设计的早期“把自己逼到角落”。另一个原因是这是一个需要以用户习惯的方式进行响应和交互的实现。 Swing 是基于 AWT 构建的,并增加了很多像这样的应用程序不需要的复杂性。总而言之,您将创建一个类自定义组件,这正是 Canvas 对象的含义 提供,如果 Sun 早点保持这种策略,他们就不会进入 Swing 原来是一团糟……开发人员社区(包括我自己)正在努力创建 Swing 提供的许多“流畅”和基于组件的设计,但我们正在构建的完全是基于 AWT 的。当 Swing 出现时,Java 作为 GUI 平台变得非常复杂,并让 Sun 和 Java 走上了一条艰难的道路……

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

祝你好运,希望这会有帮助,

WM

就“橡皮筋”选择代码而言,这是我过去使用过的,只需考虑它 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;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java Swing 自定义形状(2D 图形) 的相关文章

  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐