Java编程思想(6)

第19章 枚举类型

1 enum的函数,ordinal()返回enum的int值,name()返回enum的值

enum Shrubbery {GROUND,CRAWLING,HANGING}

public class TwoTuple{		
	public static void main(String[] args){
		for(Shrubbery s:Shrubbery.values()){
			System.out.println(s+" ordinal: "+s.ordinal());
			System.out.println(s.compareTo(Shrubbery.CRAWLING)+" ");
			System.out.println(s.equals(Shrubbery.CRAWLING)+" ");
			System.out.println(s == Shrubbery.CRAWLING);
			System.out.println(s.getDeclaringClass());
			System.out.println(s.name());
			System.out.println("-----------------------");
		}
		for(String s:"HANGING CRAWLING GROUND".split(" ")){
			Shrubbery shrub = Enum.valueOf(Shrubbery.class, s);
			System.out.println(shrub);
		}
	}
}

输出
GROUND ordinal: 0
-1 
false 
false
class c06.Shrubbery
GROUND
-----------------------
CRAWLING ordinal: 1
0 
true 
true
class c06.Shrubbery
CRAWLING
-----------------------
HANGING ordinal: 2
1 
false 
false
class c06.Shrubbery
HANGING
-----------------------
HANGING
CRAWLING
GROUND

2 将静态导入用于enum,import static

//c06/Spiciness.java
public enum Spiciness {
    NOT,MILD,MEDIUM,HOT,FLAMING
}

//c06/TwoTuple
import static c06.Spiciness.*;   // 静态导入

public class TwoTuple{		
	Spiciness degree;
	public TwoTuple(Spiciness degree){ this.degree = degree; }
	public String toString(){ return "TwoTuple is "+degree; }
	public static void main(String[] args){
		System.out.println(new TwoTuple(NOT));
		System.out.println(new TwoTuple(MEDIUM));
		System.out.println(new TwoTuple(HOT));
	}
}

3 除了不能继承自一个enum外,可以将enum看作一个常规的类。可以向enum中添加函数,甚至main()函数.enum中的构造器与函数跟普通类没什么区别。

public enum TwoTuple{		
	WEST("Miss Gulch,aka the Wichked Witch of the West"),
	NORTH("Glinda,the Good Witch of the North"),
	EAST("Wicked Witch of the East,wearer of the Ruby Slippers,crushed by Dorothy's house"),
	SOUTH("Good by inference,but missing");
	private String description;
	private TwoTuple(String description){
		this.description = description;
	}
	public String getDescription(){
		return description;
	}
	public static void main(String[] args){
		for(TwoTuple s:TwoTuple.values())
			System.out.println(s+": "+s.getDescription());
	}
}

4 覆盖enum里的函数

public enum TwoTuple{		
	SCOUT,CARGO,TRANSPORT,CRUISER,BATTLESHIP,MOTHERSHIP;
	public String toString(){
		String id = name();
		String lower = id.substring(1).toLowerCase();
		return id.charAt(0)+lower;
	}
	public static void main(String[] args){
		for(TwoTuple s:TwoTuple.values())
			System.out.println(s);
	}
}

5 switch语句中的enum

enum Signal {GREEN,YELLOW,RED}

public class TwoTuple{		
	Signal color = Signal.RED;
	public void change(){
		switch(color){
		case RED:
			color = Signal.GREEN;
			break;
		case GREEN:
			color = Signal.YELLOW;
			break;
		case YELLOW:
			color = Signal.RED;
			break;
		}
	}
	public String toString(){
		return "The traffic light is "+color;
	}
	public static void main(String[] args){
		TwoTuple t = new TwoTuple();
		for(int i=0;i<7;i++){
			System.out.println(t);
			t.change();
		}
	}
}

6 values()的神秘之处,enum类都继承自Enum类。Enum类没有values()

enum Explore { HERE,THERE }
public class TwoTuple{		
	public static Set<String> analyze(Class<?> enumClass){
		System.out.println("----- Analyzeing "+enumClass+" -----");
		System.out.println("Interfaces:");
		for(Type t : enumClass.getGenericInterfaces())
			System.out.println(t);
		System.out.println("Base: "+enumClass.getSuperclass());
		System.out.println("Methods: ");
		Set<String> methods = new TreeSet<String>();
		for(Method m : enumClass.getMethods())
			methods.add(m.getName());
		System.out.println(methods);
		return methods;
	}
	public static void main(String[] args){
		Set<String> exploreMethods = analyze(Explore.class);
		Set<String> enumMethods = analyze(Enum.class);
		System.out.println("Explore.containsAll(Enum)? "+exploreMethods.containsAll(enumMethods));
		System.out.print("Explore.removeAll(Enum): ");
		exploreMethods.removeAll(enumMethods);
		System.out.println(exploreMethods);
	}
}

输出
----- Analyzeing class c06.Explore -----
Interfaces:
Base: class java.lang.Enum
Methods: 
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
----- Analyzeing class java.lang.Enum -----
Interfaces:
java.lang.Comparable<E>
interface java.io.Serializable
Base: class java.lang.Object
Methods: 
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
Explore.containsAll(Enum)? true
Explore.removeAll(Enum): [values]

7 所有的enum都继承自java.lang.Enum类,enum不能再继承其他类,只能实现接口。如下是错误

     enum  NotPossible  extends   Pet  {  . . .   }    // error ,不能继承Pet类

enum CartoonCharacter implements Generator<CartoonCharacter> {
	SLAPPY,SPANKY,PUNCHY,SILLY,BOUNCY,NUTTY,BOB;
	private Random rand = new Random(47);
	public CartoonCharacter next(){
		return values()[rand.nextInt(values().length)];
	}
}

8 随机选取

class Enums {
	private static Random rand = new Random(47);
	public static <T extends Enum<T>> T random(Class<T> ec){
		return random(ec.getEnumConstants());
	}
	public static <T> T random(T[] values){
		return values[rand.nextInt(values.length)];   // 随机选取
	}
}
enum Activity { SITTING,LYING,STANDING,HOPPING,RUNNING,DODGNG,JUMPING,FALLING,FLYING}
public class TwoTuple{		
	
	public static void main(String[] args){
		for(int i=0;i<20;i++){
			System.out.print(Enums.random(Activity.class)+" ");
		}
	}
}

