⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shapepane.java

📁 用于串口通讯测试的工具软件。完全使用java语言编写。
💻 JAVA
字号:
package com.zcsoft.graphics.line;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.MouseInputListener;
import com.zcsoft.graphics.*;
/*
 * Title:        示例程序
 * Description:  为使用公司开发工具软件的用户提供软件实现示例代码
 * Copyright:    Copyright (c) 2001
 * Company:      苏州至诚软件
 * @author 蒋智湘
 * @version 2.0
 */
/**
 * 图形绘制面板。
 * 当前实现的功能有:
 * <ol>
 *  <li>图形控制点信息捕捉</li>
 *  <li>图形选择</li>
 *  <li>图形控制点移动</li>
 *  <li>图形移动</li>
 * </ol>
 */
public class ShapePane extends JComponent implements MouseInputListener

{
	/** 要绘制的图形列表 */
	private Vector shapeMakers = new Vector();
	/**
	* 当前选中的图形
	*/
	private transient int currentShape=-1;
//	/**
//	* 当前选中的图形的各个节点中选中的节点
//	*/
//	private transient int currentPoint=-1;
	/**
	* 鼠标拖动时,上一次拖动事件发生时所到的点
	*/
	private transient Point last=null;
	/**
	* 判断鼠标是否在里面
	*/
	//private transient boolean in=false;
	/** 是否支持鼠标移动事件的处理 */
	private boolean mouseMotionEnabled;

	/**
	*   构造一个没有任何图形的面板
	*/
	public ShapePane()
	{
		enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
		setBackground(java.awt.Color.black);
		setForeground(java.awt.Color.yellow);
		this.addMouseListener(this);
		setMouseMotionEnabled(true);
		ToolTipManager ttm = ToolTipManager.sharedInstance();
		ttm.registerComponent(this);
		ttm.setDismissDelay(3000);
		ttm.setInitialDelay(100);
	}

	/**
	 * 设定绘制面板支持对鼠标移动事件的处理
	 * @param yes
	 */
	public void setMouseMotionEnabled(boolean yes)
	{
		if (mouseMotionEnabled == yes)
		{
			return;
		}
		mouseMotionEnabled = yes;
		if (yes)
		{
			this.addMouseMotionListener(this);
		}
		else
		{
			this.removeMouseMotionListener(this);
		}
	}

	/**
	 * 判断是否允许了该绘制面板对鼠标移动事件的处理
	 * @return
	 */
	public boolean isMouseMotionEnabled()
	{
		return this.mouseMotionEnabled;
	}

	/**
	 * 处理键盘事件
	 * 当敲击回车键且无修饰键时,相当于单击鼠标左键
	 * 当敲击回车键且修饰键为ALT时,相当于双击鼠标左键
	 *
	 * @since 2.0
	 */
	protected void processKeyEvent(KeyEvent e)
	{
		if(currentShape !=-1 && e.getKeyCode()==KeyEvent.VK_ENTER && e.getID() == KeyEvent.KEY_PRESSED )
		{
			ShapeMaker sm = (ShapeMaker)this.shapeMakers.get(currentShape);
			if( e.getModifiers() == 0 )
				sm.click(sm.getRange().getLocation());
			else if( e.getModifiers() == KeyEvent.ALT_MASK )
				sm.doubleClick(sm.getRange().getLocation());
		}
		else if(e.getID() == KeyEvent.KEY_PRESSED
				  && e.isAltDown() == false
				  && e.getKeyCode()==KeyEvent.VK_TAB)
		{
			if (e.isControlDown())
			{
				this.transferFocus();
			}
			else if(this.getShapeMakerCnt() > 0)
			{
				int newShape = currentShape;
				if( e.isShiftDown() )
				{
					newShape = newShape > 0?(newShape - 1):(this.getShapeMakerCnt() - 1);
				}
				else
				{
					newShape = newShape < (this.getShapeMakerCnt() - 1)?(newShape + 1):0;
				}
				this.setSelectedShape(newShape, -1);
			}
			e.consume();
		}
	}

	/**
	 * 使得可以处理键盘事件
	 *
	 * @since 2.0
	 */
	public boolean isFocusTraversable()
	{
		return isEnabled();
	}



	/**
	* 添加图形构造器
	* @exception NullPointerException 添加图形绘制器为null
	*/
	public synchronized void addShapeMaker(ShapeMaker sm)
	{
		if(sm==null)
			throw new NullPointerException("sm is null");
		shapeMakers.add(sm);
	}
	/**
	* 获得指定的图形构造器
	*/
	public ShapeMaker getShapeMaker(int indx)
	{
		return (ShapeMaker)shapeMakers.get(indx);
	}
	/**
	* 获得已有的图形构造器的数目
	*/
	public int getShapeMakerCnt()
	{
		return shapeMakers.size();
	}
	/**
	* 删除指定图形构造器
	*/
	public synchronized void removeShapeMaker(ShapeMaker sm)
	{
		int index = this.shapeMakers.indexOf(sm);
		if (index != -1)
		{
			this.removeShapeMaker(index);
		}
	}
	/**
	* 删除指定图形构造器
	*/
	public synchronized void removeShapeMaker(int indx)
	{
		shapeMakers.remove(indx);
		if (indx == this.currentShape)
		{
			this.currentShape = -1;
//			this.currentPoint = -1;
		}
	}
	/**
	* 删除所有图形构造器
	*/
	public synchronized void removeAllShapeMakers()
	{
		shapeMakers.removeAllElements();
		this.currentShape = -1;
//		this.currentPoint = -1;
	}

