前两天写了个作业:在面板(Panel)上显示一张图片,并能够用鼠标随意拖动,将图片放置于任何位置。
 见:http://blog.csdn.net/caoxiongjun/archive/2006/09/19/1246533.aspx
    在完成那个作业后,我又想,在我双击图片后,能不能像photoshop那样,在“全选”之后,图片周围出现流动的虚线框的效果,想到就去做,于是我又研究了起来,那么,现在跟着我来看看,我是怎么实现的吧!(程序可能存在些不足,还请高手们指正).

第一步:认识虚线
        请看下图,虚线其实是由一条条不连续的"实线段"组成的,这里实线段是白色的部分,背景色是黑色,我们暂且称实线段之间间隔的空余部分为“虚线段”.

第二步:画虚线
   java的Graphics提供了画直线的方法:drawLine(int x1,int x2,int y1,int y2),
其功能是画一条从点 (x1,y1)到 点 (x2,y2)的一条直线。
   假如,我们想画一条从点 (x1,y1) 到 点 (x2,y2)的虚线,那我们该怎么做呢?是直接调用Graphics的drawLine()方法吗?显然不是,drawLine()画的是实线。那Graphics有提供实现画虚线效果的方法吗?没有,我没在java的document中找到有这种功能的方法。那现在,我们只能自己动手了(利用drawLine()方法)。

参看上图,假设,我们要画的虚线的 实现段 和 虚线段,其长度都为4个像素,那么其虚线就是:
         4个像素的线段----4个像素的空余----4个像素的线段----4个像素的空余--.......
用程序实现的过程就是:
 画4个像素的线段----跳过4个像素----画4个像素的线段----跳过4个像素----......直到达到了所要的虚线长度.代码如下:(只适用于水平线和垂直线)

     public   void  drawDashed(Graphics g,  int  x1,  int  y1,  int  x2,  int  y2)
     ... {
        int x = x1,y=y1;
        int n = 4;  //实线段长度
        int m = 4;  //虚线段长度
        
        int tx = 0,ty = 0;
        
        int c = 0;
        boolean flag = true;  //标记 有没有画完(达到要求的长度)
        
        int mark_x = 0;  //标记 要画的是 水平线(值为1)
        int mark_y = 0;  //标记 要画的是 垂直线(值为1)
        //要么0,要么 1
        if(x2-x1 != 0)
            mark_x = 1;
        else
            mark_y = 1;
        
        do
        ...{
            tx = (int)((c*(n+m) - m)*mark_x + x1 );    
            ty = (int)((c*(n+m) - m)*mark_y + y1 );   

            if(Math.abs(tx-x1) > Math.abs(x2-x1))
            ...{
                tx = x2;
                flag = false;
            }
            if(Math.abs(ty - y1) > Math.abs(y2 - y1))
            ...{
                ty = y2;
                flag = false;
            }
            g.drawLine(x,y,tx,ty);
            x = (int)(c*(n+m)*mark_x + x1 );    //更新 实线段 + 虚线段
            y = (int)(c*(n+m)*mark_y + y1 );
            
            if(x > x2 || y > y2) break;
            c++;
        }
        while(flag);
    }

第三步: 流动原理
   好了,会画虚线了,现在让我们来看看,虚线是怎么流动起来的.请看下图:

中间有条蓝线,我们假定其为一张图片的边界,蓝线的右边是一张图片,左边是不存在的空间.有过photoshop经验的朋友应该清楚,流动的虚线在视觉上好像是从图片的左边,一条条实线段,排成一列,挨个进来,然后一直往前走.循环反复.有点类似一队单列士兵队伍,正通过城门,从城外有条不紊的进来,而我们站在城内,只看到了进到城内的士兵,看不到城墙之外的其他士兵.(比喻有点不恰当,因为图片之外是没有什么线条的).上图就是组成虚线的 "实线段" 正一条接着一条的从图片之外进到图片之内.从时间0到时间6,线段正一个像素一个像素的挪动着.

第四步:实现
     分两小步走,将要画的流动虚线分成两部分: 流动虚线的第一段(实线或虚线),流动虚线的剩下部分
 A.画虚线第一段,又分两种情况:实线,虚线
    a.实线,这时实线段正穿过图片边界,进入图片内部.使用drawLine()画出进入的部分,然后计算流动虚线的第二部分的起始位置(实线进入部分的长度 + 虚线段长度)
    b.虚线,这时,前一个实线段已经整个穿过图片边界,而后续的实线段还没有开始穿越,所以不需要画线,只须计算出流动虚线的第二部风的起始位置就可以(进入的虚线部分长度)

B.画流动虚线的第二部分,由于A步骤已经计算出了该部分的起始位置,所以这里只要使用画虚线的代码,画出虚线就可以.