9 enum要求成员都是唯一。Java SE5引入了EnumSet

enum AlarmPoints {
	STAIR1,STAIR2,LOBBY,OFFICE1,OFFICE2,OFFICE3,OFFICE4,BATHROOM,UTILITY,KITCHEN
}
public class TwoTuple{		
	
	public static void main(String[] args){
		EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class);
		points.add(AlarmPoints.BATHROOM);
		System.out.println(points);
		points.addAll(EnumSet.of(AlarmPoints.STAIR1,AlarmPoints.STAIR2,AlarmPoints.KITCHEN));
		System.out.println(points);
		points = EnumSet.allOf(AlarmPoints.class);
		points.removeAll(EnumSet.of(AlarmPoints.STAIR1,AlarmPoints.STAIR2,AlarmPoints.KITCHEN));
		System.out.println(points);
		points.removeAll(EnumSet.range(AlarmPoints.OFFICE1, AlarmPoints.OFFICE4));
		System.out.println(points);
		points = EnumSet.complementOf(points);
		System.out.println(points);
	}
}

10 使用EnumMap,它要求键必须是enum。

11 Java允许为enum实例编写函数,,如下

public enum TwoTuple{		
	
	DATE_TIME{
		String getInfo(){
			return DateFormat.getDateInstance().format(new Date());
		}
	},
	CLASSPATH {
		String getInfo(){
			return System.getenv("CLASSPATH");
		}
	},
	VERSION {
		String getInfo(){
			return System.getProperty("java.version");
		}
	};
	abstract String getInfo();
	public static void main(String[] args){
		for(TwoTuple csm:values())
			System.out.println(csm.getInfo());
	}
}

12 使用enum的状态机

public enum TwoTuple{		
	NICKEL(5),DIME(10),QUARTER(25),DOLLAR(100),
	TOOTHPASTE(200),CHIPS(75),SODA(100),SOAP(50),
	ABORT_TRANSACTION {
		public int amount(){
			throw new RuntimeException("ABORT.amount()");
		}
	},
	STOP {
		public int amount(){
			throw new RuntimeException("SHUT_DOWN.amount()");
		}
	};
	int value;
	TwoTuple(int value){ this.value = value;}
	TwoTuple(){}
	int amount(){ return value; }
	static Random rand = new Random(47);
	public static TwoTuple randomSelection(){
		return values()[rand.nextInt(values().length-1)];
	}
}

第20章 注解

1 Java SE5内置了三种定义在java.lang中的注解:

  •  @Override,表示当前的方法定义将覆盖超类中的方法。如果因为拼写错误,或函数签名对不上等导致覆盖失败,编译器会报错
  • @Deprecated,如果使用了注解为它的元素,编译器会发出警告信息
  • @SuppressWarning,关闭不当的编译器警告信息。

2 元注解

3 编写注解处理器,getAnnoation()函数返回指定类型的注解对象。

public class TwoTuple{		
	public static void trackUseCases(List<Integer> useCases,Class<?> cl){
		for(Method m : cl.getDeclaredMethods()){
			UseCase uc = m.getAnnotation(UseCase.class);
			if(uc != null){
				System.out.println("Found UseCase: "+uc.id()+" "+ud.description());
				useCases.remove(new Integer(uc.id()));
			}
		}
		for(int i:useCases)
			System.out.println("Warning: Missing use case-"+i);
	}
	public static void main(String[] args){
		List<Integer> useCases = new ArrayList<Integer>();
		Collections.addAll(useCases, 47,48,49,50);
		trackUseCases(useCases,PasswordUtils.class);
	}
}

第21章 并发

1 基本的Web类库,Servlet是天生的多线程性。

2 Java的线程机制是抢占式的,这表示调度机制会周期性地中断线程,将上下问切换到另一个线程,从而为每个线程都提供时间片,使得每个线程都会分配到数量合理的时间去驱动它的任务。

3 定义任务只需实现Runnable接口并编写run()方法。如下所示

class LiftOff implements Runnable{		
	protected int countDown = 10;
	private static int taskCount = 0;
	private final int id = taskCount ++;
	public LiftOff(){}
	public LiftOff(int countDown){
		this.countDown = countDown;
	}
	public String status(){
		return "#"+id+"("+(countDown>0?countDown:"Liftoff!")+").";
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(countDown-- > 0){
			System.out.print(status());
			Thread.yield();
		}
	}
	
}
public class TwoTuple{
	public static void main(String[] args){
		LiftOff lauch = new LiftOff();
		lauch.run();   // 启动线程
	}
}

在run()中对静态函数Thread.yield()的调用是对线程调度器的一个提示,即告诉调度器“我已经执行完生命周期中最重要的部分,此刻可以切换给其他任务执行”。

4 也可以将Runnable对象提交给Thread构造器

class LiftOff implements Runnable{		
	protected int countDown = 10;
	private static int taskCount = 0;
	private final int id = taskCount ++;
	public LiftOff(){}
	public LiftOff(int countDown){
		this.countDown = countDown;
	}
	public String status(){
		return "#"+id+"("+(countDown>0?countDown:"Liftoff!")+").";
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(countDown-- > 0){
			System.out.print(status());
			Thread.yield();
		}
	}
	
}
public class TwoTuple{
	public static void main(String[] args){
		Thread t = new Thread(new LiftOff());
		t.start();
	}
}

5 Java SE5的java.util.concurrent包中的执行器(Executor)管理Thread对象。Executor在客户端和任务执行之间提供一间接层,由Executor执行任务。Executor允许你管理异步任务的执行,而无需显式的管理线程的生命周期。

class LiftOff implements Runnable{		
	protected int countDown = 10;
	private static int taskCount = 0;
	private final int id = taskCount ++;
	public LiftOff(){}
	public LiftOff(int countDown){
		this.countDown = countDown;
	}
	public String status(){
		return "#"+id+"("+(countDown>0?countDown:"Liftoff!")+").";
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(countDown-- > 0){
			System.out.print(status());
			Thread.yield();
		}
	}
	
}
public class TwoTuple{
	public static void main(String[] args){
		ExecutorService exec = Executors.newCachedThreadPool();
		for(int i=0;i<5;i++){
			exec.execute(new LiftOff());  // 由Executor创建Thread对象
		}
                exec.shutdown();
	}
}

