Java Swing 自定义形状(二维图形) [英] Java Swing custom shapes (2D Graphics)

查看:49
本文介绍了Java Swing 自定义形状(二维图形)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to draw custom shapes. Now when a user clicks on several points on the panel I create a shape using a polygon.

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

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

But I don't know if this is the best way to draw custom shapes.

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

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

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

I have seen people creating an own class implementing the Shape class and using a GeneralPath. But again I have no idea if this is a good way.

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

Now I can create my own shape with a polygon (or with a GeneralPath) but I have no clue how to attach all the edit functions to my own shape (the edit functions I mean the resize, move, etc from above).

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

I hope somebody could show me a way to do this or maybe write a little bit of code to demonstrate this.

提前致谢!!

推荐答案

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

In answer to your question, I would definitely do what you describe as an AWT solution--that way you can track the objects created and be able to allow the user to reload them onto an edit Canvas and more than likely each of the shapes the user creates would be a "layer" not the Layer Swing Container, but an object that would store and track what shapes are drawn and be able to redraw them--the main thing to keep in mind is "Draw order". Basically you can do this by assigning each object or group of object that are your "shapes" to have a Z=[0-100] etc. (100, can be any number) which determine what order each of the object/shapes are drawn in and thus how they over lay each other.

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

Basically you are going to need a shape class that stores the

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

It should be possible to edit a drawn shape:

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

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

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

you outlined and a storage object/manager that will enumerate the shape class objects/instances that are created. This classes will more or less be contained by a java.awt.Canvas container that will actually handle all the graphics.

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

Mostly you want to use awt over Swing due to the fact Swing is not Thread safe--that way you do not "paint yourself in the corner" early on in your design. Another reason is this is an implementation that needs to respond and interact in a way that a user is used to. Swing is built over the AWT and adds a great deal of complexity that an application like this doesn't need. Over all you are going to be creating a class Custom component that is exactly what the Canvas object was mean to provide and if Sun would have kept this tact earlier on they would not have gotten into the mess that Swing turned out to be... The Developer community--myself included--were well on the way to creating a lot of what Swing offered in "slickness" and component based design, but what we were building was totally AWT based. When Swing entered the scene, Java as a GUI platform was greatly complicated and started Sun and Java down a slippery path...

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

Also you have to decide what you ultimately want as far as control over what you are creating here. If you need it fast and do not really care about modifying it in the future, then there are lots of open-source examples that can do this--most for free. If you want to do it yourself, then hopefully what I have talked about above and the rubber band code below will be enough to get you there and have a deeper understanding of Java as a GUI. I personally hope you take it on yourself--this language desperately needs more "core" people that truly understand the Language and its design and not just how to "work" frameworks like Hibernate and Spring among others...

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

Good luck hope this helps,

WM

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

As far as "Rubber-band" select code goes, this is mine I have used in the past, just consider it GLP and use it as you need to...

首先是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 中都应该没问题

Here is the class which is a custom AWT component--it should be fine in either Swing/AWT probably even 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 自定义形状(二维图形)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