简单模拟word中对插入直线的操作。可以画直线,然后可以选择直线进行移动、拉伸、删除。并能显示直线的距离。
操作:点击按钮开始画线。鼠标左键点击一条直线进行移动,选择端点进行拉伸。

鼠标右键点击直线,删除它。

附上源代码

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputListener;class MyLine {int a, b, c, d;// shape后直线的两个端点boolean isSelected;boolean isSelectP0; // 选择线段的一个端点boolean isSelectP1;// 选择线段的另一个端点public static float lineWidth = 0.5f; // 线宽static float len = 1.0f;  //线宽的改变主要靠该参数GeneralPath shape;double distance;int x0, y0, x1, y1;public void constructShape() {int m = Math.round(len / 2);a = x0 + m;b = y0 + m;c = x1 + m;d = y1 + m;double[] px = new double[4];double[] py = new double[4];/*double */distance = Math.hypot(c - a, d - b);if (c == a) {px[0] = a + len;py[0] = b;px[1] = c + len;py[1] = d;px[2] = c - len;py[2] = d;px[3] = a - len;py[3] = b;} else if (d == b) {px[0] = a;py[0] = b - len;px[1] = c;py[1] = d - len;px[2] = c;py[2] = d + len;px[3] = a;py[3] = b + len;} else {double sin = (c - a) / distance;double cos = (d - b) / distance;px[0] = a + len * cos;py[0] = b - len * sin;px[1] = c + len * cos;py[1] = d - len * sin;px[2] = c - len * cos;py[2] = d + len * sin;px[3] = a - len * cos;py[3] = b + len * sin;}shape = new GeneralPath(Path2D.WIND_NON_ZERO);shape.moveTo(px[0], py[0]);shape.lineTo(px[1], py[1]);shape.lineTo(px[2], py[2]);shape.lineTo(px[3], py[3]);shape.closePath();}public boolean contains(int x, int y) {return Path2D.contains(shape.getPathIterator(null), new Point2D.Float(x, y));}
}
/*** 在面板上画线,可以选择直线,可以移动、拉伸、删除直线。* @author Limit* @date 2011.12.30*/
public class TestLine extends JPanel {class MyMouseListener implements MouseInputListener {Point oldPoint;boolean isDragge;private void constructXY0(MyLine ln, int x, int y) {if (x > getWidth())ln.x0 = getWidth();else if (x < 0)ln.x0 = 0;elseln.x0 = x;if (y > getHeight())ln.y0 = getHeight();else if (y < 0)ln.y0 = 0;elseln.y0 = y;}private void constructXY1(MyLine ln, int x, int y) {if (x > getWidth())ln.x1 = getWidth();else if (x < 0)ln.x1 = 0;elseln.x1 = x;if (y > getHeight())ln.y1 = getHeight();else if (y < 0)ln.y1 = 0;elseln.y1 = y;}@Overridepublic void mouseClicked(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}@Overridepublic void mouseMoved(MouseEvent e) {/** 判断是否移动到某直线上或者直线的端点上 **/setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));if (pressIndex != 3)pressIndex = 0;// 先清空for (MyLine line : lines) {line.isSelectP0 = false;line.isSelectP1 = false;line.isSelected = false;}if (pressIndex == 3) {setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));return;}// 判断是否选中直线,若是则将光标改变for (MyLine line : lines) {if (line.contains(e.getX(), e.getY())) {line.isSelected = true;pressIndex = 1;setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));break;}}// 如果选中了某条直线,再判断该直线的端点是否被选中if (selectedLine != null) {MyLine line = selectedLine;Point p1 = new Point(line.a, line.b); // 左端点Point p2 = new Point(line.c, line.d); // 右端点Point p = new Point(e.getX(), e.getY());if (isRange(p1, p)) {line.isSelectP0 = true;pressIndex = 2;setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));}if (isRange(p2, p)) {line.isSelectP1 = true;pressIndex = 2;setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));}}}@Overridepublic void mousePressed(MouseEvent e) {switch (pressIndex) {case 0:selectedLine = null;for (MyLine line : lines) {line.isSelectP0 = false;line.isSelectP1 = false;line.isSelected = false;}break;case 1:for (MyLine line : lines) {if (line.isSelected) {selectedLine = line;break;}}tmpSelectedLine = new MyLine();tmpSelectedLine.x0 = selectedLine.x0;tmpSelectedLine.x1 = selectedLine.x1;tmpSelectedLine.y0 = selectedLine.y0;tmpSelectedLine.y1 = selectedLine.y1;tmpSelectedLine.constructShape();oldPoint = new Point(e.getX(), e.getY());break;case 2:break;case 3:inLine = new MyLine();inLine.x0 = e.getX();inLine.y0 = e.getY();break;default:break;}}@Overridepublic void mouseDragged(MouseEvent e) {switch (pressIndex) {case 0:break;case 1:Point point = new Point(e.getX(), e.getY());int lenx = point.x - oldPoint.x;int leny = point.y - oldPoint.y;tmpSelectedLine.x0 = selectedLine.x0 + lenx;tmpSelectedLine.x1 = selectedLine.x1 + lenx;tmpSelectedLine.y0 = selectedLine.y0 + leny;tmpSelectedLine.y1 = selectedLine.y1 + leny;tmpSelectedLine.constructShape();isDragge = true;break;case 2:MyLine line = selectedLine;// lines.get(selectPointInWhichLine);if (line.isSelectP0) {constructXY0(line, e.getX(), e.getY());}if (line.isSelectP1) {constructXY1(line, e.getX(), e.getY());}line.constructShape();break;case 3:constructXY1(inLine, e.getX(), e.getY());inLine.constructShape();break;default:break;}repaint();}@Overridepublic void mouseReleased(MouseEvent e) {switch (pressIndex) {case 0:break;case 1:Point point = new Point(e.getX(), e.getY());int lenx = point.x - oldPoint.x;int leny = point.y - oldPoint.y;selectedLine.x0 += lenx;selectedLine.x1 += lenx;selectedLine.y0 += leny;selectedLine.y1 += leny;selectedLine.constructShape();tmpSelectedLine = null;if (!isDragge && e.isPopupTrigger()) {popup.show(e.getComponent(), e.getX(), e.getY());}isDragge = false;break;case 2:MyLine line = selectedLine;if (line.isSelectP0) {constructXY0(line, e.getX(), e.getY());}if (line.isSelectP1) {constructXY1(line, e.getX(), e.getY());}line.constructShape();break;case 3:constructXY1(inLine, e.getX(), e.getY());inLine.constructShape();lines.add(inLine);selectedLine = inLine;selectedLine.isSelected = true;inLine = null;pressIndex = 0;break;default:break;}// 统一在鼠标释放的时候重绘repaint();}}class PopupAction extends AbstractAction {/*** */private static final long serialVersionUID = 1L;public PopupAction(String name) {super(name);}@Overridepublic void actionPerformed(ActionEvent e) {if (lines.remove(selectedLine)) {selectedLine = null;pressIndex = 0;// selectWhichLine = -1;// selectPointInWhichLine = -1;JOptionPane.showMessageDialog(null, "remove success", "Teemo", JOptionPane.INFORMATION_MESSAGE);}repaint();}}/*** */private static final long serialVersionUID = 1L;public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {final JFrame frame = new JFrame();frame.setSize(400, 400);frame.setVisible(true);frame.setLocationRelativeTo(null);JButton jb = new JButton("add line");final TestLine tl = new TestLine();jb.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// tl.isDrawingLine = true;tl.pressIndex = 3;}});frame.getContentPane().add(jb, BorderLayout.NORTH);frame.getContentPane().add(tl, BorderLayout.CENTER);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}});}private List<MyLine> lines = new ArrayList<MyLine>();private MyLine inLine;private float range = 4f;JPopupMenu popup;private MyLine selectedLine; // 选中的lineMyLine tmpSelectedLine; // 移动时临时的线/*** 4种状态:0无任何状态1选中直线2选中端点3开始画线*/int pressIndex = 0;public TestLine() {MyMouseListener ml = new MyMouseListener();addMouseListener(ml);addMouseMotionListener(ml);// addMouseListener(pl);constructPopup();}private void constructPopup() {popup = new JPopupMenu();JMenuItem menuItem = new JMenuItem();menuItem.setAction(new PopupAction("remove line"));popup.add(menuItem);}/*** 判断两个点是否离得很近 近的标准用range来横来* * @param a*                第一个点坐标* @param b*                第二点坐标* @return 离得近为真,否则为假*/private boolean isRange(Point a, Point b) {if (Math.hypot(a.x - b.x, a.y - b.y) < range)return true;return false;}// 画图的按钮的背景和标签protected void paintComponent(Graphics g2) {super.paintComponents(g2);g2.setColor(new Color(255, 255, 255));g2.fillRect(0, 0, getWidth(), getHeight());Graphics2D g = (Graphics2D) g2;Paint oldPaint = g.getPaint();Stroke s = g.getStroke();int i = 0;for (MyLine line : lines) {g.setStroke(new BasicStroke(MyLine.lineWidth));g.setPaint(Color.BLACK);GeneralPath shape = line.shape;g.drawString(i++ + "", line.x0, line.y0);int midx = Math.round((line.x0 + line.x1) / 2.0f);int midy = Math.round((line.y0 + line.y1) / 2.0f);g.drawString(String.format("%.2f", line.distance), midx, midy);g.fill(shape);}// 如果被选择,那么直线的两端应该会有两个黑点if (selectedLine != null) {MyLine line = selectedLine;g.setPaint(Color.BLACK);int l = 6;g.drawOval(line.a - l / 2, line.b - l / 2, l, l);g.drawOval(line.c - l / 2, line.d - l / 2, l, l);g.setPaint(Color.GREEN);g.fillOval(line.a - l / 2, line.b - l / 2, l, l);g.fillOval(line.c - l / 2, line.d - l / 2, l, l);}if (tmpSelectedLine != null) {g.setStroke(new BasicStroke(MyLine.lineWidth));g.setPaint(Color.BLACK);GeneralPath shape = tmpSelectedLine.shape;g.fill(shape);}// 画正在产生的直线if (inLine != null) {g.setStroke(new BasicStroke(MyLine.lineWidth));g.setPaint(Color.BLACK);GeneralPath shape = inLine.shape;if (shape != null)g.fill(shape);}g.setPaint(oldPaint);g.setStroke(s);g2.dispose();}
}