shutdown()的调用可以防止新任务继续提交给这个Executor.

6 可以使用FixedThreadPool,提前设置线程的数量

class LiftOff implements Runnable{		
	protected int countDown = 10;
	private static int taskCount = 0;
	private final int id = taskCount ++;
	public LiftOff(){}
	public LiftOff(int countDown){
		this.countDown = countDown;
	}
	public String status(){
		return "#"+id+"("+(countDown>0?countDown:"Liftoff!")+").";
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(countDown-- > 0){
			System.out.print(status());
			Thread.yield();
		}
	}
	
}
public class TwoTuple{
	public static void main(String[] args){
		ExecutorService exec = Executors.newFixedThreadPool(5);
		for(int i=0;i<5;i++){
			exec.execute(new LiftOff());
		}
		exec.shutdown();
	}
}

7 SingleThreadExecutor像是线程数量为1的FixedThreadPool,常用于连续运行的任务,如一直监听进入的套接字连接任务等。如果向SingleThreadExecutor提交多个任务,这些任务会排队等待。

class LiftOff implements Runnable{		
	protected int countDown = 10;
	private static int taskCount = 0;
	private final int id = taskCount ++;
	public LiftOff(){}
	public LiftOff(int countDown){
		this.countDown = countDown;
	}
	public String status(){
		return "#"+id+"("+(countDown>0?countDown:"Liftoff!")+").";
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(countDown-- > 0){
			System.out.print(status());
			Thread.yield();
		}
	}
	
}
public class TwoTuple{
	public static void main(String[] args){
		ExecutorService exec = Executors.newSingleThreadExecutor();
		for(int i=0;i<5;i++){
			exec.execute(new LiftOff());
		}
		exec.shutdown();
	}
}

输出
#0(9).#0(8).#0(7).#0(6).#0(5).#0(4).#0(3).#0(2).#0(1).#0(Liftoff!).
#1(9).#1(8).#1(7).#1(6).#1(5).#1(4).#1(3).#1(2).#1(1).#1(Liftoff!).
#2(9).#2(8).#2(7).#2(6).#2(5).#2(4).#2(3).#2(2).#2(1).#2(Liftoff!).
#3(9).#3(8).#3(7).#3(6).#3(5).#3(4).#3(3).#3(2).#3(1).#3(Liftoff!).
#4(9).#4(8).#4(7).#4(6).#4(5).#4(4).#4(3).#4(2).#4(1).#4(Liftoff!).

8 从任务中产生返回值,Runnable执行任务但不返回值,如果希望有返回值可以实现Callable接口而不是Runnable接口。在Java SE5引入Callable是一具有类型参数的泛型,它表示是从函数call返回的值的类型,并且必须使用ExecutorService.submit()函数调用它

class TaskWithResult implements Callable<String>{		
	private int id;
	public TaskWithResult(int id){
		this.id = id;
	}
	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		return "result of TaskWithResult "+id;
	}
}
public class TwoTuple{
	public static void main(String[] args){
		ExecutorService exec = Executors.newCachedThreadPool();
		ArrayList<Future<String>> result = new ArrayList<Future<String>>();
		for(int i=0;i<10;i++)
			result.add(exec.submit(new TaskWithResult(i)));
		for(Future<String> s:result){
			try{
				System.out.println(s.get());
			}catch(InterruptedException e){
				System.out.println(e);
				return;
			}catch(ExecutionException e){
				System.out.println(e);
			}finally{
				exec.shutdown();
			}
		}
	}
}

submit()函数会产生Future对象。可以用isDone()函数查询Future是否已经完成。用get()函数来获取返回值。最好先有isDone()检查是否完成再调用get(),不然get()容易阻塞。

9 调用sleep()进行休眠,老版本用Thread.sleep(100),Java SE5/6采用TimeUnit.MILLISECONDS.sleep(100)

class LiftOff implements Runnable{		
	protected int countDown = 10;
	private static int taskCount = 0;
	private final int id = taskCount ++;
	public LiftOff(){}
	public LiftOff(int countDown){
		this.countDown = countDown;
	}
	public String status(){
		return "#"+id+"("+(countDown>0?countDown:"Liftoff!")+").";
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(countDown-- > 0){
			System.out.print(status());
			Thread.yield();
		}
	}
	
}
public class TwoTuple extends LiftOff{
	public void run(){
		try{
			while(countDown-- > 0){
				System.out.println(status());
				// Old-style
				// Thread.sleep(100);
				// Java SE5/6-style
				TimeUnit.MILLISECONDS.sleep(100);
			}
		}catch(InterruptedException e){
			System.out.println("Interrupted");
		}
	}
	public static void main(String[] args){
		ExecutorService exec = Executors.newSingleThreadExecutor();
		for(int i=0;i<5;i++){
			exec.execute(new LiftOff());
		}
		exec.shutdown();
	}
}

10 可以用setPriority()来读取现有线程的优先级,并且在任何时刻都可以通过setPriority()来修改

public class TwoTuple implements Runnable{
	private int countDown = 5;
	private volatile double d;
	private int priority;
	public TwoTuple(int priority){
		this.priority = priority;
	}
	public String toString(){
		return Thread.currentThread()+": "+countDown;
	}
	public void run(){
		Thread.currentThread().setPriority(priority);
		while(true){
			for(int i=1;i<10000;i++){
				d += (Math.PI+Math.E)/(double)i;
				if(i%1000 == 0)
					Thread.yield();
			}
			System.out.println(this);
			if(--countDown == 0)
				return;
		}
	}
	public static void main(String[] args){
		ExecutorService exec = Executors.newCachedThreadPool();
		for(int i=0;i<5;i++)
			exec.execute(new TwoTuple(Thread.MIN_PRIORITY));
		exec.execute(new TwoTuple(Thread.MAX_PRIORITY));
		exec.shutdown();
	}
	
}

11 后台(daemon)线程,是指在程序运行时在后台提供一种通用服务的线程。

