【问题标题】:Java Swing custom shapes (2D Graphics)Java Swing 自定义形状(2D 图形)
【发布时间】:2019-07-04 17:39:42
【问题描述】:

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

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

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

应该可以编辑绘制的形状

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

我看到人们创建了一个自己的类来实现 Shape 类并使用 GeneralPath。但是我也不知道这是否是一个好方法。

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

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

提前致谢!!

【问题讨论】:

    标签: java swing drawing 2d


    【解决方案1】:

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

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

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

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

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

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

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

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

    WM

    就“Rubber-band”选择代码而言,这是我过去使用过的,只需考虑 GLP 并根据需要使用它...

    首先是 Listener 接口:

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

    【讨论】:

    • 哇,感谢 Wintermute!我是 Java 初学者,但我会检查这段代码,我想它会对我有很大帮助!现在要研究这段代码是如何工作的,并尝试修改它以适应我的需要。 (还有框架,好吧,我现在宁愿不使用它们;))
    • 谢谢你,trashgod,我用它有点快——我确实确保它仍然编译——因为我确实从我之前写的一个相当复杂的 GUI 框架中抽象出来,而且我仍然掌握该网站仍然提供的编辑功能。 juFo:非常欢迎您。总的来说,我多年来一直是 Java 作为一门语言的拥护者。为此,我可以让某人将其视为不仅仅是获得“快速”解决方案的一种方式,而是希望真正将其理解为大多数问题空间的整体解决方案。
    【解决方案2】:

    ImageJ 项目有一个特别好的实现 Polygon tool 可调整顶点,如 herehere 所示。

    【讨论】:

      【解决方案3】:

      你看过java中的Graphics类吗(还有一个Polygon类)?有绘制和填充多边形方法,每个方法都可以接收一组 x 坐标和 y 坐标。通过使用这些数组,您应该能够相当轻松地更改点的位置。就像您可以对所有这些点进行相同的更改以重新调整大小,或者通过平均移动所有点来复制和粘贴。更改颜色就像填充新颜色并重新绘制一样简单。

      【讨论】:

      • 当我想调整它的大小时,我想要一个自定义光标和一个边界框来告诉我我可以点击并拖动它来调整它的大小,我该怎么做?
      • 您可以更改事件上的光标。就像您可以添加鼠标单击的侦听器或鼠标拖动的侦听器或类似的东西。您可以在绘制方法中拖动鼠标时设置一些布尔变量。所以,如果你在拖动,你可以在你想要的地方画你的边界框,或者做同样的事情来剪切和粘贴。
      • blog.codebeach.com/2008/02/using-custom-cursors-in-java.html 这是一个展示如何使用自定义光标的链接。
      • 这里是一个使用鼠标运动监听器的例子:leepoint.net/notes-java/examples/mouse/20dragdemo.html
      猜你喜欢
      • 2010-12-20
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 2012-11-07
      • 1970-01-01
      相关资源
      最近更新 更多