某个时间点的流动虚线已经画好了(静态),那么整个时间段的流动虚线(动态)怎么画呢?
while(true)
{
 1,计算某个时刻流动虚线第一个段的长度(从0到4一次变化,并且实线、虚线 交替出现)
 2,画某个时间点的流动虚线(如上所述)
}
ok,由于是while循环,会不停的工作,这样各个时间点就连贯起来了,虚线也就流动起来了.

第五步:代码

说明: 以下代码所做的工作是画流动虚线框,就像photoshop中,选择一个区域时,出现的流动框一样, 虚线从区域的左上角涌出,汇入图片右下角,其中线段会拐弯.
 int templen, boolean isReal, int lenReal 是全局变量
 templen负责控制流动的整个过程,随着其值的变化(0--4),才出现了流动的效果,
 isReal 是布尔变量,标识现在正进入图片的是实线段,还是虚线段(在画完某条流动虚线后,值会发生变化)
 lenReal 是当前正在画的流动虚线的第一部分的长度(在画完某条流动虚线后,值会发生变化)。

g.setColor(Color.black);        
 g.drawLine(x,y,x,height);
 这两条语句作用是在每次画虚线前,将上一次的虚线清空。

画虚线部分的代码做了些改动,以适应流动虚线

     private   void  drawFlowRect(Graphics g,  int  x,  int  y,  int  width,  int  height)
     ... {
        Color oldColor = g.getColor();
        templen = templen + 1;  //每次前进 1个像素,由templen控制
        if(templen >= 4)
        ...{
            templen = 0;
            isReal = !isReal;
        }
        lenReal = templen;
            
        boolean oldisReal = isReal;  //备份
        double oldlenReal = lenReal; //备份
                
        g.setColor(Color.black);          //上
        g.drawLine(x,y,width,x);
        g.setColor(Color.white);
        drawFlowLine(g, x,y,width,y);
            
        g.setColor(Color.black);         //右
        g.drawLine(width,y,width,height);
        g.setColor(Color.white);
        drawFlowLine(g, width,y,width,height);
                
                        
        isReal = oldisReal;     //还原 数据
        lenReal = oldlenReal;
                        
        g.setColor(Color.black);          //左
        g.drawLine(x,y,x,height);
        g.setColor(Color.white);
        drawFlowLine(g,x,y,x,height);
                        
        g.setColor(Color.black);         //下
        g.drawLine(x,height,width,height);
        g.setColor(Color.white);
        drawFlowLine(g, x,height,width,height);
                        
        isReal = oldisReal;     //还原 数据                
        g.setColor(oldColor);
    }
     // 画流动虚线
     // 需要返回的信息:最后一段是空的还是 实的, 以及长度
     private   void  drawFlowLine(Graphics g,  int  x1,  int  y1,  int  x2,  int  y2)
     ... {
        int x = x1,y=y1;
        int n = 4;  //实线段长度
        int m = 4;  //虚线段长度
        
        int tx = 0,ty = 0;
        
        int mark_x = 0;  //标记 如果为1 表示水平线
        int mark_y = 0;  //标记 如果为1 标识垂直线
        
        int c = 1;
        boolean flag = true;
        
        //要么0,要么 1
        if(x2-x1 != 0)
            mark_x = 1;
        else
            mark_y = 1;
        
        
        //先画流动虚线的第一部分
        if(isReal)
        ...{
            //实线
            tx = (int)(lenReal*mark_x + x1);
            ty = (int)(lenReal*mark_y + y1);
            g.drawLine(x,y,tx,ty);
            x = (int)((m + lenReal)*mark_x + x1);
            y = (int)((m + lenReal)*mark_y + y1);
            //System.out.println("画了段 实线:len : "+ tx+", (x,y)" + x + ", " + y);
        }
        else
        ...{
            //虚线
            x = (int)(lenReal*mark_x + x1);
            y = (int)(lenReal*mark_y + y1);
            //System.out.println("画了段 虚线 (x,y)" + x + ", " + y);
        }
        
        int ttx = x; //第二部分起始位置 x坐标
        int tty = y; //第二部分起始位置 y坐标
        
        
        do
        ...{    
            tx = (int)((c*(n+m) - m)*mark_x + ttx);
            ty = (int)((c*(n+m) - m)*mark_y + tty);
            
            if(Math.abs(tx-x1) > Math.abs(x2-x1))
            ...{
                //System.out.println(" 越界了:tx = " + tx + ", x2 = " + x2);
                lenReal = Math.abs(tx - x2);   //只支持 水平线和竖线
                isReal = true;
                
                tx = x2;
                flag = false;
            }
            if(Math.abs(ty - y1) > Math.abs(y2 - y1))
            ...{
                lenReal = Math.abs(ty - y2);
                isReal = true;
                
                ty = y2;
                flag = false;
            }
            g.drawLine(x,y,tx,ty);
            x = (int)(c*(n+m)*mark_x + ttx);
            y = (int)(c*(n+m)*mark_y + tty);
            if(x > x2 || y > y2)
            ...{
                if(flag)
                ...{
                    //System.out.println(" 虚 越界了:x = " + x + ", x2 = " + x2);
                    isReal = false;
                    if(x > x2)
                        lenReal = x-x2;
                    else
                        lenReal = y-y2; 
                }
                break;
            }
            c++;
        }
        while(flag);
    }