public class TwoTuple implements Runnable{
	public void run(){
		try{
			while(true){
				TimeUnit.MILLISECONDS.sleep(100);
				System.out.println(Thread.currentThread()+": "+this);
			}
		}catch(InterruptedException e){
			System.out.println("sleep() interrupted");
		}
	}
	public static void main(String[] args) throws Exception{
		for(int i=0;i<10;i++){
			Thread daemon = new Thread(new TwoTuple());
			daemon.setDaemon(true);
			daemon.start();
		}
		System.out.println("All daemons started");
		TimeUnit.MILLISECONDS.sleep(175);
	}
}

12 除了实现Runnable,可以通过继承Thread来实现多线程

public class TwoTuple extends Thread{
	private int countDown = 5;
	private static int threadCount = 0;
	public TwoTuple(){
		super(Integer.toString(++threadCount));
		start();
	}
	public String toString(){
		return "#"+getName()+"("+countDown+")";
	}
	public void run(){
		while(true){
			System.out.println(this);
			if(--countDown == 0)
				return;
		}
	}
	public static void main(String[] args) throws Exception{
		for(int i=0;i<10;i++){
			new TwoTuple();
		}
	}
}

13 一个线程可以在其他线程上调用join()函数,其效果是等待一段时间直到第二个线程结束才能继续执行。如果某个线程在另一个线程t上调用t.join(),此线程将被挂起,直到目标线程t结束后才恢复(即t.isAlive()返回false)。

class Sleeper extends Thread{
	private int duration;
	public Sleeper(String name,int sleepTime){
		super(name);
		duration = sleepTime;
		start();
	}
	public void run(){
		try{
			sleep(duration);
		}catch(InterruptedException e){
			System.out.println(getName()+" was interrupted. "
					+"isInterrupted(): "+isInterrupted());
			return;
		}
		System.out.println(getName()+" has awakened");
	}
}
class Joiner extends Thread{
	private Sleeper sleeper;
	public Joiner(String name,Sleeper sleeper){
		super(name);
		this.sleeper = sleeper;
		start();
	}
	public void run(){
		try{
			sleeper.join();
		}catch(InterruptedException e){
			System.out.println("Interrupted");
		}
		System.out.println(getName()+" join completed");
	}
}
public class TwoTuple {
	
	public static void main(String[] args) {
		Sleeper sleepy = new Sleeper("Sleepy",1500);
		Sleeper grumpy = new Sleeper("Grumpy",1500);
		Joiner dopey = new Joiner("Dopey",sleepy);
		Joiner doc = new Joiner("Doc",grumpy);
		grumpy.interrupt();
	}
}

输出
Grumpy was interrupted. isInterrupted(): false
Doc join completed
Sleepy has awakened
Dopey join completed

14 Java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持。

15 同步操作

  • 用synchronized同步控制
public class TwoTuple extends IntGenerator {
	private int currentEvenValue = 0;
	public synchronized int next(){   // 同步
		++currentEvenValue;
		Thread.yield();
		++currentEvenValue;
		return currentEvenValue;
	}
	public static void main(String[] args) {
		... 
	}
}
  • 使用显式的Lock对象,Java SE5的java.util.concurrent类库包含定义在java.util.concurrent.locks中的显式的互斥机制。Lock对象必须被显式地创建,锁定和释放
public class TwoTuple extends IntGenerator {
	private int currentEvenValue = 0;
	private Lock lock = new ReentrantLock();  // Lock对象创建
	public int next(){
		lock.lock();   // Lock对象锁定
		try{
			++currentEvenValue;
			Thread.yield();
			++currentEvenValue;
			return currentEvenValue;
		}finally{
			lock.unlock();  // Lock对象释放
		}
	}
	public static void main(String[] args) {
		EvenChecker.test(new TwoTuple());
	}
}

16 当你定义long或double变量时,如果使用volatile关键字,就会获得的原子性。

17 Java SE5引入了如AtomicInteger,AtomicLong,AtomicReference等原子性变量类。

public class TwoTuple implements Runnable {
	private AtomicInteger i = new AtomicInteger(0);
	public int getValue(){
		return i.get();
	}
	private void evenIncrement(){
		i.addAndGet(2);
	}
	public void run(){
		while(true){
			evenIncrement();
		}
	}
	public static void main(String[] args) {
		new Timer().schedule(new TimerTask(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("Aborting");
				System.exit(0);
			}
			
		},5000);
		ExecutorService exec = Executors.newCachedThreadPool();
		TwoTuple a = new TwoTuple();
		exec.execute(a);
		while(true){
			int val = a.getValue();
			if(val%2 != 0){
				System.out.println(val);
				System.exit(0);
			}
		}
	}
}

18 临界区,使用synchronized指定某个对象

public class TwoTuple implements Runnable {
	public void increment(){
		Pair temp;
		synchronized(this){
			p.incrementX();
			p.incrementY();
			temp = getPair();
		}
	}
}

19 一个线程可以处于四种状态:新建(new),就绪(Runnable),阻塞(Blocked),死亡(Dead)

20 wait()表示任务挂起,并且只在notify()或notifyAll()发生时,该任务才会被唤醒。

第22章 图形化用户界面

1 大多数Swing应用都被构建在基础的JFrame内部,JFrame在你使用的任何操作系统中都可以创建视窗应用。

public class TwoTuple {
	public static void main(String[] args) throws Exception{
		JFrame frame = new JFrame("Hello Swing");
		JLabel label = new JLabel("A Label");
		frame.add(label);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(300, 100);
		frame.setVisible(true);
		TimeUnit.MILLISECONDS.sleep(1);
		label.setText("Hey! This is Different");
	}
}

setDefaultCloseOperation()告诉JFrame当用户执行关闭操作时应该做什么。setSize()以像素为单位设置视窗的尺寸。setVisible(true)表示显示视窗,没有这句就看不到界面。

2 其他线程应该通过Swing事件分发线程提交要执行的任务。可以通过任务提交给SwingUtilities.invokeLater()来实现这种方式,它会通过事件分发线程将任务放置到待执行事件行列中。

public class TwoTuple {
	public static void main(String[] args) throws Exception{
		JFrame frame = new JFrame("Hello Swing");
		final JLabel label = new JLabel("A Label");
		frame.add(label);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(300, 100);
		frame.setVisible(true);
		TimeUnit.MILLISECONDS.sleep(1);
		SwingUtilities.invokeLater(new Runnable(){  // 分发线程
			@Override
			public void run() {
				// TODO Auto-generated method stub
				label.setText("Hey! This is Different");
			}			
		});
	}
}