	public void paint(java.awt.Graphics g)
	{
		if (this.getWidth() == 0 || this.getHeight() == 0 || this.isShowing() == false)
		{
			return;
		}

		g.setColor(this.getBackground());
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		g.setColor(this.getForeground());

		this.paintComponent(g);
	}

	/**
	 * 绘制图形
	 */
	protected void paintComponent(java.awt.Graphics g)
	{
		Rectangle bounds = g.getClipBounds();

		for (int i = shapeMakers.size() - 1; i >= 0; i--)
		{
			ShapeMaker sm = this.getShapeMaker(i);
			if (sm.isVisible() && sm.intersects(bounds))
			{
				if(sm.getShapeColor() == null)
					sm.setShapeColor(this.getForeground());
				if( sm.getOwner() == null)
					sm.setOwner(this);
				sm.paint((Graphics2D)g.create());
			}
		}
	}

	/**
	 * 处理鼠标点击事件。
	 *
	 * @since 2.0
	 */
	public void mouseClicked(MouseEvent e)
	{
		if (this.currentShape!=-1)
		{
			if (SwingUtilities.isLeftMouseButton(e))
			{
				ShapeMaker sm = (ShapeMaker)this.shapeMakers.get(currentShape);
				if(e.getClickCount() > 1 )
				{
					sm.doubleClick(e.getPoint());
				}
				else
				{
					sm.click(e.getPoint());
				}
			}
		}
	}
	/**
	* 处理鼠标按钮按下时的事件
	*/
	public void mousePressed(MouseEvent e)
	{
		if ( !this.hasFocus() )
		{
			this.requestFocus();
		}
		if(SwingUtilities.isMiddleMouseButton(e))
			return;
		Point p = e.getPoint();
		last = p;

		int currentPoint = -1;
		int currentShape = findMakerAt(p);
		if (currentShape != -1)
		{
			currentPoint = this.getShapeMaker(currentShape).findControlPointUnder(p);
		}

		this.setSelectedShape(currentShape, currentPoint);
	}

	/**
	 * 找到指定点下的绘制器。
	 * 如果该点下存在多个重叠的绘制器,则找最小区域的那个。
	 * 查找时,不遍历不可见的绘制器。
	 * @param p
	 * @return
	 */
	protected int findMakerAt(Point p)
	{
		Rectangle bounds, minimumBounds = null;
		ShapeMaker sm;
		int index = -1;
		for (int i = shapeMakers.size() - 1; i >= 0 ; i--)
		{
			sm = (ShapeMaker)this.shapeMakers.get(i);
			if (sm.isVisible() && sm.contains(p))
			{
				bounds = sm.getRange();
				if (minimumBounds == null
					 || minimumBounds.contains(bounds))
				{
					index = i;
					minimumBounds = bounds;
				}
			}
		}
		return index;
	}

	/** @todo 设置选中的图形
	 *
	 * @param cs 当前选中图形
	 * @param cp 当前选中的控制点
	 *
	 * @return 是否改变选择图形或控制点
	 *
	 * @since 2.0
	 */
	protected boolean setSelectedShape(int cs, int cp)
	{
		int oldShape = this.currentShape;
		this.currentShape = cs;

		ShapeMaker sm = null;

		if(cs != oldShape)
		{
			if(cs != -1 )
			{
				sm = getShapeMaker(cs);
				sm.setSelectedPoint(cp);
				sm.setSelected(true);
			}
			if(oldShape != -1)
			{
				getShapeMaker(oldShape).setSelected(false);
			}
		}
		else if( cs != -1 )
		{
			sm = (ShapeMaker)shapeMakers.get(cs);
			sm.setSelectedPoint(cp);
			sm.setSelected(true);
		}
		return sm != null;
	}

	/**
	 * 处理鼠标按钮弹起时的事件
	 */
	public void mouseReleased(MouseEvent e)
	{
		last = null;
		if(e.isPopupTrigger())
		{
			if (this.currentShape == -1)
			{
				this.mousePressed(e);
			}
			if (this.currentShape == -1)
			{
				return ;
			}
			ShapeMaker sm = this.getShapeMaker(currentShape);
			Point p = e.getPoint();
			if (sm.contains(p))
			{
				JPopupMenu pop = sm.getContextMenu(p);
				if (pop != null)
				{
					ShapePane.getLocationRelativeTo(pop, this, p);
					pop.show(this, p.x, p.y);
				}
			}
		}
	}