-----------------------------------------------------------------------------------------------------------------

http://shop33871860.taobao.com/

QQ: 780023319

旺旺: xichu_coa

画流动虚线框(java)相关推荐

  1. java画虚线_画流动虚线框(java) | 学步园

    前两天写了个作业:在面板(Panel)上显示一张图片,并能够用鼠标随意拖动,将图片放置于任何位置. 见:http://blog.csdn.net/caoxiongjun/archive/2006/09 ...

  2. 在Visio中快速的画一个虚线框

    在Visio中我们需要一个虚线框怎么来画:我的方法是画一个矩形然后改变其属性来实现,这样你就不用考虑初次画框的大小,因为矩形可以随意去拉伸其大小. 1.在指针工具那里选择矩形画一个矩形出来 2.修改矩 ...

  3. visio画透明虚线框

    visio画虚线框,可以将别的内容包含住 1.选择插入容器,选择一个矩形框 2.双击容器,右键点击设置形状 3.设置短划线类型

  4. word流程图怎么做虚线框_如何在visio中画虚线框以及将visio图形复制到word文档

    这两个问题都不是什么复杂的事情,但是如果对visio用的不多或者只是临时用起来碰到了这种问题还真是麻烦事儿. ============================================= ...

  5. Java Swing去掉按钮(JButton)中文字周围的虚线框

    Java Swing去掉按钮中文字周围的虚线框 今天偶尔发现的一个问题,JButton创建按钮的时候,生成的按钮文字周围有虚线框.如下图: 解决办法如下: //去掉按钮文字周围的焦点框 button. ...

  6. 如何在visio中画虚线框以及将visio图像复制到word文档中虚线变成实现的问题

    原文地址:http://blog.csdn.net/learngis/article/details/4634776 这两个问题都不是什么复杂的事情,但是如果对visio用的不多或者只是临时用起来碰到 ...

  7. viso 画背景框_如何在visio中画虚线框以及将visio图形复制到word文档

    这两个问题都不是什么复杂的事情,但是如果对visio用的不多或者只是临时用起来碰到了这种问题还真是麻烦事儿. ============================================= ...

  8. 如何在visio中画虚线框以及将visio图形复制到word文档中虚线变为实线的问题

    这两个问题都不是什么复杂的事情,但是如果对visio用的不多或者只是临时用起来碰到了这种问题还真是麻烦事儿. ============================================= ...

  9. Android 使用shape实现虚线或者虚线框

    画一条虚线作为分割线 1.先写一个shape,命名为shape_line_dash.xml 虚线 ?xml version="1.0" encoding="utf-8&q ...

最新文章

  1. 使用JackJSON 流式API 创建JSON串【学习记录】
  2. 多gpu训练梯度如何计算,求和是否要求平均
  3. 在vue中获取微信支付code及code被占用问题的解决?
  4. Linux系统的存储管理
  5. 剑指Offer #10 矩形覆盖(问题分析)
  6. 使用npm init生成package.json
  7. Java并发编程—为什么wait/notify操作要先获取到锁?
  8. Oracle client 安装、配置
  9. 开学季|计算机专业的你看过来!
  10. Spring Boot笔记-banner.txt的使用
  11. “参与 Debian 项目 20 年后,被降级的我选择退出”
  12. 1095.山脉数组中查找目标值
  13. 记录:成功配置 centos + nginx + .net core 2.0
  14. 绩效考核及评估活动的实施步骤及疑难问题汇编
  15. RM遥控器接收程序的分析
  16. 美橙互联域名转入万网 美橙互联域名转入万网
  17. 腾讯游戏安全高级工程师胡和君:定制化对抗——游戏反外挂的安全实践
  18. WIN10系统盘安装提示MBR分区问题解决步骤
  19. Zotero-word中引用跳转到参考文献/建立超链接-引用格式(Xie et al 2021, Achanta et al 2012)
  20. html分列代码,科学网—EXCEL 分列 (TextToColumns) 的C#代码 - 丁祥欢的博文

热门文章

  1. 利用Python实现视频中人物的人脸转换超详细教程
  2. IBM-PC汇编语言程序设计课后习题答案(第4、5章)
  3. 木马 + 流氓软件 + 垃圾软件 玩死 Win 2000 pro~
  4. thrift 技术分享待续
  5. 自媒体剪辑视频都在用的6个音效素材网站。
  6. 《Excel效率手册:早做完,不加班》
  7. 为自动驾驶保驾护航—谈谈主流中间件设计
  8. SSD源码解读1-数据层AnnotatedDataLayer
  9. Intel Composer XE
  10. VisionPro基础篇(一): VisionPro界面介绍