3 继承JFrame

public class TwoTuple extends JFrame{
	JLabel label;
	public TwoTuple(){
		super("Hello Swing");
		label = new JLabel("A Label");
		add(label);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(300, 100);
		setVisible(true);
	}
	static TwoTuple ssp;
	public static void main(String[] args) throws Exception{
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				ssp = new TwoTuple();
			}			
		});
		TimeUnit.MILLISECONDS.sleep(1);
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				ssp.label.setText("Hey! This is Different");
			}			
		});
	}
}

4 创建按键,使用JButton。FlowLayout是”布局管理器“,即面板用来隐式地决定控件在窗体上的位置的工具。JFrame通常使用BorderLayout管理布局。FlowLayout使得控件可以从窗体上从左到右,从上到下连续均匀分布。

public class TwoTuple extends JFrame{
	private JButton b1 = new JButton("Button1"),
			b2 = new JButton("Button2");
	public TwoTuple(){
		setLayout(new FlowLayout());
		add(b1);
		add(b2);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}
			
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,100);
	}
}

5 捕获事件,比如调用JButton的addActionListener()函数

public class TwoTuple extends JFrame{
	private JButton b1 = new JButton("Button1"),
			b2 = new JButton("Button2");
	private JTextField txt = new JTextField(10);
	class ButtonListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String name = ((JButton)e.getSource()).getText();
			txt.setText(name);
		}	
	}
	private ButtonListener bl = new ButtonListener();
	public TwoTuple(){
		b1.addActionListener(bl);
		b2.addActionListener(bl);
		setLayout(new FlowLayout());
		add(b1);
		add(b2);
		add(txt);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,100);
	}
}

6 文本区域JTextArea

public class TwoTuple extends JFrame{
	private JButton b = new JButton("Add Data"),
			c = new JButton("Clear Data");
	private JTextArea t = new JTextArea(20,40);
	private Map<String,String> m = new HashMap<String,String>();
	public TwoTuple(){
		m.put("key1", "value1");
	    m.put("key2", "value2");
	    m.put("key3", "value3");
		b.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				for(Map.Entry<String, String> me:m.entrySet())
					t.append(me.getKey()+": "+me.getValue()+"\n");
			}
			
		});
		c.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				t.setText("");
			}
		});
		setLayout(new FlowLayout());
		add(new JScrollPane(t));
		add(b);
		add(c);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),476,425);
	}
}

7 控制布局

  • BorderLayout.NORTH   顶端
  • BorderLayout.SOUTH   底端
  • BorderLayout.EAST      右端
  • BorderLayout.WEST     左端
  • BorderLayout.CENTER   中央
public class TwoTuple extends JFrame{
	public TwoTuple(){
		add(BorderLayout.NORTH,new JButton("North"));
		add(BorderLayout.SOUTH,new JButton("South"));
		add(BorderLayout.EAST,new JButton("East"));
		add(BorderLayout.WEST,new JButton("West"));
		add(BorderLayout.CENTER,new JButton("Center"));
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),300,250);
	}
}

8 FlowLayout将组件从左到右“流动”到窗体上,直到占满上方的空间,然后向下移动一行,继续流动。

public class TwoTuple extends JFrame{
	public TwoTuple(){
		setLayout(new FlowLayout());
		for(int i=0;i<20;i++)
			add(new JButton("Button #"+i));
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),300,250);
	}
}

9 GridLayout构建放置控件的表格,如new GridLayout( 7 , 3 )表示7行3列的表格 

public class TwoTuple extends JFrame{
	public TwoTuple(){
		setLayout(new GridLayout(7,3));
		for(int i=0;i<20;i++)
			add(new JButton("Button #"+i));
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),300,300);
	}
}

10 事件与监听器的类型

11 事件监听

public class TwoTuple extends JFrame{
	private JTextField name = new JTextField(25);
	private JTextArea results = new JTextArea(40,65);
	private static Pattern addListener = Pattern.compile("(add\\w+?Listener\\(.*?\\))");
	private static Pattern qualifier = Pattern.compile("\\w+\\.");
	class NameL implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String nm = name.getText().trim();
			if(nm.length() == 0){
				results.setText("No match");
				return;
			}
			Class<?> kind;
			try{
				kind = Class.forName("javax.swing."+nm);
			}catch(ClassNotFoundException t){
				results.setText("No match");
				return;
			}
			Method[] methods = kind.getMethods();
			results.setText("");
			for(Method m:methods){
				Matcher matcher = addListener.matcher(m.toString());
				if(matcher.find())
					results.append(qualifier.matcher(matcher.group(1)).replaceAll("")+"\n");
			}
		}
	}
	public TwoTuple(){
		NameL nameListener = new NameL();
		name.addActionListener(nameListener);
		JPanel top = new JPanel();
		top.add(new JLabel("Swing class name (press Enter):"));
		top.add(name);
		add(BorderLayout.NORTH,top);
		add(new JScrollPane(results));
		name.setText("JTextArea");
		nameListener.actionPerformed(new ActionEvent("",0,""));
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),800,400);
	}
}

12 Swing的按钮

public class TwoTuple extends JFrame{
	private JButton jb = new JButton("JButton");
	private BasicArrowButton up = new BasicArrowButton(BasicArrowButton.NORTH);
	private BasicArrowButton down = new BasicArrowButton(BasicArrowButton.SOUTH);
	private BasicArrowButton left = new BasicArrowButton(BasicArrowButton.EAST);
	private BasicArrowButton right = new BasicArrowButton(BasicArrowButton.WEST);
	public TwoTuple(){
		setLayout(new FlowLayout());
		add(jb);
		add(new JToggleButton("JToggleButton"));
		add(new JCheckBox("JCheckBox"));
		add(new JRadioButton("JRadioButton"));
		JPanel jp = new JPanel();
		jp.setBorder(new TitledBorder("Directions"));
		jp.add(up);
		jp.add(down);
		jp.add(left);
		jp.add(right);
		add(jp);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),350,200);
	}
}

13 按钮组(ButtonGroup)