	/**
	 * 已知组件invoker上的某点p,求得组件me在屏幕上的正确位置,即如果组件
	 * 所求得点上显示,则尽可能保证组件me全部在屏幕的可是范围内。
	 * <BR>
	 * 同时更改点p的位置为所求得位置相对于组件invoker的新位置。
	 *
	 * @param me 想在屏幕正确位置上显示的组件
	 * @param invoker
	 * @param p 组件invoker上的某个点。其坐标原点在invoker所在矩形区域的
	 *          左上角
	 * @return 待求的组件位置
	 */
	public static Point getLocationRelativeTo(Component me
		, Component invoker
		, Point p)
	{
		Point loc = invoker.getLocationOnScreen();
		int x = loc.x + p.x,
			y = loc.y + p.y;
		Dimension size = me.getPreferredSize(),
					ss = JOptionPane.getRootFrame().getSize();
		int offset = (x + size.width) - ss.width;
		if (offset > 0)
		{
			x -= offset;//size.width;
		}
		offset = (y + size.height) - ss.height;
		if (offset>0)
		{
			if (y>size.height)
				y -= size.height;
			else
				y -= offset;
		}
		p.setLocation(x-loc.x, y-loc.y);
		return new Point(x, y);
	}

	/**
	 * 处理鼠标进入面板事件
	 */
	public void mouseEntered(MouseEvent e)
	{
		//in=true;
	}

	/**
	 * 处理鼠标移出面板事件
	 */
	public void mouseExited(MouseEvent e)
	{
		//in=false;
	}

	/**
	 * 鼠标拖动事件侦听实现
	 * 如果选择了图形上的某个控制点,该方法就完成移动该控制点的功能,
	 * 否则,如果当前选中了图形,则方法就完成移动该控制点的功能。
	 */
	public void mouseDragged(MouseEvent e)
	{
		Point p = e.getPoint();
		if(currentShape == -1
			|| last == null
			|| !this.getVisibleRect().contains(p))
		{
			return;
		}
		ShapeMaker sm = (ShapeMaker)shapeMakers.get(currentShape);
		Rectangle oldBounds = sm.getRange();
		boolean b;
		if( sm.isMovable() && sm.getSelectedPoint() < 0) //移动整个图形
		{
			b = sm.translate(p.getX()-last.getX(),p.getY()-last.getY());
			if(b)
			{
				last = p;
				repaint(oldBounds.union(sm.getRange()));
			}
		}
		else //移动一个点
		{
			b = ((ShapeMaker)shapeMakers.get(currentShape)).refreshPoint(sm.getSelectedPoint()
						, new DoublePoint(p.getX(), p.getY()) );
			if(b)
			{
				this.setCursor(sm.getCuror(sm.getSelectedPoint()));
				repaint(oldBounds.union(sm.getRange()));
			}
		}
	}

	/**
	* 鼠标移动事件侦听实现
	*
	* 实现设置工具提示和设置光标功能
	*
	*/
	public void mouseMoved(MouseEvent e)
	{
		ShapeMaker sm;
		Point p = e.getPoint();
		this.setCursor(Cursor.getDefaultCursor());
		int shapeIndx = this.findMakerAt(p);
		if(shapeIndx != -1)
		{
			sm = this.getShapeMaker(shapeIndx);
			int indexControlPoint = sm.findControlPointUnder(p);
			if (indexControlPoint != -1)
			{
				//更新工具提示内容为控制点信息
				this.setCursor(sm.getCuror(indexControlPoint));
				Object pointInfo = sm.getPointInfo(indexControlPoint);
				this.setToolTipText(pointInfo==null?null:pointInfo.toString());
				return ;
			}
		}
		//没有找到点但找到图形,如果选中的图形可以被移动,则设置选中的图形的光标为移动光标
		if ( shapeIndx == currentShape && shapeIndx != -1)
		{
			sm = (ShapeMaker)this.shapeMakers.get(shapeIndx);
			if(sm.isMovable())
			  this.setCursor( sm.getMovingCursor());
		}

		if( shapeIndx != -1 )
			this.setToolTipText(((ShapeMaker)this.shapeMakers.get(shapeIndx)).getToolTipText(p));
		else
			this.setToolTipText(null);//取消工具提示
	}

	/**
	 * 设置工具提示内容
	 *
	 * @param txt 工具提示内容,支持HTML格式,
	 *  但不包含<code>&lt;html&gt;</code>和<code>&lt;/html&gt;</code>标记。
	 */
	public void setToolTipText(String txt)
	{
		super.putClientProperty(super.TOOL_TIP_TEXT_KEY,txt!=null?("<html>".concat(txt).concat("</html>")):null);
	}

	/**
	 * 获取选中的图形绘制器
	 * @return 选中的图形绘制器。如果没有选中的图形,则为null
	 */
	public ShapeMaker getSelectedShape()
	{
		return this.currentShape != -1?this.getShapeMaker(this.currentShape):null;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -