前两天写了个作业:在面板(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个像素----......直到达到了所要的虚线长度.代码如下:(只适用于水平线和垂直线)

publicvoiddrawDashed(Graphics g,intx1,inty1,intx2,inty2)

...{

intx=x1,y=y1;

intn=4;//实线段长度intm=4;//虚线段长度inttx=0,ty=0;

intc=0;

booleanflag=true;//标记 有没有画完(达到要求的长度)intmark_x=0;//标记 要画的是 水平线(值为1)intmark_y=0;//标记 要画的是 垂直线(值为1)

//要么0,要么 1if(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);

这两条语句作用是在每次画虚线前,将上一次的虚线清空。

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

privatevoiddrawFlowRect(Graphics g,intx,inty,intwidth,intheight)

...{

        Color oldColor=g.getColor();

        templen=templen+1;//每次前进 1个像素,由templen控制if(templen>=4)

...{

            templen=0;

            isReal=!isReal;

        }        lenReal=templen;

booleanoldisReal=isReal;//备份doubleoldlenReal=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);

    }//画流动虚线

//需要返回的信息:最后一段是空的还是 实的, 以及长度privatevoiddrawFlowLine(Graphics g,intx1,inty1,intx2,inty2)

...{

intx=x1,y=y1;

intn=4;//实线段长度intm=4;//虚线段长度inttx=0,ty=0;

intmark_x=0;//标记 如果为1 表示水平线intmark_y=0;//标记 如果为1 标识垂直线intc=1;

booleanflag=true;

//要么0,要么 1if(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);}

intttx=x;//第二部分起始位置 x坐标inttty=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)

java画虚线_画流动虚线框(java) | 学步园相关推荐

  1. 画流动虚线框(java)

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

  2. java runnable 匿名_匿名类实现Runnable接口 | 学步园

    15.2.3  使用Runnable接口 我们知道,Java中的类只能够是单继承,也就是说,如果一个类为了使用线程而继承了Thread类,它就不能再继承别的类了.这很可能给编程带来不便.本节中介绍的就 ...

  3. c++画蛋糕_为什么Golang能从Java和C++嘴里抢来一块蛋糕

    不得不说go的市场切入点非常准确 go被设计出来的目标应用场景是服务器开发,而服务器端开发是c++和java的地盘,占了大部分份额,go的目标是从他们嘴里抢蛋糕 程序员选语言除了流行度以外,语言是否好 ...

  4. css虚线矩形,css3内部虚线框设计

    第一个使用的是border为虚线,再加上box-shadow来模拟外面的框:第二个使用的:before方法生成一个虚线框,这里注意的是生成的内容定位上下左右各为3px,确定了这个生成内容的大小,另外需 ...

  5. java coin介绍_代码示例中的Java 7:Project Coin

    java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...

  6. java 故障排查_目前最全的 Java 服务问题排查套路

    问题分类: CPU问题 内存问题(GC问题.内存泄漏. OOM,Coredump 等) I/O问题 问题排查工具箱: 系统级别的工具: top:查看系统/进程cpu.内存.swap等资源占用情况的必备 ...

  7. eclipse写java实现端口_使用eclipse(windows)在java中使用IPv6地址和端口号创建套接字...

    当我尝试使用IPv4地址创建套接字时,它很成功,但是当我尝试使用IPv6地址和端口号创建套接字时,它会引发异常: java.net.SocketException: Network is unreac ...

  8. java lock 效率_工作常用4种Java线程锁的特点,性能比较、使用场景

    多线程的缘由 在出现了进程之后,操作系统的性能得到了大大的提升.虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求. 使用多线程的理由之一是和进程相比,它是一种非常花 ...

  9. java布道师_初探第10代Java帝国:11位Java专家道出了他们最喜欢的功能

    Java 10发布后.我们第一时间与11位Java专家讨论了一波.顺便深入挖掘了他们在Java 10中最喜欢的功能和对未发布的JDK11版本的一些看法. " Java 10对Java 9来说 ...

最新文章

  1. 2013年下半年信息系统项目管理师考试论文试卷
  2. macos关闭软件更新小红点_MacOS和Windows哪个更适合你?
  3. BZOJ3251: 树上三角形
  4. wzplayer for android V1.0
  5. Jenkins-CI 远程代码执行漏洞复现(CVE-2017-1000353)
  6. MYSQL(3)---MySQL的基本概念介绍
  7. 余承东嘲讽苹果:iPhone 12落后华为Mate40两代
  8. 关于php单引号和双引号
  9. noip2012借教室
  10. Linux读取内核空间,linux,arm_arm如何在内核空间直接读写某个物理地址(或者进程的虚拟地址),linux,arm,c,linux-kernel,memory - phpStudy...
  11. 独立游戏佳作分享-001(FEZ、Braid、Super Meat Boy)
  12. 【李守聪原创】攻坚克难,梦在远方
  13. 爬取优美图库里的照片,并存到文件夹中
  14. CentOS 7 安装osquery监控系统
  15. cocos2d-x Touch 移动精灵
  16. 互斥事件的概念和公式_统计学中的基本概念和重要公式(一)
  17. springboot项目启动报错 url‘ attribute is not specified and no embedded datasource could be configured
  18. video视频标签怎么禁止用户拖动进度条快进
  19. Xshell SSH免密登录
  20. 如何批量生成JAN13条码

热门文章

  1. 【逆向学习记录】格式化字符串漏洞原理及其利用
  2. C语言练习:用户输入圆的半径,求圆的面积
  3. 【BMI指数计算器V2.0】项目实战
  4. 如何修改WebUpload上传文件默认调用系统相机,而不是手机相册?
  5. oracle旬统计,Oracle准时间分旬查询
  6. 『HTTP知识点』什么是HTTP协议?(HTTP协议详解)
  7. 基于WebRTC实现音视频及数据通信
  8. flutter 报错java.net.URISyntaxException: Illegal character in opaque part at index 2
  9. 欧能智能电销机器人为颠覆电销行业而来
  10. s8韩版+android8,三星Galaxy S8韩版官方安卓9固件rom刷机包:G950NKSU3DSE2