public class TwoTuple extends JFrame{
	private static String[] ids = {
			"June","Ward","Beaver","Wally","Eddie","Lumpy"
	};
	static JPanel makeBPanel(
		Class<? extends AbstractButton> kind,String[] ids){
		ButtonGroup bg = new ButtonGroup();
		JPanel jp = new JPanel();
		String title = kind.getName();
		title = title.substring(title.lastIndexOf('.')+1);
		jp.setBorder(new TitledBorder(title));
		for(String id:ids){
			AbstractButton ab = new JButton("failed");
			try{
				Constructor ctor = kind.getConstructor(String.class);
				ab = (AbstractButton)ctor.newInstance(id);
			}catch(Exception e){
				System.err.println("can't create "+kind);
			}
			bg.add(ab);
			jp.add(ab);
		}
		return jp;
	}
	public TwoTuple(){
		setLayout(new FlowLayout());
		add(makeBPanel(JButton.class,ids));
		add(makeBPanel(JToggleButton.class,ids));
		add(makeBPanel(JCheckBox.class,ids));
		add(makeBPanel(JRadioButton.class,ids));
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),500,350);
	}
}

14 图标用ImageIcon对象

public class TwoTuple extends JFrame{
	private static Icon[] faces;
	private JButton jb,jb2 = new JButton("Disable");
	private boolean mad = false;
	public TwoTuple(){
		faces = new Icon[]{
				new ImageIcon(getClass().getResource("fac.gif")),
				new ImageIcon(getClass().getResource("fac.gif")),
				new ImageIcon(getClass().getResource("fac.gif"))
		};
		jb = new JButton("JButton",faces[2]);
		setLayout(new FlowLayout());
		jb.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				if(mad){
					jb.setIcon(faces[1]);
					mad = false;
				}else{
					jb.setIcon(faces[0]);
					mad = true;
				}
				jb.setVerticalAlignment(JButton.TOP);
				jb.setHorizontalAlignment(JButton.LEFT);
			}
			
		});
		jb.setRolloverEnabled(true);
		jb.setRolloverIcon(faces[1]);
		jb.setPressedIcon(faces[0]);
		jb.setDisabledIcon(faces[2]);
		jb.setToolTipText("Yow!");
		add(jb);
		jb2.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				if(jb.isEnabled()){
					jb.setEnabled(false);
					jb2.setText("Enable");
				}else{
					jb.setEnabled(true);
					jb2.setText("Disable");
				}
			}
		});
		add(jb2);
	}
	
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),500,350);
	}
}

15 边框

public class TwoTuple extends JFrame{
	static JPanel showBorder(Border b){
		JPanel jp = new JPanel();
		jp.setLayout(new BorderLayout());
		String nm = b.getClass().toString();
		nm = nm.substring(nm.lastIndexOf('.')+1);
		jp.add(new JLabel(nm,JLabel.CENTER),BorderLayout.CENTER);
		jp.setBorder(b);
		return jp;
	}
	public TwoTuple(){
		setLayout(new GridLayout(2,4));
		add(showBorder(new TitledBorder("Title")));
		add(showBorder(new EtchedBorder()));
		add(showBorder(new LineBorder(Color.BLUE)));
		add(showBorder(new MatteBorder(5,5,30,30,Color.GREEN)));
		add(showBorder(new BevelBorder(BevelBorder.RAISED)));
		add(showBorder(new SoftBevelBorder(BevelBorder.LOWERED)));
		add(showBorder(new CompoundBorder(
				new EtchedBorder(),new LineBorder(Color.RED))));	
	}
	
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),500,350);
	}
}

16 复选框 JCheckBox

public class TwoTuple extends JFrame{
	private JTextArea t = new JTextArea(6,15);
	private JCheckBox cb1 = new JCheckBox("Check Box 1");
	private JCheckBox cb2 = new JCheckBox("Check Box 2");
	private JCheckBox cb3 = new JCheckBox("Check Box 3");
	public TwoTuple(){
		cb1.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				trace("1",cb1);
			}		
		});
		cb2.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				trace("2",cb2);
			}		
		});
		cb3.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				trace("3",cb3);
			}		
		});
		setLayout(new FlowLayout());
		add(new JScrollPane(t));
		add(cb1);
		add(cb2);
		add(cb3);
	}
	private void trace(String b,JCheckBox cb){
		if(cb.isSelected())
			t.append("Box "+b+" Set\n");
		else
			t.append("Box "+b+" Cleared\n");
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,350);
	}
}

17 单选按键JRadioButton。要设置一组关联的JRadioButton,需要加入到一个ButtonGroup中。

public class TwoTuple extends JFrame{
	private JTextField t = new JTextField(15);
	private ButtonGroup g = new ButtonGroup();
	private JRadioButton rb1 = new JRadioButton("one",false);
	private JRadioButton rb2 = new JRadioButton("two",false);
	private JRadioButton rb3 = new JRadioButton("three",false);
	private ActionListener al = new ActionListener(){
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			t.setText("Radio button "+((JRadioButton)e.getSource()).getText());
		}		
	};
	public TwoTuple(){
		rb1.addActionListener(al);
		rb2.addActionListener(al);
		rb3.addActionListener(al);
		g.add(rb1);g.add(rb2);g.add(rb3);
		t.setEditable(false);
		setLayout(new FlowLayout());
		add(t);
		add(rb1);
		add(rb2);
		add(rb3);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,350);
	}
}

18 组合框JComboBox

public class TwoTuple extends JFrame{
	private String[] description = {
		"Ebullient","Obtuse","Recalcitrant","Brilliant",
		"Somnescent","Timorous","Florid","Putrescent"
	};
	private JTextField t = new JTextField(15);
	private JComboBox c = new JComboBox();
	private JButton b = new JButton("Add items");
	private int count = 0;
	public TwoTuple(){
		for(int i=0;i<4;i++)
			c.addItem(description[count++]);
		t.setEditable(false);
		b.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				if(count<description.length)
					c.addItem(description[count++]);
			}
		});
		c.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				t.setText("index: "+c.getSelectedIndex()+"  "
						+((JComboBox)e.getSource()).getSelectedItem());
			}
		});
		setLayout(new FlowLayout());
		add(t);
		add(c);
		add(b);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,175);
	}
}