简单模拟word中对插入直线的操作相关推荐

  1. Word中的插入页眉 ?Word中页眉横线如何删除?

    文章目录 Word中的插入页眉方法 方法1: 方法2: 2 5种方法 删除页眉横线 方法1: 方法2: 方法3: 方法4: 方法5: 当我们给Word添加完页眉的时候,会发现,被添加的页眉下面有一条横 ...

  2. WORD中自动插入图表标签

    在WORD中自动插入图表标签的主要菜单项为"插入"菜单下的"应用"菜单下的"题注-"和"交叉应用"两个菜单项. 1. 自 ...

  3. 【Get深一度】Microsoft Office 2013 Word中图片插入后变模糊解决办法

     Microsoft Office 2013 Word中图片插入后变模糊解决办法 作者在使用Word时发现插入的图片变模糊了,这个问题以前也经常遇到,只是从未上心过,这次花点心思解决一下,也给众多 ...

  4. word中如何插入abcd英文字母的页码 页码word中怎么做插入abcd英文字母的 oldtimeblog

    word中如何插入abcd英文字母的页码 页码word中怎么做插入abcd英文字母的页码 word中插入页码的时候,默认是插入的123数字页码,想要插入abcd英文字母页码,该怎么插入呢?下面我们就来 ...

  5. 目录超出页边距了怎么办|word中自动插入目录,页码超出页边距如何修改

    很多同学在写论文的时候遇到word中自动插入目录但是目录的右边超过超过了页边距的界限了,以下为解决方法的操作步骤 1.全选目录 2.右击,选择"段落" 3.选择制表位 4. 设置制 ...

  6. word中如何插入 符号_如何在Word中插入版权或商标符号

    word中如何插入 符号 You can easily insert hundreds of symbols into your Word document with a few nimble key ...

  7. word中如何插入 符号_如何在Word 2013中使用符号

    word中如何插入 符号 Hundreds of symbols that are not available on your keyboard are provided in Microsoft W ...

  8. word中如何插入一个横线

    (1)如果横线不长,可以采用设置下划线的方法:先按一下下划线工具"U",再根据需要输入几个字符,按一些空格.例如:"姓名"."学校"后边跟的 ...

  9. Word2003入门动画教程77:在Word中如何插入艺术字

    Word 2003是微软公司提供的一款文字处理软件,可以对文字进行 排版 和编辑.分段等各种处理,最终将编辑好的内容打印出来,是办公室一族中必备的办公软件之一.我们在使用Word文档的时候,有时为了达 ...

