java画虚线_画流动虚线框(java) | 学步园
前两天写了个作业:在面板(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,要么 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);
这两条语句作用是在每次画虚线前,将上一次的虚线清空。
画虚线部分的代码做了些改动,以适应流动虚线
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,要么 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);
}
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) | 学步园相关推荐
- 画流动虚线框(java)
前两天写了个作业:在面板(Panel)上显示一张图片,并能够用鼠标随意拖动,将图片放置于任何位置. 见:http://blog.csdn.net/caoxiongjun/archive/2006/0 ...
- java runnable 匿名_匿名类实现Runnable接口 | 学步园
15.2.3 使用Runnable接口 我们知道,Java中的类只能够是单继承,也就是说,如果一个类为了使用线程而继承了Thread类,它就不能再继承别的类了.这很可能给编程带来不便.本节中介绍的就 ...
- c++画蛋糕_为什么Golang能从Java和C++嘴里抢来一块蛋糕
不得不说go的市场切入点非常准确 go被设计出来的目标应用场景是服务器开发,而服务器端开发是c++和java的地盘,占了大部分份额,go的目标是从他们嘴里抢蛋糕 程序员选语言除了流行度以外,语言是否好 ...
- css虚线矩形,css3内部虚线框设计
第一个使用的是border为虚线,再加上box-shadow来模拟外面的框:第二个使用的:before方法生成一个虚线框,这里注意的是生成的内容定位上下左右各为3px,确定了这个生成内容的大小,另外需 ...
- java coin介绍_代码示例中的Java 7:Project Coin
java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...
- java 故障排查_目前最全的 Java 服务问题排查套路
问题分类: CPU问题 内存问题(GC问题.内存泄漏. OOM,Coredump 等) I/O问题 问题排查工具箱: 系统级别的工具: top:查看系统/进程cpu.内存.swap等资源占用情况的必备 ...
- eclipse写java实现端口_使用eclipse(windows)在java中使用IPv6地址和端口号创建套接字...
当我尝试使用IPv4地址创建套接字时,它很成功,但是当我尝试使用IPv6地址和端口号创建套接字时,它会引发异常: java.net.SocketException: Network is unreac ...
- java lock 效率_工作常用4种Java线程锁的特点,性能比较、使用场景
多线程的缘由 在出现了进程之后,操作系统的性能得到了大大的提升.虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求. 使用多线程的理由之一是和进程相比,它是一种非常花 ...
- java布道师_初探第10代Java帝国:11位Java专家道出了他们最喜欢的功能
Java 10发布后.我们第一时间与11位Java专家讨论了一波.顺便深入挖掘了他们在Java 10中最喜欢的功能和对未发布的JDK11版本的一些看法. " Java 10对Java 9来说 ...
最新文章
- 2013年下半年信息系统项目管理师考试论文试卷
- macos关闭软件更新小红点_MacOS和Windows哪个更适合你?
- BZOJ3251: 树上三角形
- wzplayer for android V1.0
- Jenkins-CI 远程代码执行漏洞复现(CVE-2017-1000353)
- MYSQL(3)---MySQL的基本概念介绍
- 余承东嘲讽苹果:iPhone 12落后华为Mate40两代
- 关于php单引号和双引号
- noip2012借教室
- Linux读取内核空间,linux,arm_arm如何在内核空间直接读写某个物理地址(或者进程的虚拟地址),linux,arm,c,linux-kernel,memory - phpStudy...
- 独立游戏佳作分享-001(FEZ、Braid、Super Meat Boy)
- 【李守聪原创】攻坚克难,梦在远方
- 爬取优美图库里的照片,并存到文件夹中
- CentOS 7 安装osquery监控系统
- cocos2d-x Touch 移动精灵
- 互斥事件的概念和公式_统计学中的基本概念和重要公式(一)
- springboot项目启动报错 url‘ attribute is not specified and no embedded datasource could be configured
- video视频标签怎么禁止用户拖动进度条快进
- Xshell SSH免密登录
- 如何批量生成JAN13条码
热门文章
- 【逆向学习记录】格式化字符串漏洞原理及其利用
- C语言练习:用户输入圆的半径,求圆的面积
- 【BMI指数计算器V2.0】项目实战
- 如何修改WebUpload上传文件默认调用系统相机,而不是手机相册?
- oracle旬统计,Oracle准时间分旬查询
- 『HTTP知识点』什么是HTTP协议?(HTTP协议详解)
- 基于WebRTC实现音视频及数据通信
- flutter 报错java.net.URISyntaxException: Illegal character in opaque part at index 2
- 欧能智能电销机器人为颠覆电销行业而来
- s8韩版+android8,三星Galaxy S8韩版官方安卓9固件rom刷机包:G950NKSU3DSE2