19 列表框JList

public class TwoTuple extends JFrame{
	private String[] flavors = {
			"Chocolate","Strawberry","Vanilla Fudge Swirl",
			"Mint Chip","Mocha Almond Fudge","Rum Raisin",
			"Praline Cream","Mud Pie"
	};
	private DefaultListModel lItems = new DefaultListModel();
	private JList lst = new JList(lItems);
	private JTextArea t = new JTextArea(flavors.length,20);
	private JButton b = new JButton("Add Item");
	private ActionListener bl = new ActionListener(){

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if(count < flavors.length)
				lItems.add(0,flavors[count++]);
			else{
				b.setEnabled(false);
			}
		}
	};
	private ListSelectionListener ll = new ListSelectionListener(){

		@Override
		public void valueChanged(ListSelectionEvent e) {
			// TODO Auto-generated method stub
			if(e.getValueIsAdjusting()) return;
			t.setText("");
			for(Object item:lst.getSelectedValues())
				t.append(item+"\n");
		}
	};
	private int count = 0;
	public TwoTuple(){
		t.setEditable(false);
		setLayout(new FlowLayout());
		Border brd = BorderFactory.createMatteBorder(1, 1, 2, 2, Color.BLACK);
		lst.setBorder(brd);
		for(int i=0;i<4;i++)
			lItems.addElement(flavors[count++]);
		add(t);
		add(lst);
		add(b);
		lst.addListSelectionListener(ll);
		b.addActionListener(bl);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),250,375);
	}
}

20 页签面板 JTabbedPane

public class TwoTuple extends JFrame{
	private String[] flavors = {
			"Chocolate","Strawberry","Vanilla Fudge Swirl",
			"Mint Chip","Mocha Almond Fudge","Rum Raisin",
			"Praline Cream","Mud Pie"
	};
	private JTabbedPane tabs = new JTabbedPane();
	private JTextField txt = new JTextField(20);
	public TwoTuple(){
		int i=0;
		for(String flavor: flavors)
			tabs.addTab(flavors[i], new JButton("Tabbed pane "+i++));
		tabs.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent e) {
				// TODO Auto-generated method stub
				txt.setText("Tab selected: "+tabs.getSelectedIndex());
			}
		});
		add(BorderLayout.SOUTH,txt);
		add(tabs);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),400,250);
	}
}

21 消息框包含在JOptionPane

public class TwoTuple extends JFrame{
	private JButton[] b = {
		new JButton("Alert"),new JButton("Yes/No"),
		new JButton("Color"),new JButton("Input"),
		new JButton("3 Vals")
	};
	private JTextField txt = new JTextField(15);
	private ActionListener al = new ActionListener(){

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String id = ((JButton)e.getSource()).getText();
			if(id.equals("Alert"))
				JOptionPane.showMessageDialog(null, "There's a bug on you!","Hey!",JOptionPane.ERROR_MESSAGE);
			else if(id.equals("Yes/No"))
				JOptionPane.showConfirmDialog(null, "or no","choose yes",JOptionPane.YES_NO_OPTION);
			else if(id.equals("Color")){
				Object[] options = {"Red","Green"};
				int sel = JOptionPane.showOptionDialog(null, "Choose a Color!", "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null,options, options[0]);
				if(sel != JOptionPane.CLOSED_OPTION)
					txt.setText("Color Selected: "+options[sel]);
			}else if(id.equals("Input")){
				String val = JOptionPane.showInputDialog("How many fingers do you see?");
				txt.setText(val);
			}else if(id.equals("3 Vals")){
				Object[] selections = {"First","Second","Third"};
				Object val = JOptionPane.showInputDialog(null, "Choose one", "Input", JOptionPane.INFORMATION_MESSAGE, null, selections, selections[0]);
				if(val != null)
					txt.setText(val.toString());
			}
		}
	};
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public TwoTuple(){
		setLayout(new FlowLayout());
		for(int i=0;i<b.length;i++){
			b[i].addActionListener(al);
			add(b[i]);
		}
		add(txt);
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,200);
	}
}

22 菜单JMenuBar

public class TwoTuple extends JFrame{
	private JTextField t = new JTextField(15);
	private ActionListener al = new ActionListener(){

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			t.setText(((JMenuItem)e.getSource()).getText());
		}
	};
	private JMenu[] menus = {
			new JMenu("Winken"),new JMenu("Blinken"),
			new JMenu("Nod")
	};
	private JMenuItem[] items = {
		new JMenuItem("Fee"),new JMenuItem("Fi"),
		new JMenuItem("Fo"),new JMenuItem("Zip"),
		new JMenuItem("Zap"),new JMenuItem("Zot"),
		new JMenuItem("Olly"),new JMenuItem("Oxen"),
		new JMenuItem("Free")
	};
	public TwoTuple(){
		for(int i=0;i<items.length;i++){
			items[i].addActionListener(al);
			menus[i%3].add(items[i]);
		}
		JMenuBar mb = new JMenuBar();
		for(JMenu jm:menus)
			mb.add(jm);
		setJMenuBar(mb);
		setLayout(new FlowLayout());
		add(t);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}

	public static void main(String[] args){
		run(new TwoTuple(),200,150);
	}
}

23 弹出式菜单,要实现一个JPopupMenu,最直接的方法式创建一个继承自MouseAdapter的内部类

public class TwoTuple extends JFrame{
	private JPopupMenu popup = new JPopupMenu();
	private JTextField t = new JTextField(10);
	public TwoTuple(){
		setLayout(new FlowLayout());
		add(t);
		ActionListener al = new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				t.setText(((JMenuItem)e.getSource()).getText());
			}
		};
		JMenuItem m = new JMenuItem("Hither");
		m.addActionListener(al);
		popup.add(m);
		m = new JMenuItem("Yon");
		m.addActionListener(al);
		popup.add(m);
		m = new JMenuItem("Afar");
		m.addActionListener(al); 
		popup.add(m);
		popup.addSeparator();
		m = new JMenuItem("Stay Here");
		m.addActionListener(al);
		popup.add(m);
		PopupListener pl = new PopupListener();
		addMouseListener(pl);
		t.addMouseListener(pl);
	}
	class PopupListener extends MouseAdapter{

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			maybeShowPopup(e);
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			maybeShowPopup(e);
		}
		private void maybeShowPopup(MouseEvent e){
			if(e.isPopupTrigger())
				popup.show(e.getComponent(), e.getX(), e.getY());
		}
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}

	public static void main(String[] args){
		run(new TwoTuple(),300,200);
	}
}

