2008年6月30日星期一

测试

不知道怎么回事,用word跟新时虽然网站上有内容但是word依然提示出错……

2008年6月29日星期日

2008年6月26日星期四

Java的超链接处理问题

最近为了这个Blog可谓麻烦死某熊……恩,今天写点有用的内容。
我们知道JEditPanel是支持HTML排版的,而HTML一个很重要的特性就是超链接,那么怎么在程序中处理那些超链接呢?答案是使用javax.swing.event.HyperlinkListener。这个监听器在超链接被触发时调用(例如鼠标进入,鼠标离开和点击)。集体的用法可以在JavaDOC中查到,这里就给出一个示例代码,这个函数返回的监听器将在外部浏览器打开指定的链接,链接必须包括http://

public HyperlinkListener createHyperLinkListener() {
return new HyperlinkListener() {

public void hyperlinkUpdate(HyperlinkEvent e) {
System.out.println(e);
if (e.getEventType() == HyperlinkEvent.EventType.ENTERED) {
((JEditorPane) e.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else if (e.getEventType() == HyperlinkEvent.EventType.EXITED) {
((JEditorPane) e.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} else if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
Desktop.getDesktop().browse(e.getURL().toURI());
} catch (Exception ex) {
Logger.getLogger(HTMLServerMessagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
}

2008年6月25日星期三

代码高亮测试


/*
* Copyrights (C) 2008 Bearice (Bearice@Gmail.com)
* Release under GNU/GPL Version 2.
*/
package cn.bearice.ipcontroller.client.core.remote.guet;

import cn.bearice.java.security.Account;
import cn.bearice.ipcontroller.controller.ControllerServer;
import cn.bearice.ipcontroller.RemoteServer;
import cn.bearice.ipcontroller.events.ServerStatusChangeListerer;
import cn.bearice.java.util.listener.*;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.AccountException;
import javax.security.auth.login.AccountLockedException;
import javax.security.auth.login.AccountNotFoundException;

/**
*
* @author Bearice
*/
public class GUET_UDPControllerServer implements ControllerServer {

public static final int STAT_NOT_LOGED_ON = 0;
public static final int STAT_LOGED_ON = 2;
public static final int STAT_LOGON_PENDDING = 1;
private static final Method statusChangedMethod;


static {
try {
statusChangedMethod = ServerStatusChangeListerer.class.getDeclaredMethod(
"serverStatusChanged",
new Class[]{
RemoteServer.class,
int.class,
int.class
});
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}

class StatusChangeListenerSupport extends ListenerSupport {

void fireStatusChanged(int before, int after) {
this.fireEventAsync(statusChangedMethod, GUET_UDPControllerServer.this, before, after);
}
}
public static final int CLIENT_LISTEN_PORT = 26000;
StatusChangeListenerSupport statusChangeListenerSupport = new StatusChangeListenerSupport();
SocketAddress remoteAddress;
DatagramSocket socket;
protected int status = STAT_NOT_LOGED_ON;

protected void receive(byte[] buff) throws IOException {
DatagramPacket packet = new DatagramPacket(buff, buff.length);
do {
socket.receive(packet);
} while (packet.getSocketAddress().equals(remoteAddress));
}

protected void send(byte[] buff) throws IOException {
DatagramPacket packet = new DatagramPacket(buff, buff.length);
packet.setSocketAddress(remoteAddress);
socket.send(packet);
}

public GUET_UDPControllerServer(SocketAddress remoteAddress) {
try {
this.remoteAddress = remoteAddress;
socket = new DatagramSocket(CLIENT_LISTEN_PORT);
} catch (SocketException ex) {
Logger.getLogger(GUET_UDPControllerServer.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}

public void logon(Account account) throws AccountException {
try {
setStatus(STAT_LOGON_PENDDING);
GUET_PreLogonPacket lp = new GUET_PreLogonPacket(account.getName());
send(lp.toByteArray());
byte[] buff = new byte[22];
receive(buff);
lp.readByteArray(buff);
switch (lp.status) {
case GUET_PreLogonPacket.STATUS_ERROR:
throw new AccountNotFoundException();
case GUET_PreLogonPacket.STATUS_LOCKED:
throw new AccountLockedException();
case GUET_PreLogonPacket.STATUS_OK:
break;
default:
throw new IOException("Illegal PLP.status");
}
lp = new GUET_LogonPacket(account.getName(), account.getPassword());
send(lp.toByteArray());
buff = new byte[32];
receive(buff);
lp.readByteArray(buff);
switch (lp.status) {
case GUET_PreLogonPacket.STATUS_ERROR:
throw new AccountNotFoundException();
case GUET_PreLogonPacket.STATUS_LOCKED:
throw new AccountLockedException();
case GUET_PreLogonPacket.STATUS_OK:
break;
default:
throw new IOException("Illegal PLP.status");
}
setStatus(STAT_LOGED_ON);
} catch (IOException ex) {
Logger.getLogger(GUET_UDPControllerServer.class.getName()).log(Level.SEVERE, null, ex);
throw new AccountException("Error while commucating with server: " + ex);
}
}

public void logoff() {
if (getStatus() != STAT_LOGED_ON) {
throw new IllegalStateException("not loged on!");
}

}

public int getStatus() {
return status;
}

protected void setStatus(int status) {
int oldstst = this.status;
this.status = status;
statusChangeListenerSupport.fireStatusChanged(oldstst, status);
}

public void addStatusChangeListerer(ServerStatusChangeListerer linstener) {
throw new UnsupportedOperationException("Not supported yet.");
}

public void removeStatusChangeLinstener(ServerStatusChangeListerer lintener) {
throw new UnsupportedOperationException("Not supported yet.");
}

public Collection getStatusChangeListeners() {
throw new UnsupportedOperationException("Not supported yet.");
}
}

某熊又回来了

历经千辛万苦,爬过雪山,做过沼泽,进行N次空间跳跃,更换了无数次BSP,最后某熊作出了一个伟大的决定:我还是回来吧……NND全世界BSP千千万,就是没有一个适合某熊的……我先去面个壁去……

2008年6月23日星期一

[转]控制台下的输出色彩控制

VT100控制符文档
这个东西很好玩,你可以用这些东西来展现多彩世界。
我在PHP、C/CPP、SHELL等输出文本中都写这些东西。。。

格式:
echo "\033[字背景颜色;字体颜色m字符串\033[0m"

例如:
C程序语句:

printf(" \033[41;36m something here \033[0m");

PHP:

echo "Rpc Time:\033[40;33m",$string,"\033[0m\n";

and so on...
其中41的位置代表底色, 36的位置是代表字的颜色

那些ascii code 是对颜色调用的始末.
\033[ ; m …… \033[0m

字背景颜色范围:40----49
40:黑
41:深红
42:绿
43:黄色
44:蓝色
45:紫色
46:深绿
47:白色

字颜色:30-----------39
30:黑
31:红
32:绿
33:黄
34:蓝色
35:紫色
36:深绿
37:白色

==============================ANSI控制码的说明
\33[0m 关闭所有属性
\33[1m 设置高亮度
\33[4m 下划线
\33[5m 闪烁
\33[7m 反显
\33[8m 消隐
\33[30m -- \33[37m 设置前景色
\33[40m -- \33[47m 设置背景色
\33[nA 光标上移n行
\33[nB 光标下移n行
\33[nC 光标右移n行
\33[nD 光标左移n行
\33[y;xH设置光标位置
\33[2J 清屏
\33[K 清除从光标到行尾的内容
\33[s 保存光标位置
\33[u 恢复光标位置
\33[?25l 隐藏光标
\33[?25h 显示光标

2008年6月18日星期三

答辩?还是便秘?

==本文纯属吐槽,请无视,谢谢==
今天参加一个C语言实训的答辩,气死某熊了。吐槽一下,以解心头之气。

本来是C语言的实训,有人竟然堂而皇之地用C++,还用MFC,而且所有人都是讲的很长很长很长很长很长很长很长很长很长很长,而且,我排在最后一个,从7:30等到9:00还没结束。

然后是内容,不是什么***管理系统,就是***销售系统。烦都烦死了。总之感觉就和小孩过家家一样没意思。

等到我的笔记本剩余电量小于20%之后,某熊彻底丧失耐心,走人。去TNND的大便吧……

2008年6月17日星期二

IcyBear's File Storge Server

其实并不是一个服务器软件……因为那个空间不支持目录浏览,而且还有关不掉的防盗链功能……极其郁闷……所以就写了这个玩意儿……好久没碰ASP了,都忘了怎么写了,一开始每句后面习惯性加一个分号if语句总是不自觉的加上大括号啥的……

链接在这里:
这是代码
这是示例

2008年6月15日星期日

某熊犯难……到底是用哪边比较好?

现在犯难中……是应该继续用原来的WordPress呢?还是换到Blogger呢……MS两边都不是特别稳定……

2008年6月14日星期六

此博客调整中

此博客目前正在调整中……
由于某喜欢水产的SB ZF的某SB GFW,目前某熊正在抓狂ing.....
原来的WordPress现在在http://wp.icybear.cn

2008年6月10日星期二

天空中飞舞的妖精——战斗妖精雪风通关留念

前两天下载了一个雪风,用了一个周末的时间把它打通关了……感觉这个游戏可以吐槽的地方不少。

首先,说说剧情,剧情基本上和OVA是一样的,但是只有OVA中的前一两集。整个任务流程非常短。也没有什么分支剧情,任务提示也不是很全……倒数第二关时,他设定的是主角的飞机一定会被击落……但是我左闪又避没有被击落……直接熬到了时间结束,任务失败……这设定也太烂了吧。

然后是3D模型,好吧,作为一个比较古老的游戏,画面基本上还说的过去,但是感觉不如ACE COMBAT系列来的精致,最要命的是飞机的起落架……在跑道滑行时,起落架上的轮子是不会转的……而且飞行时起落架竟然没有收起来……这是何等的师太!

之后是系统兼容性……作为古老的游戏……在新系统上有点问题是正常的,但是这问题的诡异程度就有点麻烦了……但你从游戏里直接切换回去时,你会惊奇的发现……系统就这么卡住了……虽然背景音还在放,但是什么按键都无用了……用Ctrl_Alt_Delete调出任务管理器,发现竟然没法结束进程。因为鼠标和键盘的输入都被游戏拦截掉了……我费了好大的劲才把他结束掉。

最后是按键问题:游戏里只有输入选择是用键盘游戏还是用飞行摇杆,但是没有重新定义键位的选项,幸好本熊是用Jok2Key模拟键盘玩的,感觉用键盘飞模拟飞行类游戏很不爽。

总之,这个游戏的评价并不很高,我也是冲着雪风的名气才会去下载这个游戏的。

另附:A9VG上的介绍+攻略:

http://bbs.a9vg.com/read.php?tid=460154&fpage=1&toread=&page=1

以上。

2008年6月1日星期日

事件监听器支持类

因为要写一个带事件的类,所以就写了这个东西。废话不多说,直接贴代码了:


/*

* Copyrights (C) 2008 Bearice (Bearice@Gmail.com)

* Release under GNU/GPL Version 2.

*/

package cn.bearice.java.util.listener;



import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Collections;

import java.util.EventListener;

import java.util.List;

import java.util.TreeSet;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



/**

* 监听器支持。

* 同于扩展特定的监听器支持类。

* <p>提供监听器的添加,获取和移除服务。提供多监听器的全同步、全异步、顺序同步,顺序异步调用。</p>

* <p>调用侦听器时不保证侦听器的调用顺序。</p>

* <p>除非特别说明,传人任何等于null的参数都将引发NullPointerException</p>

*
@author Bearice

*/

public abstract class ListenerSupport<T extends EventListener> {



protected static final ExecutorService tp = Executors.newCachedThreadPool();

protected static final ExecutorService stp = Executors.newSingleThreadExecutor();

protected Collection<T> listeners = new TreeSet<T>();



private static class ListenerCaller implements Callable<Object> {



private Method method;

private Object[] args;

private EventListener listener;



public ListenerCaller(Method method, EventListener listener, Object[] args) {

this.method = method;

this.args = args;

this.listener = listener;

}



public Object call() throws Exception {

return method.invoke(tp, args);

}

}



/**

* 添加一个侦听器。

* <p>如果侦听器已经存在,则忽略。</p>

*
@param listener 要添加的侦听器

*
@throws NullPointerException listener等于null

*/

public void addListener(T listener) {

if (listener == null) {

throw new NullPointerException();

}

if (!listeners.contains(listener)) {

listeners.add(listener);

}

}



/**

* 移除一个侦听器。

* <p>如果侦听器不存在,则忽略。</p>

*
@param listener 要移除的侦听器

*
@throws NullPointerException listener等于null

*/

public void removeListener(T listener) {

if (listener == null) {

throw new NullPointerException();

}

if (listeners.contains(listener)) {

listeners.remove(listener);

}

}



/**

* 获取所有侦听器。

* 返回一个包含所有侦听器的<b>不可修改的</b>侦听器集合副本。

* 任何针对该副本的修改操作将引发异常

*
@return 侦听器集合副本。

*/

public Collection<T> getAllListeners() {

return Collections.unmodifiableCollection(listeners);

}



/**

* 全异步调用所有侦听器。

* <p>所有侦听器将在不同的线程中同时调用,该方法不会阻塞当前线程。</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventAsync(Method method, Object... args) {

for (EventListener eventListener : listeners) {

tp.submit(new ListenerCaller(method, eventListener, args));

}

}



/**

* 全同步调用所有侦听器。

* <p>所有侦听器将在不同的线程中同时调用,该方法会阻塞当前线程并等待所有监听器调用全部返回之后才返回</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventSync(Method method, Object... args) throws InterruptedException {

List<Callable> allCallable = new ArrayList<Callable>(listeners.size());

for (EventListener eventListener : listeners) {

allCallable.add(new ListenerCaller(method, eventListener, args));

}

tp.invokeAll((Collection) allCallable);

}



/**

* 顺序异步调用所有侦听器。

* <p>所有侦听器将在相同同的线程中顺序调用,该方法不会阻塞当前线程。</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

* <p><b>调用顺序:</b>不确定调用侦听器的顺序</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventAsyncSeq(Method method, Object... args) {

for (EventListener eventListener : listeners) {

stp.submit(new ListenerCaller(method, eventListener, args));

}

}



/**

* 顺序同步调用所有侦听器。

* <p>所有侦听器将在相同的线程中顺序调用,该方法会阻塞当前线程并等待所有监听器调用全部返回之后才返回</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

* <p><b>调用顺序:</b>不确定调用侦听器的顺序</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventSyncSeq(Method method, Object... args) throws InterruptedException {

List<Callable> allCallable = new ArrayList<Callable>(listeners.size());

for (EventListener eventListener : listeners) {

allCallable.add(new ListenerCaller(method, eventListener, args));

}

stp.invokeAll((Collection) allCallable);

}

}