最新文章

  1. 南京大学计算机考研机试,2018南大CS考研机试答案
  2. C#中使用Monitor类、Lock和Mutex类来同步多线程的执行(转)
  3. CF1407D Discrete Centrifugal Jumps(单调队列+DP)
  4. 【Android应用开发】Android 蓝牙低功耗 (BLE) ( 第一篇 . 概述 . 蓝牙低功耗文档 翻译)
  5. 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值
  6. 二叉树的遍历(算法导论第三版12.1-4)(包含先序遍历,后序遍历和中序遍历)
  7. 使用Kotlin的Android菜单
  8. 获取验证码 60秒后重新获取
  9. plc编程软件通过计算机,英威腾PLC编程软件(Auto Station)
  10. 黑莓7290软件_黑莓7290,我买的是情怀
  11. 有趣!让你的桌面独一无二——iWall for Mac2.1.1破解版可以交互的动态桌面壁纸!
  12. Power bi 4.19 龙卷风图
  13. 计算机网络几种常见协议
  14. wifi热点创建和自动连接
  15. 力扣股神之路动态规划
  16. 590. N-ary Tree Postorder Traversal*
  17. QTP_QTP学习笔记(1)
  18. 微软 Microsoft
  19. 大数据Flink(十四):流批一体API Connectors JDBC
  20. vue VantUI组件初探 使用

热门文章

  1. 我定义的价值观和行为准则
  2. 亚马逊运营自然订单减少了该怎么办?
  3. 盒子垂直居中的三种办法
  4. 07_Ensemble Learning and Random Forests_Bagging_Out-of-Bag_Random Forests_Extra-Trees极端随机树_Boosting
  5. HDU 4489 The King's Ups and Downs
  6. 携职教育:为什么要考中级会计证?落户补贴、职场进阶…
  7. 在c++中hex/oct/dec的用法
  8. TreeView安装使用集锦
  9. FISCO BCOS——SmartDev-Contract——Traceability商品溯源合约案例分析
  10. python调用函数来判断质数_Python计算-质数的判断