24 绘图

class SineDraw extends JPanel{
	private static final int SCALEFACTOR = 200;
	private int cycles;
	private int points;
	private double[] sines;
	private int[] pts;
	public SineDraw(){ setCycles(5); }
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		int maxWidth = getWidth();
		double hstep = (double)maxWidth / (double)points;
		int maxHeight = getHeight();
		pts = new int[points];
		for(int i=0;i<points;i++)
			pts[i] = (int)(sines[i]*maxHeight/2*95+maxHeight/2);
		g.setColor(Color.RED);
		for(int i=1;i<points;i++){
			int x1 = (int)((i-1)*hstep);
			int x2 = (int)(i*hstep);
			int y1 = pts[i-1];
			int y2 = pts[i];
			g.drawLine(x1, y1, x2, y2);
		}
	}
	public void setCycles(int newCycles){
		cycles = newCycles;
		points = SCALEFACTOR*cycles*2;
		sines = new double[points];
		for(int i=0;i<points;i++){
			double radians = (Math.PI/SCALEFACTOR)*i;
			sines[i] = Math.sin(radians);
		}
		repaint();
	}
}
public class TwoTuple extends JFrame{
	private SineDraw sines = new SineDraw();
	private JSlider adjustCycles = new JSlider(1,30,5);
	public TwoTuple(){
		add(sines);
		adjustCycles.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent e) {
				// TODO Auto-generated method stub
				sines.setCycles(((JSlider)e.getSource()).getValue());
			}
		});
		add(BorderLayout.SOUTH,adjustCycles);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}

	public static void main(String[] args){
		run(new TwoTuple(),700,400);
	}
}

25 对话框JDialog

class MyDialog extends JDialog{
	public MyDialog(JFrame parent){
		super(parent,"My dialog",true);
		setLayout(new FlowLayout());
		add(new JLabel("Here is my dialog"));
		JButton ok = new JButton("OK");
		ok.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				dispose();
			}
		});
		add(ok);
		setSize(150,125);
	}
}
public class TwoTuple extends JFrame{
	private JButton b1 = new JButton("Dialog Box");
	private MyDialog dlg = new MyDialog(null);
	public TwoTuple(){
		b1.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				dlg.setVisible(true);
			}
		});
		add(b1);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}

	public static void main(String[] args){
		run(new TwoTuple(),125,75);
	}
}

26 文件对话框JFileChooser

public class TwoTuple extends JFrame{
	private JTextField fileName = new JTextField(),
			dir = new JTextField();
	private JButton open = new JButton("open"),
			save = new JButton("save");
	public TwoTuple(){
		JPanel p = new JPanel();
		open.addActionListener(new OpenL());
		p.add(open);
		save.addActionListener(new SaveL());
		p.add(save);
		add(p,BorderLayout.SOUTH);
		dir.setEditable(false);
		fileName.setEditable(false);
		p = new JPanel();
		p.setLayout(new GridLayout(2,1));
		p.add(fileName);
		p.add(save);
		add(p,BorderLayout.NORTH);
	}
	class OpenL implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			JFileChooser c = new JFileChooser();
			int rVal = c.showOpenDialog(TwoTuple.this);
			if(rVal == JFileChooser.APPROVE_OPTION){
				fileName.setText(c.getSelectedFile().getName());
				dir.setText(c.getCurrentDirectory().toString());
			}
			if(rVal == JFileChooser.CANCEL_OPTION){
				fileName.setText("You pressed cancel");
				dir.setText("");
			}
		}
	}
	class SaveL implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			JFileChooser c = new JFileChooser();
			int rVal = c.showSaveDialog(TwoTuple.this);
			if(rVal == JFileChooser.APPROVE_OPTION){
				fileName.setText(c.getSelectedFile().getName());
				dir.setText(c.getCurrentDirectory().toString());
			}
			if(rVal == JFileChooser.CANCEL_OPTION){
				fileName.setText("You pressed cancel");
				dir.setText("");
			}
		}
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}

	public static void main(String[] args){
		run(new TwoTuple(),250,150);
	}
}

27 Swing内任何能接受文本的组件都可以接受HTML文本,且能根据HTML的规则来重新格式化文本。

public class TwoTuple extends JFrame{
	private JButton b = new JButton(
			"<html><b><font size=+2><center>Hello!<br><i>Press me now!");
	public TwoTuple(){
		b.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				add(new JLabel("<html><i><font size=+4>Kapow!"));
				validate();
			}
		});
		setLayout(new FlowLayout());
		add(b);
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),200,500);
	}
}

28 滑块与进度条

public class TwoTuple extends JFrame{
	private JProgressBar pb = new JProgressBar();
	private ProgressMonitor pm = new ProgressMonitor(
			this,"Monitoring Progress","Test",0,100);
	private JSlider sb = new JSlider(JSlider.HORIZONTAL,0,100,60);
	public TwoTuple(){
		setLayout(new GridLayout(2,1));
		add(pb);
		pm.setProgress(0);
		pm.setMillisToPopup(1000);
		sb.setValue(0);
		sb.setPaintTicks(true);
		sb.setMajorTickSpacing(20);
		sb.setMinorTickSpacing(5);
		sb.setBorder(new TitledBorder("Slider Me"));
		pb.setModel(sb.getModel());
		add(sb);
		sb.addChangeListener(new ChangeListener(){
			@Override
			public void stateChanged(ChangeEvent e) {
				// TODO Auto-generated method stub
				pm.setProgress(sb.getValue());
			}
		});
	}
	public static void run(final JFrame f,final int width,final int height){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				f.setTitle(f.getClass().getSimpleName());
				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				f.setSize(width, height);
				f.setVisible(true);
			}		
		});
	}
	public static void main(String[] args){
		run(new TwoTuple(),300,200);
	}
}

 

29 Java网络发布协议(Java Network Launch Protocol,JNLP)

猜你喜欢

转载自blog.csdn.net/haima95/article/details/83006007