`
xiaozhonghua
  • 浏览: 254200 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Swing第五刀:走马观花看世博

阅读更多

没错,这依旧是一篇技术文章,而不是世博会游记。其实至今尚未参观世博会,虽然就生活在这个城市,却没有外地朋友的那番激情和热度。在上下班地铁站上与蜂拥而至的旅游团队挤地铁、看着地铁车厢屏幕上跳动的接近50万的世博会当日入园人数统计、画面上如广州火车站春运搬的人流,想想这接近40度的桑拿天和时不时骤降的倾盆大雨,这最后的一点去看一看的激情也被无情的抹杀了。
 
作为遵纪守法、积极用户党和政府的三好公民,就算未亲临世博,也要积极宣传世博,为城市做贡献,让城市更美好不是么?思前想后,还不如直接用我们程序员最熟悉的工具——代码——来展示一下世博之美。
 
网上随便转一下,用Flash制作的“旋转的图片画廊”效果的例子,可谓比比皆是,大家都见怪不怪了。所以,Flash/Flex自然也被贴上了“酷炫到底”的贵族标签。没错,Flash/Flex有内置的动画、渲染、滤镜等机制,制作这类小把戏具有先天的优势,可谓是小菜一碟,各方大牛的例子也是让人心潮澎湃、此起彼伏啊。既然咱们是玩Swing的,那自然会想:Swing这把大砍刀,也玩玩这瓷器活?!能行么?
 
可以肯定的说,答案肯定是肯定的。看看我一个上午的小成果:


不是很轻松

不得不说,用Swing做这类趣味程序效果,并非很轻松。可以说是大菜刀修指甲、大扫帚修眉毛,做是能做,就要看你的功力如何了。本例子纯属把Swing的能力和一些编程技巧和大家展示,真正用Swing做动画这类程序,还是推荐用Flash/Flex、JavaFx之类,除非你的“菜刀功法”比较深厚,也就无所谓了。

 

下面我们就把一些关键的“刀法”一一解读。

 

用到的第三方包

没错,这里用到了TWaver这个包。但是要强调的是,这里所介绍的Swing技巧和TWaver无关,用它只是为了更加方便,减少一些代码量。对第三方的东西有强烈“排斥恐惧症”的朋友,可以静下心来仔细研究一下代码,我相信一定会有所收获。

 

如何生成“镜面倒影”

程序中的每个图片,在下方都有一个灰度的、缩小的、渐暗的、翻转的镜面倒影。这是怎么做到的?是直接PS处理、存在原图片中吗?不,那太就没技术含量了。如果都靠美工,如何体现我们程序员的价值?这个倒影是通过一定的算法,动态生成的内存图片。大家仔细观察ImageNode.java中的createShadowImage和convertPixel函数。如果理解了这里的代码,也就搞清楚了这一算法和原理。

 

我们需要的倒影是:翻转的、灰度的(去掉颜色)、渐变的、缩短的图。为了在内存中这个图,我们对原图的每个像素进行抓取,然后根据一定算法来对像素的红、绿、蓝以及alpha透明通道进行处理。首先对原图的像素进行抓取:

int w = image.getWidth(null);
int h = image.getHeight(null);
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
try {
  pg.grabPixels();
} catch (Exception e) {
  return null;
}

 

以上代码将原图的所有像素以int形式存放在pixels数组中。然后,对每个像素进行处理,包括渐变、压缩等等:

for (int i = 0; i < w; i++) {
    pixels[j * w + i] = convertPixel(i, j, w, h, pixels[j * w + i], fadeSpeed);
}

 
其中convertPixel函数负责了具体处理。这个函数里面有几个地方需要注意:percent是这个倒影的“消失”的速度,这个通过透明度来控制。越下面的像素行,透明度越大。当然,fadeSpeed值越大,percent越大,倒影消失的越快:

double percent = (double) (y * 100) / h / 100d;
for (int i = 0; i < fadeSpeed; i++) {
    percent = percent * percent;
}
alpha = (int) (alpha * percent);

 
而下面这句话保证了alpha不大于150,这样,即使最接近原图底部的倒影部分,也保持一定的“暗度”,而不是和原图一样的“亮”,保证了倒影的效果和感觉。这里本人经过反复实验,还是感觉150的透明度不错。

alpha = Math.min(alpha, 150);

 
然后是把像素变灰。像素变灰有很多种算法,大家可以Google一下相关原理或看一下图像处理的相关书籍,这里不再赘述。我们就使用最简单的平均法:r、g、b平均作为新的灰度:

int gray = (red + green + blue) / 3;

 
这样,像素就处理好了。当每个像素处理结束后,再对所有像素进行镜面翻转。镜面翻转的原理是:像素所在的列不变,行取反。代码如下:

int[] newPixels = new int[w * h];
for (int j = 0; j < h; j++) {
  for (int i = 0; i < w; i++) {
    newPixels[j * w + i] = pixels[(h - j - 1) * w + i];
  }
}

 
最后,再将像素装箱打包,生成图片:

MemoryImageSource source = new MemoryImageSource(w, h, newPixels, 0, w);
return new ImageIcon(Toolkit.getDefaultToolkit().createImage(source));

 
好了,大家再仔细欣赏一下我们的成果,看效果是不是很不错?

如何处理“倒影跟随”

大家可以对图片进行任意拖动操作,可以发现几个特征:

  • 倒影不能被鼠标选中(就像倒影不是图片本身的一部分);
  • 倒影总是跟随图片移动;
  • 倒影的大小随原图的大小等比例变化;

这是如何做到的呢?这里利用了TWaver的Follower机制。

 

首先,程序中的每个图片,都是一个TWaver的ResizableNode节点;然后,倒影是一个Follower节点,并设置其host为图片节点。这样,就实现了倒影跟随;然后,整个画布是一个TWaver的Network,定制其“鼠标点选”,忽略倒影的点选动作:

network.addSelectableFilter(new SelectableFilter() {

  public boolean isSelectable(Element element) {
      return !(element instanceof Follower);
  }
});

 
然后,在图片节点中添加属性监听,当图片和尺寸发生变化时候,调整其倒影节点的大小:

addPropertyChangeListener(new PropertyChangeListener() {

  public void propertyChange(PropertyChangeEvent evt) {
    if (TWaverUtil.getPropertyName(evt).equalsIgnoreCase(TWaverConst.PROPERTYNAME_IMAGE)) {
      updateImage();
    }
    if (TWaverUtil.getPropertyName(evt).equalsIgnoreCase(TWaverConst.PROPERTYNAME_SIZE)) {
      updateSize();
    }
  }
});

 
在事件发生后,通过以下代码动态调整倒影的尺寸和位置:

private void updateSize() {
  shadowNode.setSize(getSize().width, (int) (getSize().height * 1));
  shadowNode.setLocation(this.getLocation().x, this.getLocation().y + this.getHeight() + shadowGap);
}

 

如何动画

动画的部分比较复杂。

 

首先大家要了解TWaver的Node的处理图片的方法:当我们给ResizableNode或Follower直接设置其宽高之后,其对应的图片会被直接压缩或拉伸。这个和我们用Graphics2D.drawImage(image,x,y,width,height,null)是一样的道理,没什么可说的。

 

所以,接下来的工作主要是:如何将图片节点从位置A动画的移动到位置B,尺寸从X动画的变为Y呢?在Mover.java里,我们继承了Thread线程,用于动画处理。这个线程可以完成这样一个任务:给我图片的老宽高和新宽高,我可以在规定的时间动画的把图片宽高修改过去;同时还可以动画的处理图片的位置。在这个线程里面,我们把线程的生存时间拆分为90个时间片,每个片是5毫秒(定义在delay变量中)。Run函数中,循环这90个时间片,每个时间片处理一个“步进”并sleep 5毫秒。

 

为什么是90个时间片呢?为了增加动画的质感,如果直接使用线性函数来做步进,就会显得很生硬。看一下Flash做的动画效果,都有二次甚至三次函数对动画进行处理。例如那种慢——快——慢,甚至“急刹车”或“刹车过头”的动画方式,我们一定印象深刻。这里我们选择了最简单的三角函数,用两段拼接的正弦函数来模拟慢——快——慢的效果:

这样大家就会明白为何使用90:可以方便的把时间轴作为角度值,来处理一个动画周期。在具体处理时,先用45个时间片来处理前半周期,此时用cos函数:

int movementX = (int) (info.getCenterChangeX() / 2 * (1 - Math.cos(Math.toRadians(i * 2))));
int x = info.getOldCenterX() + movementX;
int movementY = (int) (info.getCenterChangeY() / 2 * (1 - Math.cos(Math.toRadians(i * 2))));
int y = info.getOldCenterY() + movementY;

 
注意i*2这样就把45个时间片放在了完整的90度范围中,利用了正弦曲线的完整形状。下半个动画周期使用sin函数:

int movementX = (int) (info.getCenterChangeX() / 2 * Math.sin(Math.toRadians(i * 2)));
int x = info.getOldCenterX() + info.getCenterChangeX() / 2 + movementX;
int movementY = (int) (info.getCenterChangeY() / 2 * Math.sin(Math.toRadians(i * 2)));
int y = info.getOldCenterY() + info.getCenterChangeY() / 2 + movementY;

这样出来的效果明显比线性的要有动感。具体算法请看Mover.java类。

如何做到“齐头并动”

以上解决了一个图片的动画问题。在程序中,是每个图片都在同时、并行的动画。这个如何处理?难道多个Mover线程吗?那样肯定消耗资源而且效果不佳。最好的方法肯定是在每个时间片中,同时移动所有需要移动的图片和物体。

 

在Mover中我们做以下改进:接受多个图片节点的动画信息并保存;在动画过程中,提前算好每个物体需要移动的步进和路径,然后在90个时间片中,同时移动所有需要移动的物体。在Mover的run函数中:

for (int index = 0; index < infos.size(); index++) {
MoverInfo info = infos.get(index);
//移动物体
}

 

如何计算图片停留点位置


在本例子中,图片一共有5个停留位置:

在每个位置点,图片都有对应的、固定的中心点和尺寸,我们提前计算好并记录下来就行了。在Main.java中,createNodes函数创建了所有图片节点,同时又返回了每个停留点的边界:

private Rectangle[] positions = createNodes();

 
这样,当一个图片需要从1点移动到2点时,我们就直接把对应index的Rectangle拿出来,交给Mover去move就行了。

 

如何连续移动

以上解决了移动一个位置的动画问题。如果一个图片需要从1点直接跳到3点,该如何处理?为了简化程序,同时保持“一步一步走”的动画效果,我们还是把两段动画连续播放,而不是直接忽悠一下移动过去。也就是说,先让图片从1点移动到2点,停顿一下再移动到3点。这样就要连接两个线程。

 

由于线程是异步的,一旦run起来我们就没法控制其暂停和停止以及后续动作。所以,我们要改造一下Mover:在创建的时候,可以给他一个Runnable,当线程执行结束后,可以执行这个Runnable进行“收尾”或“桥接”。例如,这个Runnable可以在线程结束后重新设置一下图片的前后遮挡关系,也可以用于链接、执行下一个动画。可见,这个改进非常有必要。

 

观察Mover.java的构造函数:

public Mover(ArrayList<MoverInfo> infos, Runnable action)

 
最后一个参数就是这个Runnable,我们可以叫它action,一个动作。在run函数结束的时候:

if (action != null) {
  SwingUtilities.invokeLater(action);
}

 
也就是说,如果action不为空,就在Swing线程中执行它。为什么在Swing线程中执行它呢?因为当前线程并非Swing线程,而action大多情况是处理一些Swing事务,所以这样就避免了外部再次写SwingUtilities.invokeLater带来的啰嗦。如果还不熟悉Swing事件派发线程(EDT)和SwingUtilities.invokeLater机制的同学,那就要多读书、多加油喽!

 

有了这个机制,我们就可以实现两段动画的连接:把第二段动画放在第一段动画的action里面就行了。

private void moveTwoSteps(final boolean unclockwise) {
  Mover mover = createNodeMover(unclockwise, new Runnable() {

    public void run() {
      Mover mover = createNodeMover(unclockwise, null);
      mover.start();
    }
  });
  mover.start();
}

 

 

增加点击移动事件

有了以上的动画能力,还要把它通过一定的事件触发出来。当然是“点击图片移动它到面前”的方式最好了,也符合这类程序的一般设计感觉。我们在TWaver的Network画布上添加一个节点点击事件:

network.addElementClickedActionListener(new ActionListener() {

  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source instanceof ImageNode) {
      ImageNode node = (ImageNode) source;
      move(node);
    }
  }
});

 
当一个图片节点点击后,调用move函数进行移动。在move函数中,首先判断当前点击图片的位置编号。如果是1、5号位,则分别逆时针、顺时针移动2个位置;如果是2、4号位,则分别逆时针、顺时针移动1个位置;如果3号位,则不动。

 

为什么点击3号位,不移动呢?因为按理说5号位是中锋的位置,3号位是小前锋,应当跑动最多的球员。在NBA中,目前公认的最佳5号位中锋是我们的姚明。虽然一年多没打球了,但是实力依然不可小视。不过最近火箭正在吸收当帕特里克•帕特森,一个刚刚结束在肯塔基大学第二年的学生来打3号位,这孩子身体素质如牛,弹跳爆发力极强,让人十分期待。怎么扯到篮球了?继续看代码:

int index = (Integer) node.getUserObject();
if (index == 1) {
  moveTwoSteps(true);
}
if (index == 2) {
  moveOneStep(true);
}
if (index == 4) {
  moveOneStep(false);
}
if (index == 5) {
  moveTwoSteps(false);
}

 

其中moveOneStep和moveTwoSteps函数都是封装好了的移动一步、两步的方法。另外,boolean参数是控制逆时针或顺时针方向。

 

如何避免动画错乱

什么?这么精妙的动画算法怎么会错乱?那可不一定,要看谁玩儿了。你没发现我们程序员都有一个习惯:逮着一个程序,尤其花里胡哨的那种程序,鼠标冲上去就是一通speed>10次/秒的速度狂戳,而且四处乱戳,毫无规律可言。如果这样暴力,这个动画一定会乱:第一段动画还每完,第二段、第三段又起来了。

 

怎么办?对付这种变态的用户,只能加一把“线程锁”:通过一个唯一存在的“信号灯”来做标记。当动画尚未结束的时候,让其它动画线程一律:a、等待;b、去死。我选择了b。原因很简单,因为它简单。

 

这个例子中的具体做法是:在Mover类里面定义了一个static的信号变量:

private static boolean moving = false;

 

并用两个synchronized函数来负责存取:

public static synchronized boolean isMoving() {
        return moving;
    }

    public static synchronized void setMoving(boolean moving) {
        Mover.moving = moving;
    }

 

在动画开始的时候进行如下判断:

public void run() {
        if (!isMoving()) {
            setMoving(true);

 
如果信号灯开启,线程直接结束;否则,打开信号灯,然后执行动画。

 

没错,我承认这里处理的还很粗糙:一个static的信号灯太粗鲁了一点。不过在这个简单的、只有一个动画场景的环境里面,就不搞的太复杂了。有兴趣的同学可以弄的再科学一点。

 

当然,这样处理后,界面我随你鼠标狂风暴雨,我自岿然不动。不是不动,是悠然自得的慢慢的动。

 

处理图片的遮挡关系

别小看这个话题。当图片动起来后,其不断变化的前后遮挡关系要及时处理,很是烦人。错误的遮挡关系会严重破坏程序的感觉。图片的遮挡关系应当符合这个原则:最中间的图片离眼睛最近,所以应当在最上面;1号位(弗老大的位置)和5号位(姚明的位置)应当离眼睛最远,应当在最下面。

 

 

在代码中,我们把每个位置的图片用一个大小不同的数字来代表其前后关系,然后把数字作为key,把每个节点放入一个可自动排序的TreeMap哈希表:

if (index == 3) {
  sortedNodes.put(5, node);
}
if (index == 2) {
  sortedNodes.put(4, node);
}
if (index == 4) {
  sortedNodes.put(3, node);
}
if (index == 1) {
  sortedNodes.put(2, node);
}
if (index == 5) {
  sortedNodes.put(0, node);
}

 

然后在每段动画结束的时候,用一个runnable对排序进行重新整理,更新其遮挡关系:

Runnable action = new Runnable() {

public void run() {
  Iterator<Integer> iterator = sortedNodes.keySet().iterator();
  while (iterator.hasNext()) {
    int index = iterator.next();
    ImageNode node = sortedNodes.get(index);
    sendToTop(node);
  }
  if (followingAction != null) {
    followingAction.run();
  }
}
};

 

 

其他小伎俩

 

设置Tooltip这个就简单了:直接在node上用setToolTipText函数就行了。注意用点HTML的小伎俩。

node.setToolTipText("<html><b>中国馆</b>"
                    + "<br>中国馆你没见过吗?不会吧童鞋?"
                    + "<br>点我,闲着也是闲着");

 

另外还可以修改背景颜色。黑色的也挺酷,不是么?

不足与改进空间

这个例子最大的缺点是:写死了只能处理5张图片,而不是任意多。动画的控制函数也比较单一。不过通过以上原理介绍后,大家完全可以自行改进。欢迎感兴趣的童鞋积极动手,欢迎各位大侠给出宝贵意见。

 

例子与源代码下载

老规矩,有福同享、有难我当。可执行程序、源代码的下载请见本页面下方。注意需要twaver.jar包以及JDK6环境。有任何疑问请给我留言。

 

另外,程序中用到的素材图片均来自网络,版权归作者所有;世博场馆造型设计版权归各自场馆和国家所有,本人决没有侵权的意思。

 

再次感谢大家捧场!

  • 大小: 260.6 KB
  • 大小: 108.2 KB
  • 大小: 20.3 KB
  • 大小: 6 KB
  • 大小: 238.5 KB
分享到:
评论
44 楼 kehengqun 2011-08-06  
  向楼主致敬!
  我前几天也用swing做了一个类似的图片浏览小软件,不过是把图片放在一个椭圆周上浏览,能显示移动过程,具体见http://kehengqun.iteye.com/blog/1140491
  不过和你做的差距有点大啊,没有做倒影,全部都是自己写的没用三方库,图片移动也没用慢-快-慢的效果,只是简单的沿圆周运动。
  但是理论上可以显示的图片数量没限制,每次显示10张,有很多显示按钮。
  欢迎指教!
43 楼 wecley 2010-11-19  
    最近开始学习,twaver,向LZ牛人,学习~~膜拜中...
42 楼 wyx065747 2010-09-23  
楼主,你太帅了!!你完全颠覆了我对swing的看法,谢谢你发表的文章及发布的源码。期待你更强大的作品!!
41 楼 greeysid 2010-09-05  
继续向楼主深入学习swing。
40 楼 xiaozhonghua 2010-07-23  
JustDoNow 写道
javagui 写道
这本书都介绍到了

请楼主鉴定一下这本书是学习Swing的好书吗

不好意思,老实说这本书我真没看过,看名字挺不错。Swing Hacks看过,无疑是好书。
39 楼 wxq594808632 2010-07-23  
近几年就没swing的好书。上面那个算。还有个swing hack不错。。其余的就无视了
38 楼 JustDoNow 2010-07-23  
javagui 写道
这本书都介绍到了

请楼主鉴定一下这本书是学习Swing的好书吗
37 楼 ninja9turtle 2010-07-20  
CodingMouse 写道
ninja9turtle 写道
gml520 写道
ninja9turtle 写道
node.setToolTipText("<html><b>中国馆</b>"  
                   + "<br>中国馆你没见过吗?不会吧童鞋?"  
                   + "<br>点我,闲着也是闲着"); 

能支持HTML有点意思,不知道复杂的css能否支持,好像现在flex对HTML的支持不怎么样


我记得Java Swing 从1.4开始就已经支持Html3.0 的标准了。

奇怪这么好的功能一直很少见人用的,我对swing了解不多,在我看来HTML的特别是文字方面的支持是很重要但是很难的,例如Flash啥都不错,就是文字支持比较烂,至少没有人傻到用flash做论坛的当然也有纯粹玩玩而已,我估计swing的支持也是很浅的,这个功能做完善了那几乎是一半browser的功能了


这个Swing的Tooltips本身就支持html格式定义好不好?详细可参考JDK安装目录下的示例:“demo\jfc\SwingSet2”,效果图如下:



支持地球人大家都知道,借用你的口气:现在讨论的是支持到什么程度“好不好”?
36 楼 CodingMouse 2010-07-20  
很感谢楼主的共享精神!你的Swing设计思路很让人受益。以前搞过几年VFP桌面开发,一直对桌面应用开发情有独钟,期望楼主有更多的刀法分享!
35 楼 CodingMouse 2010-07-20  
ninja9turtle 写道
gml520 写道
ninja9turtle 写道
node.setToolTipText("<html><b>中国馆</b>"  
                   + "<br>中国馆你没见过吗?不会吧童鞋?"  
                   + "<br>点我,闲着也是闲着"); 

能支持HTML有点意思,不知道复杂的css能否支持,好像现在flex对HTML的支持不怎么样


我记得Java Swing 从1.4开始就已经支持Html3.0 的标准了。

奇怪这么好的功能一直很少见人用的,我对swing了解不多,在我看来HTML的特别是文字方面的支持是很重要但是很难的,例如Flash啥都不错,就是文字支持比较烂,至少没有人傻到用flash做论坛的当然也有纯粹玩玩而已,我估计swing的支持也是很浅的,这个功能做完善了那几乎是一半browser的功能了


这个Swing的Tooltips本身就支持html格式定义好不好?详细可参考JDK安装目录下的示例:“demo\jfc\SwingSet2”,效果图如下:


34 楼 ninja9turtle 2010-07-19  
gml520 写道
ninja9turtle 写道
node.setToolTipText("<html><b>中国馆</b>"  
                   + "<br>中国馆你没见过吗?不会吧童鞋?"  
                   + "<br>点我,闲着也是闲着"); 

能支持HTML有点意思,不知道复杂的css能否支持,好像现在flex对HTML的支持不怎么样


我记得Java Swing 从1.4开始就已经支持Html3.0 的标准了。

奇怪这么好的功能一直很少见人用的,我对swing了解不多,在我看来HTML的特别是文字方面的支持是很重要但是很难的,例如Flash啥都不错,就是文字支持比较烂,至少没有人傻到用flash做论坛的当然也有纯粹玩玩而已,我估计swing的支持也是很浅的,这个功能做完善了那几乎是一半browser的功能了
33 楼 huhuanqadn 2010-07-19  
NB的楼主,拜读
32 楼 xx314327475 2010-07-19  
真不错..我喜欢
31 楼 menuhin 2010-07-19  
楼主的刀法真是惊人啊。。。
让我们大家眼前一亮啊!
30 楼 wwj85523 2010-07-19  
虽然你是TWaver公司的托,
但同位一个swing开发者,我还是要顶你
29 楼 wese345 2010-07-19  
lz让swing在众人眼前一亮,amazing!
28 楼 gml520 2010-07-19  
ninja9turtle 写道
node.setToolTipText("<html><b>中国馆</b>"  
                   + "<br>中国馆你没见过吗?不会吧童鞋?"  
                   + "<br>点我,闲着也是闲着"); 

能支持HTML有点意思,不知道复杂的css能否支持,好像现在flex对HTML的支持不怎么样


我记得Java Swing 从1.4开始就已经支持Html3.0 的标准了。
27 楼 ninja9turtle 2010-07-18  
node.setToolTipText("<html><b>中国馆</b>"  
                   + "<br>中国馆你没见过吗?不会吧童鞋?"  
                   + "<br>点我,闲着也是闲着"); 

能支持HTML有点意思,不知道复杂的css能否支持,好像现在flex对HTML的支持不怎么样
26 楼 lkj107 2010-07-18  
TWaver 一个jar包,报价20万,引入这个东东太...了
25 楼 yonlist 2010-07-18  
效果很不错,但必须用TWaver吗?

相关推荐

    SWING大刀系列源码

    主题:Swing是一把刀 ...主题:Swing第二刀:枝间新绿一重重 ...主题:Swing第二小刀刀:星星之火可以燎原 ...Swing第五刀:走马观花看世博 http://joshuaxiao.iteye.com/blog/726318 Swing第六刀:老婆不能换,窗户框可以

    Swing_大刀系列.pdf

    Swing大刀系列: 1.1 Swing是一把刀 1.2 Swing第二刀:枝间新绿一重重 1.3 Swing第三刀:做套ERP,要配得上我的登录界面!...1.5 Swing第五刀:走马观花看世博 1.6 Swing第六刀:老婆不能换,窗户框可以

    Swing第三刀:做套ERP,要配得上我的登录界面

    Swing第三刀:做套ERP,要配得上我的登录界面

    Swing第五刀(转)

    Swing第*刀(转) 个人觉得不错,发来大家学习,不要分

    基于Swing应用程序设计:一个简易的文本编辑框

    As a professional in the IT field, I'll be detailing the knowledge points from the given title, description, and tags, specifically focusing on creating a simple text editor using Swing in Java. ...

    Swing第二刀(转)

    Swing第*刀(转) 觉得很好,发给大家看看,不需要分

    Swing大刀系列

    ### Swing大刀系列知识点概述 #### 1. Swing的地位与争议 - **Swing的现状**: Swing作为一种桌面应用开发框架,在Web技术和RIA(富互联网应用)兴起后受到了冷落。很多人认为Swing已经过时或者即将被淘汰。 - **...

    Java Swing大神必经之路

    第5篇 Java Swing大神必经之路5:JavaSwing-ItemSelectable 本篇文章详细介绍了 ItemSelectable 接口,包括其方法和使用场景,幫助讀者更好地理解 ItemSelectable 的使用。 第6篇 Java Swing大神必经之路6:Java ...

    精通java-swing开发.doc

    在Java Swing开发中,Swing组件库是一个强大的工具集,用于构建图形用户界面(GUI)。这个库主要围绕着`javax.swing`包展开,它提供了丰富的组件、布局管理器以及事件处理机制,使得开发者可以创建出复杂的桌面应用...

    Swing第一刀(转)

    Swing第*刀(转) 觉得很好,发给大家看看,不需要分

    Swing第三刀(转)

    Swing第*刀(转) 个人觉得不错,发来大家学习,不要分

    Swing第四刀(转)

    Swing第*刀(转) 个人觉得不错,发来大家学习,不要分

    Swing第六刀(转)

    Swing第*刀(转) 个人觉得不错,发来大家学习,不要分

    Java Swing创建自定义闪屏:在闪屏上添加Swing进度条控件(二)

    NULL 博文链接:https://yshjava.iteye.com/blog/1326539

    java swing是一把刀

    文件名列表中的"swing第一刀.doc、swing第三刀.doc、swing第二刀.doc、swing第四刀.doc"可能包含了一系列教程或示例,指导读者如何利用Swing的特性。这些文档可能涵盖了从基本组件的使用到高级主题,如布局管理、...

    swing-layout-1.0.3

    swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3swing-layout-1.0.3...

    Java中Swing.pdf

    5. `javax.swing.filechooser`:提供了文件选择器对话框的实现,让用户能够方便地浏览和选择文件。 6. `javax.swing.plaf`:这个包允许开发者实现可插入的用户界面外观,使用户可以自定义界面风格。 7. `javax....

    good swing

    ### Swing基础知识详解 #### Swing简介 Swing 是 Java 中用于构建图形用户界面(GUI)的一套组件库。它建立在 AWT(Abstract Window Toolkit)基础之上,但与 AWT 不同的是,Swing 组件完全由 Java 实现,这意味着...

    Java中Swing的相关知识(1)

    ### Java中Swing的相关知识详解 #### 一、Swing简介 ##### 1.1 Swing的背景 在深入了解Swing之前,我们先回顾一下它的前身——AWT(Abstract Window Toolkit)。AWT最初是为了支持简单的用户界面而设计的,主要...

    swing教程之经典

    #### 五、Swing的实际应用案例 - **示例1:简单Swing应用程序**:创建一个包含按钮和标签的简单窗口,展示如何使用Swing组件创建基本的GUI界面。 - **示例2:使用Swing创建复杂的应用程序**:演示如何利用Swing的...

Global site tag (gtag.js) - Google Analytics