Java从入门到精通(12~21章)
2023-12-20 01:17:10 6 举报
AI智能生成
Java从入门到精通(12~21章)总结
作者其他创作
大纲/内容
集合类
官方说法将它看成一个容器,集合中的各个对象,很容易将其从集合中取出来,也很容易将其存放到集合中,还可以将其按照一定的顺序进行摆放
集合类概述
相比于数组,集合没有边界,且不会占用过多内存,拿服务器举例,一个用数组来存用户数据,当他的用户数量超过数组长度,数据将存储不下,这时需要停服维护,且你不知道下一次该把数组改多大,会有多少用户注册,另一个使用集合来存储用户数据,当用户量超过当前容量,集合会适当扩大容量,可以把它看作火车,车厢不够可以加,但数组不能,所以相比于数组,集合的用处和实用性都远高于数组
常用的集合类有List集合,Set集合和Map集合,其中List集合和Set集合继承了Collection接口,各接口提供了不同的实现类
下图是集合类的继承关系:
下图是集合类的继承关系:
Collection接口
Collection接口时层次结构中的接口,构成Collection的单位称为元素,它不能直接使用,但是提供了方法,例如添加元素,删除元素,管理元素。因为List接口和Set接口都继承了Collection接口,所以这些方法,List集合和Set集合都是通用的
下图是Collection接口的常用方法:
例题12.2
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Gather {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String>list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
int i=(int)(Math.random()*list.size());
System.out.println("随机获取集合中的元素:"+list.get(i));
list.remove(3);
System.out.println("将索引是'3'的元素从集合移除后,集合中的元素是:");
for(int j=0;j<list.size();j++) {
System.out.println(list.get(j));
for(String temp : list) {
System.out.println(temp);
}
System.out.println("Inerator迭代打印内容:");
Iterator<String> it =list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
import java.util.Iterator;
import java.util.List;
public class Gather {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String>list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
int i=(int)(Math.random()*list.size());
System.out.println("随机获取集合中的元素:"+list.get(i));
list.remove(3);
System.out.println("将索引是'3'的元素从集合移除后,集合中的元素是:");
for(int j=0;j<list.size();j++) {
System.out.println(list.get(j));
for(String temp : list) {
System.out.println(temp);
}
System.out.println("Inerator迭代打印内容:");
Iterator<String> it =list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
运行结果
List接口
List接口继承了Collection接口,因此包含Collection接口中的所以方法,此外,它还有两个非常重要的方法
1.get(int index):获取指定索引位置的元素
2.set(int index,Object obj):将集合中指定索引位置的对象修改为指定的对象
2.set(int index,Object obj):将集合中指定索引位置的对象修改为指定的对象
List接口的实现类
List接口的常用实现类有ArrayList类与LinkedList类
ArrayList类:实现了可变的数组,允许保存所有元素,包括null,并可根据索引位置对集合进行快速的随机访问。缺点就是向指定的u怂恿位置插入对象或删除对象的速度较慢。
LinkedList类:采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象。需要向集合中插入,删除对象时,使用LinkedList类实现的List集合的效率更高,但对于随机访问合集中的对象,使用LiknedList类实现List集合的效率较低。
LinkedList类:采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象。需要向集合中插入,删除对象时,使用LinkedList类实现的List集合的效率更高,但对于随机访问合集中的对象,使用LiknedList类实现List集合的效率较低。
实例化List集合的代码如下:
1.List<E> list = new ArrayList<>();
2.List<E> list2 = new LinkedList<>();
2.List<E> list2 = new LinkedList<>();
Set集合
Set接口常用的实现类有HshSet类与TreeSet类
HashSet类实现Set接口,由哈希表支持,他不保证Set集合的迭代顺序,特别是它不保证顺序恒久不变。此类允许使用null元素
TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序
TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序
例题12.3
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Set<Integer>set=new TreeSet<>();
set.add(-5);
set.add(-7);
set.add(10);
set.add(6);
set.add(3);
Iterator<Integer>it=set.iterator();
System.out.print("Set集合中的元素:");
while(it.hasNext()) {
System.out.print(it.next()+" ");
}
}
}
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Set<Integer>set=new TreeSet<>();
set.add(-5);
set.add(-7);
set.add(10);
set.add(6);
set.add(3);
Iterator<Integer>it=set.iterator();
System.out.print("Set集合中的元素:");
while(it.hasNext()) {
System.out.print(it.next()+" ");
}
}
}
运行结果
Map类
Map集合没有继承Collerction接口,,其提供的是key到value的映射。Map集合中不能包含相同的key,每个key只能映射一个value。
Map接口
Map接口提供了将key映射到值的对象。一个映射不能包含重复的key,每个key最多只能映射到一个值
Map接口的实现类
常用的接口有HashMap类和TreeMap类。
HashMap类:
是基于哈希表的Map接口,此实现提供所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。
TreeMap类:
不仅实现了Map接口,还实现了java,util.SortedMap接口,因此集合中的映射关系具有一定的顺序。但在添加,删除和定位映射关系时,TreeMap类比HashMap类性能稍差。
是基于哈希表的Map接口,此实现提供所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。
TreeMap类:
不仅实现了Map接口,还实现了java,util.SortedMap接口,因此集合中的映射关系具有一定的顺序。但在添加,删除和定位映射关系时,TreeMap类比HashMap类性能稍差。
例
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String,String>map=new HashMap<>();
map.put("ISBN-978654","JAVA从入门到精通");
map.put("ISBN-978361","Android从入门到精通");
map.put("ISBN-978893","21天学Android");
map.put("ISBN-978756","21天学JAVA");
Set<String>set=map.keySet();
Iterator<String>it=set.iterator();
System.out.println("key值:");
while (it.hasNext()) {
System.out.print(it.next()+" ");
}
Collection<String>coll=map.values();
it=coll.iterator();
System.out.println("\nvalue值:");
while(it.hasNext()) {
System.out.print(it.next()+" ");
}
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String,String>map=new HashMap<>();
map.put("ISBN-978654","JAVA从入门到精通");
map.put("ISBN-978361","Android从入门到精通");
map.put("ISBN-978893","21天学Android");
map.put("ISBN-978756","21天学JAVA");
Set<String>set=map.keySet();
Iterator<String>it=set.iterator();
System.out.println("key值:");
while (it.hasNext()) {
System.out.print(it.next()+" ");
}
Collection<String>coll=map.values();
it=coll.iterator();
System.out.println("\nvalue值:");
while(it.hasNext()) {
System.out.print(it.next()+" ");
}
}
}
运行结果:
枚举类型与泛型
Java中的枚举是一种特殊的类,它用于定义一组有限的常量。
枚举在Java中被视为数据类型,你可以使用它们来创建枚举类型的变量,然后使用那些变量等。
枚举类使用enum关键字进行定义。
枚举在Java中被视为数据类型,你可以使用它们来创建枚举类型的变量,然后使用那些变量等。
枚举类使用enum关键字进行定义。
例如:在这个例子中,我们定义了一个名为Day的枚举类,它包含了一周的七天作为常量。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
定义枚举类时,需要遵循以下规则:
1、枚举类中只能包含常量和方法,以及构造函数。
2、枚举常量必须是public static final类型,每个常量的名称必须唯一。
3、枚举类中可以定义构造函数和方法,但这些方法只能访问枚举常量和实例变量。
4、枚举常量按照它们的声明顺序在枚举类中进行排序。
5、枚举类不能继承其他类或实现接口。
6、枚举常量的名称必须是唯一的,不能重复。
7、枚举类的构造函数只能有一个,且必须为private类型。
8、枚举类中不能使用继承和多态等特性。
2、枚举常量必须是public static final类型,每个常量的名称必须唯一。
3、枚举类中可以定义构造函数和方法,但这些方法只能访问枚举常量和实例变量。
4、枚举常量按照它们的声明顺序在枚举类中进行排序。
5、枚举类不能继承其他类或实现接口。
6、枚举常量的名称必须是唯一的,不能重复。
7、枚举类的构造函数只能有一个,且必须为private类型。
8、枚举类中不能使用继承和多态等特性。
使用
枚举类型在实际中主要用于以下几个方面:
1、定义有限个特定的值:枚举可以用来定义一组有限的特定的值,例如一周的天数,或者颜色等。这些值在程序运行期间是不会改变的。
2、作为方法的参数:枚举可以作为方法的参数,这样可以让代码更加清晰,易于阅读和维护。例如,你可以定义一个枚举类型来表示不同的排序方式,然后在方法中使用这个枚举作为参数。
3、作为返回类型和参数类型:枚举可以作为方法的返回类型和参数类型。例如,你可以定义一个方法来获取一个枚举类型的列表,或者传递一个枚举类型的对象作为参数。
2、作为方法的参数:枚举可以作为方法的参数,这样可以让代码更加清晰,易于阅读和维护。例如,你可以定义一个枚举类型来表示不同的排序方式,然后在方法中使用这个枚举作为参数。
3、作为返回类型和参数类型:枚举可以作为方法的返回类型和参数类型。例如,你可以定义一个方法来获取一个枚举类型的列表,或者传递一个枚举类型的对象作为参数。
例如:在这个例子中,我们定义了一个枚举SortType来表示不同的排序方式。
这个枚举有两个值:ASC和DESC,分别表示升序和降序。我们还为每个值提供了一个字符串描述。
这个枚举有两个值:ASC和DESC,分别表示升序和降序。我们还为每个值提供了一个字符串描述。
public enum SortType {
ASC("升序"), DESC("降序");
private String value;
SortType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
ASC("升序"), DESC("降序");
private String value;
SortType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
然后我们可以像下面这样使用这个枚举:
SortType type = SortType.ASC; // 使用 SortType 作为变量类型
System.out.println(type.getValue()); // 输出 "升序"
System.out.println(type.getValue()); // 输出 "升序"
或者在方法中使用:
public void sortData(SortType type) {
// 根据 type 进行排序
// ...
}
// 调用方法时使用枚举作为参数
sortData(SortType.ASC);
// 根据 type 进行排序
// ...
}
// 调用方法时使用枚举作为参数
sortData(SortType.ASC);
优缺点
优点:
1、安全:使用枚举可以防止错误地使用无效的值。如果一个方法只接受有限个特定的值作为参数,那么使用枚举可以确保传入的参数是有效的。如果试图传入一个无效的值,编译器将会报错。
2、可读性和可维护性:使用枚举可以使代码更加清晰和易于阅读。每个枚举值都可以有一个有意义的名称,而不是一个难以理解的数字或者字符串。同时,如果需要添加新的枚举值,只需要在枚举类中添加新的实例,而不需要修改现有的代码。
3、性能:使用枚举可以提高性能。因为枚举值是静态的,所以它们可以在编译期间被解析和优化。相比之下,如果使用一个字符串或者整数来表示相同的信息,那么这些值需要在运行时解析和比较。
2、可读性和可维护性:使用枚举可以使代码更加清晰和易于阅读。每个枚举值都可以有一个有意义的名称,而不是一个难以理解的数字或者字符串。同时,如果需要添加新的枚举值,只需要在枚举类中添加新的实例,而不需要修改现有的代码。
3、性能:使用枚举可以提高性能。因为枚举值是静态的,所以它们可以在编译期间被解析和优化。相比之下,如果使用一个字符串或者整数来表示相同的信息,那么这些值需要在运行时解析和比较。
缺点:
1、占用空间:每个枚举值都会在内存中占用一定的空间。虽然这可能不会对单个程序造成太大的影响,但是如果在一个大型的项目中使用大量的枚举值,那么这可能会成为一个问题。
2、可能产生过度设计:如果过度使用枚举,可能会导致代码变得过于复杂和难以维护。例如,如果在一个方法中使用一个包含大量枚举值的列表,那么这可能会使代码变得难以理解和维护。
2、可能产生过度设计:如果过度使用枚举,可能会导致代码变得过于复杂和难以维护。例如,如果在一个方法中使用一个包含大量枚举值的列表,那么这可能会使代码变得难以理解和维护。
方法
枚举类存在的方法,具体详见JavaApi文档1.8
Iambda表达式与流处理
lambda表达式
在Java中,Lambda表达式是一种函数式编程的特性,它允许以简洁的语法编写函数或操作,而无需显式创建匿名类。Lambda表达式在Java 8中引入,是使Java更适应现代编程风格和需求的重要工具。lambda表达式可以代替简单的匿名内部类的实现。
lambda表达式的一个重要作用就是能够简写代码。
需要注意的是,lambda表达式只适用于函数式接口,也就是接口内只定义了一个方法的接口。
如果一个接口是函数式接口一般会使用 @FunctionalInterface 来表示。
lambda表达式的一个重要作用就是能够简写代码。
需要注意的是,lambda表达式只适用于函数式接口,也就是接口内只定义了一个方法的接口。
如果一个接口是函数式接口一般会使用 @FunctionalInterface 来表示。
例如:forEach遍历中的接口就是一个函数式接口。
lambda表达式语法
(parameters) -> { statements; }
parameters:这是Lambda表达式的参数列表。参数类型是可选的,也可以直接推断。例如,a -> a + 1 和 (int a) -> a + 1 是等效的。
->:这是Lambda操作符,将参数列表和Lambda体分开。
expression:这是Lambda体的单个表达式。如果Lambda体包含多个语句,则它们必须被大括号 {} 包围。
->:这是Lambda操作符,将参数列表和Lambda体分开。
expression:这是Lambda体的单个表达式。如果Lambda体包含多个语句,则它们必须被大括号 {} 包围。
需要了解的是在实现 lambd表达式时可以按规则来简写lambda表达式:
在小括号()内,如果只有一个形参,或者形象类型只有一种,那么形参类型可以省略
在大括号内{},如果只有一条语句,那么 大括号可以省略、return可以省略、分号也可以省略。
在大括号内{},如果只有一条语句,那么 大括号可以省略、return可以省略、分号也可以省略。
以下通过具体案例来说明这个简写规则。
首先先定义一个set集合,我们都知道set集合是无索引的,那么set集合常规的遍历方式只有迭代器遍历与forEach遍历。
首先先定义一个set集合,我们都知道set集合是无索引的,那么set集合常规的遍历方式只有迭代器遍历与forEach遍历。
Set<String> s=new HashSet<>();
// set集合:无序、不重复、无索引
s.add("张三");
s.add("李四");
s.add("王五");
// set集合:无序、不重复、无索引
s.add("张三");
s.add("李四");
s.add("王五");
1、迭代器遍历
// 迭代器方式遍历set集合
// 创建迭代器
Iterator<String> it = s.iterator();
// 判断当前迭代器指针是否指向最后一个位置
while(it.hasNext()){
// 返回迭代器指针当前指向的元素,并且移动迭代器指针
String str = it.next();
System.out.println(str);
}
// 创建迭代器
Iterator<String> it = s.iterator();
// 判断当前迭代器指针是否指向最后一个位置
while(it.hasNext()){
// 返回迭代器指针当前指向的元素,并且移动迭代器指针
String str = it.next();
System.out.println(str);
}
2、forEach遍历
// foreach循环遍历set集合
for(String i : s){
System.out.println(i);
}
for(String i : s){
System.out.println(i);
}
以上两种遍历方式都能实现遍历set集合的要求,但是代码还是不够简洁,以下我们来通过从匿名内部类到lambda表达式的改进。
匿名内部类
//完整版
s.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
s.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
lambda表达式
s.forEach((String i) -> {
System.out.println(i);
});
System.out.println(i);
});
根据简化规则的lambda表达式
s.forEach((o1) -> System.out.println(o1) ); //极简版
方法引用
在Java中,方法引用是一种简化Lambda表达式的方式,它允许你直接引用现有的方法,而不是重新定义一个Lambda表达式。
方法引用在Java 8中引入,它是一种非常方便的语法糖,可以使代码更加简洁、易读。
常用的方法引用分为引用静态方法、引用成员方法等。
方法引用在Java 8中引入,它是一种非常方便的语法糖,可以使代码更加简洁、易读。
常用的方法引用分为引用静态方法、引用成员方法等。
1、引用静态方法
语法:类名 :: 静态方法名,这里出现的新操作符 :: 这是英文状态的冒号组成的。
需要注意的是这个语法中方法名是没有圆括号的。
需要注意的是这个语法中方法名是没有圆括号的。
例如:
List<String> list = Arrays.asList("A", "B", "C");
list.forEach(System.out::println);
list.forEach(System.out::println);
在上面的例子中,System.out::println 是一个方法引用。它引用了 System.out 类的静态方法 println。这个方法接受一个参数(在这个例子中是 String 类型),并打印这个参数。
引用静态方法规则:
1、方法名和参数:在引用静态方法时,你需要提供方法的名称以及所需要的任何参数。例如,如果你有一个名为greet的静态方法,它需要一个字符串和一个整数作为参数,你可以这样引用它:ClassName.greet(参数1, 参数2)。
2、作用域:你可以在任何地方引用静态方法,包括在类的内部,其他类的内部,或者作为表达式的一部分。
3、访问权限:如果静态方法是私有的,那么你不能从类的外部访问它。如果它是受保护的,那么你可以从同一个包中的类或者其他包中的子类访问它。如果它是默认的(即没有修饰符),那么你可以从同一个包中的类访问它。
4、重载:你可以在一个类中拥有多个同名的静态方法,只要他们的参数列表不同(即形成了重载)。在引用时,Java会根据你提供的参数类型和数量来确定应该调用哪个方法。
5、泛型:虽然静态方法可以使用泛型,但是他们在引用时并不需要提供具体的类型参数。例如,如果你有一个名为calculate的静态方法,它需要一个List作为参数,你可以这样调用它:ClassName.calculate(myList),而不必提供类型参数。
6、访问静态方法的方式:你可以通过类名来访问静态方法,或者通过实例来访问(虽然这有些混淆,因为通常我们通过实例来调用实例方法,而不是静态方法)。例如,ClassName.methodName()或者instanceName.methodName()。
7、链式调用:如果一个静态方法的返回值是返回类型的实例,那么我们可以连续地调用这个实例的方法。例如,如果add方法返回一个Calculator实例,并且这个实例有一个calculate方法,那么我们可以这样使用:ClassName.add(1, 2).calculate()。
2、作用域:你可以在任何地方引用静态方法,包括在类的内部,其他类的内部,或者作为表达式的一部分。
3、访问权限:如果静态方法是私有的,那么你不能从类的外部访问它。如果它是受保护的,那么你可以从同一个包中的类或者其他包中的子类访问它。如果它是默认的(即没有修饰符),那么你可以从同一个包中的类访问它。
4、重载:你可以在一个类中拥有多个同名的静态方法,只要他们的参数列表不同(即形成了重载)。在引用时,Java会根据你提供的参数类型和数量来确定应该调用哪个方法。
5、泛型:虽然静态方法可以使用泛型,但是他们在引用时并不需要提供具体的类型参数。例如,如果你有一个名为calculate的静态方法,它需要一个List作为参数,你可以这样调用它:ClassName.calculate(myList),而不必提供类型参数。
6、访问静态方法的方式:你可以通过类名来访问静态方法,或者通过实例来访问(虽然这有些混淆,因为通常我们通过实例来调用实例方法,而不是静态方法)。例如,ClassName.methodName()或者instanceName.methodName()。
7、链式调用:如果一个静态方法的返回值是返回类型的实例,那么我们可以连续地调用这个实例的方法。例如,如果add方法返回一个Calculator实例,并且这个实例有一个calculate方法,那么我们可以这样使用:ClassName.add(1, 2).calculate()。
2、引用成员方法
引用对象的方法是指通过对象来引用其成员方法。
方法引用的语法格式为:object::methodName,其中object为对象实例,methodName为对象所属类中的成员方法名。
方法引用的语法格式为:object::methodName,其中object为对象实例,methodName为对象所属类中的成员方法名。
例如:
class Animal {
String name;
void makeSound() {
System.out.println("The animal makes a sound");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.name = "Cat";
// 引用对象方法
MethodReferenceDemo demo = new MethodReferenceDemo();
demo.printAnimalInfo(animal::makeSound, animal);
}
}
String name;
void makeSound() {
System.out.println("The animal makes a sound");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.name = "Cat";
// 引用对象方法
MethodReferenceDemo demo = new MethodReferenceDemo();
demo.printAnimalInfo(animal::makeSound, animal);
}
}
在这个示例中,我们定义了一个Animal类,并在Main类中创建了一个Animal对象。我们使用animal::makeSound方法引用了Animal对象的makeSound方法。在printAnimalInfo方法中,我们使用Lambda表达式来处理被引用的方法,同时将Animal对象作为参数传递给该方法。
请注意,这里的MethodReferenceDemo和printAnimalInfo方法需要根据你的实际需求进行相应的实现。
Stream流
Java中的Stream流是一种新的特性,它提供了一种处理集合和数组的方式,可以极大地方便我们对集合、数组等数据源进行连续操作。Stream流可以让我们以一种更加简洁、高效、可读性更强的方式来处理数据。
Stream流的操作可以分为中间操作和终止操作两种类型。中间操作返回的是一个新的Stream流,而终止操作返回的是一个非Stream类型的结果。
在Stream流的处理过程中,数据是惰性求值的,只有在执行终止操作时才会开始处理数据。这种处理方式可以减少计算量和开销,提高效率。
创建Stream流可以从很多种数据源中创建,例如List、Set或者任何其他实现了Iterable接口的类。创建方式很简单,使用stream()或parallelStream()方法即可。总的来说,Stream流是一种方便、简洁且高效的数据处理方式,它可以使代码更加简洁易懂,提高代码的可读性和可维护性。
Stream流的操作可以分为中间操作和终止操作两种类型。中间操作返回的是一个新的Stream流,而终止操作返回的是一个非Stream类型的结果。
在Stream流的处理过程中,数据是惰性求值的,只有在执行终止操作时才会开始处理数据。这种处理方式可以减少计算量和开销,提高效率。
创建Stream流可以从很多种数据源中创建,例如List、Set或者任何其他实现了Iterable接口的类。创建方式很简单,使用stream()或parallelStream()方法即可。总的来说,Stream流是一种方便、简洁且高效的数据处理方式,它可以使代码更加简洁易懂,提高代码的可读性和可维护性。
常用的中间操作方法
/*
filter:为过滤方法,方法中形参为lambda表达式或实现类
stream流只能使用一次,建议使用链式编程
修改流中的数据,不会改变原数组或集合的值,类似于拷贝了一份进行操作而已
limit:获取stream流中前几个元素,形参为个数
skip:跳过stream流中形参个元素。
distinct:去重方法,当stream对象为自定义方法时,那么需要重写hashcode与equals方法
concat:合并两个stream流
map:转换流中数据类型
*/
filter:为过滤方法,方法中形参为lambda表达式或实现类
stream流只能使用一次,建议使用链式编程
修改流中的数据,不会改变原数组或集合的值,类似于拷贝了一份进行操作而已
limit:获取stream流中前几个元素,形参为个数
skip:跳过stream流中形参个元素。
distinct:去重方法,当stream对象为自定义方法时,那么需要重写hashcode与equals方法
concat:合并两个stream流
map:转换流中数据类型
*/
常用的终止方法
/*
总结方法:
froEach方法,遍历
count:统计
toArray:将流中数据转换为指定类型数组进行返回。
collect:将流中数据收集进一个集合进行返回
*/
总结方法:
froEach方法,遍历
count:统计
toArray:将流中数据转换为指定类型数组进行返回。
collect:将流中数据收集进一个集合进行返回
*/
需要注意的是,在进行流处理的时候,中间方法与终止方法的区别在于中间方法会返回一个新的stream流,可以需要调用,而终止方法返回的是一个非stream流的结果。所以stream一般适合链式调用。
示例1:
使用stream流将List集合中的数据添加到map集合中,姓名做键,年龄做值。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class 方法 {
public static void main(String[] args) {
/*
总结方法:
froEach方法,遍历
count:统计
toArray:将流中数据转换为指定类型数组进行返回。
collect:将流中数据收集进一个集合进行返回
*/
List<String> list=new ArrayList<>();
Collections.addAll(list,"张无忌-男-18","wuhu-男-20","呀呼-女-20");
// 匿名内部类实现stream流
Map<String, String> user = list.stream().collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
}
, new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[2];
}
}
)
);
// lambda实现stream流
Map<String, String> user2 = list.stream().collect(Collectors.toMap(o1 -> o1.split("-")[0], o2 -> o2.split("-")[2]));
user.forEach((o1,o2) -> System.out.println(o1+","+o2));
System.out.println(user2);
}
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class 方法 {
public static void main(String[] args) {
/*
总结方法:
froEach方法,遍历
count:统计
toArray:将流中数据转换为指定类型数组进行返回。
collect:将流中数据收集进一个集合进行返回
*/
List<String> list=new ArrayList<>();
Collections.addAll(list,"张无忌-男-18","wuhu-男-20","呀呼-女-20");
// 匿名内部类实现stream流
Map<String, String> user = list.stream().collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
}
, new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[2];
}
}
)
);
// lambda实现stream流
Map<String, String> user2 = list.stream().collect(Collectors.toMap(o1 -> o1.split("-")[0], o2 -> o2.split("-")[2]));
user.forEach((o1,o2) -> System.out.println(o1+","+o2));
System.out.println(user2);
}
}
结果:
以上方法都是使用到了流处理的中间方法与终结方法。
I/O(输入/输出)
绪论
首先如果我们在Java编写的一个程序中获得了想要的某种结果,那么在程序结束后,这个结果还存在嘛?不存在的,因为在Java程序运行时,程序会被加载到内存中在内存中运行,但是,在程序结束后虚拟机会自动释放内存空间,中间程序得到得结果也会消失,但是我们如果想保存这个结果呢?之前因为我们学习过使用JDBC技术链接数据库,这也能达到目的,但是对于某些长文本数据存储到数据库中就有些不便,那么这次我们学习Java的io技术可以将程序结果存储到本地的文件中,随取随存。
输入流
Java中的输入流是一种用于从外部设备读取数据的机制。它提供了一组类和接口,用于从不同的数据源读取数据,如文件、网络连接、控制台等。
Java中的输入流主要分为以下几种类型:
Java中的输入流主要分为以下几种类型:
1、字节流(Byte Stream):以字节为单位进行读写操作的流。常见的字节流类包括InputStream和OutputStream。
2、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Reader和Writer。
3、缓冲流(Buffered Stream):缓冲流可以提高读写效率,减少对外部设备的访问次数。常见的缓冲流类包括BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter。
4、数据流(Data Stream):数据流用于读写基本数据类型,如int、float、double等。常见的数据流类包括DataInputStream和DataOutputStream。
5、转换流(Conversion Stream):转换流可以将一种类型的流转换为另一种类型的流,例如InputStreamReader可以将字节流转换为字符流。
2、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Reader和Writer。
3、缓冲流(Buffered Stream):缓冲流可以提高读写效率,减少对外部设备的访问次数。常见的缓冲流类包括BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter。
4、数据流(Data Stream):数据流用于读写基本数据类型,如int、float、double等。常见的数据流类包括DataInputStream和DataOutputStream。
5、转换流(Conversion Stream):转换流可以将一种类型的流转换为另一种类型的流,例如InputStreamReader可以将字节流转换为字符流。
常规常见输入流步骤:
1、创建输入流对象:根据需要创建相应的输入流对象,例如使用FileInputStream类创建字节流对象读取文件,使用BufferedReader类创建字符流对象读取文本文件。
2、打开连接:打开与外部设备的连接,例如使用open()方法打开文件。
3、读取数据:通过输入流对象读取数据。在读取数据时,可以使用输入流提供的方法逐个读取字节或字符,也可以使用输入流的读取方法一次读取多个字节或字符。
4、关闭连接:关闭与外部设备的连接,例如使用close()方法关闭文件。
2、打开连接:打开与外部设备的连接,例如使用open()方法打开文件。
3、读取数据:通过输入流对象读取数据。在读取数据时,可以使用输入流提供的方法逐个读取字节或字符,也可以使用输入流的读取方法一次读取多个字节或字符。
4、关闭连接:关闭与外部设备的连接,例如使用close()方法关闭文件。
输出流
Java中的输出流是一种用于将数据写入到外部设备的机制。它提供了一组类和接口,用于将数据从Java程序输出到不同的目标,如文件、网络连接、控制台等。
Java中的输出流主要分为以下几种类型:
1、字节流(Byte Stream):以字节为单位进行读写操作的流。常见的字节流类包括OutputStream和Writer。
2、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
3、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
4、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
5、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
2、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
3、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
4、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
5、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
使用输出流进行数据写入的一般步骤如下:
1、创建输出流对象:根据需要创建相应的输出流对象,例如使用FileOutputStream类创建字节流对象写入文件,使用PrintWriter类创建字符流对象写入文本文件。
2、创建输出流对象:根据需要创建相应的输出流对象,例如使用FileOutputStream类创建字节流对象写入文件,使用PrintWriter类创建字符流对象写入文本文件。
3、写入数据:通过输出流对象将数据写入到外部设备。在写入数据时,可以使用输出流提供的方法逐个写入字节或字符,也可以使用输出流的写入方法一次写入多个字节或字符。
4、关闭连接:关闭与外部设备的连接,例如使用close()方法关闭文件。
2、创建输出流对象:根据需要创建相应的输出流对象,例如使用FileOutputStream类创建字节流对象写入文件,使用PrintWriter类创建字符流对象写入文本文件。
3、写入数据:通过输出流对象将数据写入到外部设备。在写入数据时,可以使用输出流提供的方法逐个写入字节或字符,也可以使用输出流的写入方法一次写入多个字节或字符。
4、关闭连接:关闭与外部设备的连接,例如使用close()方法关闭文件。
需要注意的是:
在使用输入输出流进行数据读取时,应该遵循“打开-使用-关闭”的原则,及时关闭连接以释放资源。同时,应该根据实际需求选择合适的流类,以达到最佳的读写效果。
File类
Java中的File类是用于文件和目录操作的类。它提供了一种在Java程序中创建、读取、写入和删除文件的方式。
File类主要用于对文件增删查的操作,没有用于对文件内部数据的读写功能。
File类主要用于对文件增删查的操作,没有用于对文件内部数据的读写功能。
File类的主要功能包括:
1、创建文件或目录:可以使用File类的构造函数创建一个新的文件或目录。例如,File file = new File(“path/to/file.txt”)将创建一个名为file.txt的文件。如果文件已经存在,则不会创建新文件。
2、判断文件或目录是否存在:可以使用File类的exists()方法来判断文件或目录是否存在。如果文件或目录存在,则返回true,否则返回false。
3、获取文件或目录的属性:可以使用File类的各种方法获取文件或目录的属性,如文件名、文件大小、文件创建时间等。例如,getName()方法返回文件或目录的名称,length()方法返回文件的大小(以字节为单位),lastModified()方法返回文件最后修改的时间。
4、删除文件或目录:可以使用File类的delete()方法删除文件或目录。如果删除成功,则返回true,否则返回false。需要注意的是,如果文件或目录不存在,或者由于其他原因无法删除,则删除操作可能会失败。
5、获取文件或目录的路径:可以使用File类的getAbsolutePath()方法获取文件或目录的绝对路径。该路径是一个字符串,表示文件或目录在文件系统中的位置。
6、获取文件或目录的路径:可以使用File类的getAbsolutePath()方法获取文件或目录的绝对路径。该路径是一个字符串,表示文件或目录在文件系统中的位置。
7、获取文件或目录的名称:可以使用File类的getName()方法获取文件或目录的名称。例如,如果文件位于C:\Users\username\Documents\file.txt,则文件名将是file.txt。
8、创建文件夹:可以使用 mkdir() 或 mkdirs() 方法创建文件夹。 mkdir() 只创建最后一个不存在的父目录,而 mkdirs() 会创建所有不存在的父目录。
9、判断是否是文件:可以使用 isFile() 方法判断路径是否对应一个普通文件。如果是,返回 true;否则返回 false。
10、判断是否是目录:可以使用 isDirectory() 方法判断路径是否对应一个目录。如果是,返回 true;否则返回 false。
11、其他操作:File类还提供了一些其他的方法,如listFiles()方法返回一个包含指定目录下所有文件的数组,list()方法返回一个包含指定目录下所有文件和子目录的字符串数组等。
2、判断文件或目录是否存在:可以使用File类的exists()方法来判断文件或目录是否存在。如果文件或目录存在,则返回true,否则返回false。
3、获取文件或目录的属性:可以使用File类的各种方法获取文件或目录的属性,如文件名、文件大小、文件创建时间等。例如,getName()方法返回文件或目录的名称,length()方法返回文件的大小(以字节为单位),lastModified()方法返回文件最后修改的时间。
4、删除文件或目录:可以使用File类的delete()方法删除文件或目录。如果删除成功,则返回true,否则返回false。需要注意的是,如果文件或目录不存在,或者由于其他原因无法删除,则删除操作可能会失败。
5、获取文件或目录的路径:可以使用File类的getAbsolutePath()方法获取文件或目录的绝对路径。该路径是一个字符串,表示文件或目录在文件系统中的位置。
6、获取文件或目录的路径:可以使用File类的getAbsolutePath()方法获取文件或目录的绝对路径。该路径是一个字符串,表示文件或目录在文件系统中的位置。
7、获取文件或目录的名称:可以使用File类的getName()方法获取文件或目录的名称。例如,如果文件位于C:\Users\username\Documents\file.txt,则文件名将是file.txt。
8、创建文件夹:可以使用 mkdir() 或 mkdirs() 方法创建文件夹。 mkdir() 只创建最后一个不存在的父目录,而 mkdirs() 会创建所有不存在的父目录。
9、判断是否是文件:可以使用 isFile() 方法判断路径是否对应一个普通文件。如果是,返回 true;否则返回 false。
10、判断是否是目录:可以使用 isDirectory() 方法判断路径是否对应一个目录。如果是,返回 true;否则返回 false。
11、其他操作:File类还提供了一些其他的方法,如listFiles()方法返回一个包含指定目录下所有文件的数组,list()方法返回一个包含指定目录下所有文件和子目录的字符串数组等。
示例:输出某一文件夹中所有的文件信息(包括子文件夹):
需要注意的是,如果某个文件夹需要权限才能访问,那么使用File类的listFiles方法返回的是null,为了代码不出现错误,我们需要对此进行判断。
public static void main(String[] args) {
out_data(new File("E:\\简历"));
}
public static void out_data(File f){
//获取文件名或文件夹名
System.out.println("--------------"+f.getName()+"------------------");
File[] files = f.listFiles();
if(files == null) { return; }
for(File ft : files){
// 判断是否文件夹,是则继续往下递归
if(ft.isDirectory()) { out_data(ft); }
// 不是文件夹,则输出信息
else{ System.out.println(ft.getName()); }
}
System.out.println("--------------"+f.getName()+"------------------");
}
out_data(new File("E:\\简历"));
}
public static void out_data(File f){
//获取文件名或文件夹名
System.out.println("--------------"+f.getName()+"------------------");
File[] files = f.listFiles();
if(files == null) { return; }
for(File ft : files){
// 判断是否文件夹,是则继续往下递归
if(ft.isDirectory()) { out_data(ft); }
// 不是文件夹,则输出信息
else{ System.out.println(ft.getName()); }
}
System.out.println("--------------"+f.getName()+"------------------");
}
运行结果
文件输入 / 输出流
Java中的文件输入输出流是用于读取和写入文件的类。Java提供了两种类型的文件输入输出流:字节输入输出流和字符输入输出流。
二者的区别在于,字节流是以字节为单位进行读取,随读随取,可以读取除文本外任意文件;字符流也是以字节进行读取,但是不同点在于它遇到中文时会按中文的编码方式进行读取,而带有缓冲区机制。
二者的区别在于,字节流是以字节为单位进行读取,随读随取,可以读取除文本外任意文件;字符流也是以字节进行读取,但是不同点在于它遇到中文时会按中文的编码方式进行读取,而带有缓冲区机制。
字节输入输出流
字节输入输出流以字节为单位进行读写操作。Java中提供了以下几种字节输入输出流类:
1、FileInputStream:用于从文件中读取字节数据。
2、FileOutputStream:用于向文件中写入字节数据。
3、BufferedInputStream:用于从文件中读取数据,并将数据缓存在内存中,以提高读取效率。
4、BufferedOutputStream:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
5、DataInputStream:用于从文件中读取基本数据类型,如int、float、double等。
6、DataOutputStream:用于向文件中写入基本数据类型,如int、float、double等。
2、FileOutputStream:用于向文件中写入字节数据。
3、BufferedInputStream:用于从文件中读取数据,并将数据缓存在内存中,以提高读取效率。
4、BufferedOutputStream:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
5、DataInputStream:用于从文件中读取基本数据类型,如int、float、double等。
6、DataOutputStream:用于向文件中写入基本数据类型,如int、float、double等。
使用字节输入输出流进行文件读写的一般步骤如下:
1、创建输入输出流对象:使用上述类之一的构造函数创建输入输出流对象。例如,使用FileInputStream类创建文件输入流对象,使用FileOutputStream类创建文件输出流对象。
2、打开连接:使用open()方法打开文件,建立与文件的连接。
3、读取/写入数据:使用输入输出流提供的方法读取或写入数据。例如,使用read()方法从输入流中读取字节数据,使用write()方法向输出流中写入字节数据。
4、关闭连接:使用close()方法关闭文件,断开与文件的连接。
2、打开连接:使用open()方法打开文件,建立与文件的连接。
3、读取/写入数据:使用输入输出流提供的方法读取或写入数据。例如,使用read()方法从输入流中读取字节数据,使用write()方法向输出流中写入字节数据。
4、关闭连接:使用close()方法关闭文件,断开与文件的连接。
示例:读取文件
import java.io.FileInputStream;
import java.io.IOException;
public class FileReadingExample {
public static void main(String[] args) {
try (FileInputStream fileInputStream = new FileInputStream("path/to/file.txt")) {
int data;
while ((data = fileInputStream.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
public class FileReadingExample {
public static void main(String[] args) {
try (FileInputStream fileInputStream = new FileInputStream("path/to/file.txt")) {
int data;
while ((data = fileInputStream.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例:写入文件
import java.io.FileOutputStream;
import java.io.IOException;
public class FileWritingExample {
public static void main(String[] args) {
try (FileOutputStream fileOutputStream = new FileOutputStream("path/to/file.txt")) {
String data = "Hello, World!";
fileOutputStream.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
public class FileWritingExample {
public static void main(String[] args) {
try (FileOutputStream fileOutputStream = new FileOutputStream("path/to/file.txt")) {
String data = "Hello, World!";
fileOutputStream.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符输入输出流
字符输入输出流以字符为单位进行读写操作。
Java中提供了以下几种字符输入输出流类:
FileReader:用于从文件中读取字符数据。
FileWriter:用于向文件中写入字符数据。
BufferedReader:用于从文件中读取数据,并将数据缓存在内存中,以提高读取效率。
BufferedWriter:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
BufferedWriter:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
FileWriter:用于向文件中写入字符数据。
BufferedReader:用于从文件中读取数据,并将数据缓存在内存中,以提高读取效率。
BufferedWriter:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
BufferedWriter:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
使用字符输入输出流进行文件读写的一般步骤如下:
1、创建输入输出流对象:使用上述类之一的构造函数创建输入输出流对象。例如,使用FileReader类创建文件输入流对象,使用FileWriter类创建文件输出流对象。
2、打开连接:使用open()方法打开文件,建立与文件的连接。
3、读取/写入数据:使用输入输出流提供的方法读取或写入数据。例如,使用read()方法从输入流中读取字符数据,使用write()方法向输出流中写入字符数据。
4、关闭连接:使用close()方法关闭文件,断开与文件的连接。
2、打开连接:使用open()方法打开文件,建立与文件的连接。
3、读取/写入数据:使用输入输出流提供的方法读取或写入数据。例如,使用read()方法从输入流中读取字符数据,使用write()方法向输出流中写入字符数据。
4、关闭连接:使用close()方法关闭文件,断开与文件的连接。
示例:读取文件
import java.io.FileReader;
import java.io.IOException;
public class FileReadingExample {
public static void main(String[] args) {
try (FileReader fileReader = new FileReader("path/to/file.txt")) {
int data;
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
public class FileReadingExample {
public static void main(String[] args) {
try (FileReader fileReader = new FileReader("path/to/file.txt")) {
int data;
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例:写入文件
import java.io.FileWriter;
import java.io.IOException;
public class FileWritingExample {
public static void main(String[] args) {
try (FileWriter fileWriter = new FileWriter("path/to/file.txt")) {
String data = "Hello, World!";
fileWriter.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
public class FileWritingExample {
public static void main(String[] args) {
try (FileWriter fileWriter = new FileWriter("path/to/file.txt")) {
String data = "Hello, World!";
fileWriter.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
需要注意的是,在进行io读取操作时,应该遵循“打开-使用-关闭”的原则,及时关闭连接以释放资源。同时,应该根据实际需求选择合适的流类,以达到最佳的读写效果。
反射与注解
反射
反射,从字面意思的理解就是反过来映射,它的功能也是如此,一般我们要在程序的运行过程中获取一个类的内部信息,那么得先生成一个这个类的对象,然后再使用这个类对外提供的方法来获取,这个类对外提供了什么样方法我们就只能获得到什么信息。
在程序的过程中我们无法像直接翻看源代码一样查看到某个类的信息,但是通过反射机制,能让我们在程序运行阶段就能直接获取某个类中的所有信息,就算这个类的信息有些不对外开发,但是我们依然能获取到。
class类
class类是一个特殊的类,Class类表示正在运行的Java应用程序中的类和接口。
一个类在被JVM加载后,会在内存中生成对应Class对象,而我们可以通过获取对应类的Class对象,来获取这个类的信息。
一个类在被JVM加载后,会在内存中生成对应Class对象,而我们可以通过获取对应类的Class对象,来获取这个类的信息。
获取方式
Class类对象只有三种可以获取方式,因为Class中的构造方法被private修饰了,所以我们无法通过构造方法来创建Class类的对象。
1、Class.forName(“全类名”)
通过这个静态方法我们可以获取某个类的Class对象,全类名指的是这个类在什么位置。
例如:创建test包下的student类的Class对象。
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException {
Class claz = Class.forName("test.student");
}
}
public static void main(String[] args) throws ClassNotFoundException {
Class claz = Class.forName("test.student");
}
}
2、类名.class
Class studentClass = student.class;
3、对象.getClass()
Object类是所有类的父类,在Object类中有一个方法:getClass方法,这个方法可以获取一个对应的Class对象。所以我们可以使用这个方法获取。
常用功能
Class类提供了很多的方法供我们使用,总得来说常用功能可以分为三大类:
访问构造方法
访问成员变量
访问成员方法
访问成员变量
访问成员方法
针对不同的需求可以使用不同的方法。
1、访问构造方法
获取构造方法的常用方法
1、Constructor[] getConstructors():获取所有公共(public)构造方法。
2、Constructor[] getDeclaredConstructors():获取所有声明的构造方法,包括公共和非公共的。
3、Constructor getConstructor(Class<?>… parameterTypes):获取具有指定参数类型的公共构造方法。
4、Constructor getDeclaredConstructor(Class<?>… parameterTypes):获取具有指定参数类型的声明的构造方法,包括公共和非公共的。
2、Constructor[] getDeclaredConstructors():获取所有声明的构造方法,包括公共和非公共的。
3、Constructor getConstructor(Class<?>… parameterTypes):获取具有指定参数类型的公共构造方法。
4、Constructor getDeclaredConstructor(Class<?>… parameterTypes):获取具有指定参数类型的声明的构造方法,包括公共和非公共的。
需要注意的是,如果获取指定的构造方法,那么需要根据该构造方法来进行传参。
示例
首先创建一个student进行示例说明,该类中拥有两个属性与多个构造方法,分别使用不同的权限修饰符进行修饰。
public final class student {
public String name;
public int age;
public student(){}
private student(String name){
this.name=name;
}
protected student(int age){
this.age=age;
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
}
public String name;
public int age;
public student(){}
private student(String name){
this.name=name;
}
protected student(int age){
this.age=age;
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
}
然后我们使用不同的获取方法进行获取这个类的构造方法。
package test;
import java.lang.reflect.Constructor;
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class claz = Class.forName("test.student"); //获取Class对象
Constructor con = claz.getConstructor(); //获取单个的公共构造方法
Constructor[] cons = claz.getConstructors(); // 获取所有公共的构造方法
Constructor[] pcons = claz.getDeclaredConstructors(); //获取所有的构造方法
Constructor targteCon = claz.getDeclaredConstructor(String.class); // 获取指定形参的构造方法
System.out.println("单个的公共构造方法:");
System.out.println(con);
System.out.println("----------------------------------------");
System.out.println("所有公共的构造方法:");
for (Constructor constructor : cons) {
System.out.println(constructor);
}
System.out.println("----------------------------------------");
System.out.println("获取所有的构造方法");
for (Constructor pcon : pcons) {
System.out.println(pcon);
}
System.out.println("----------------------------------------");
System.out.println("获取指定的构造方法");
System.out.println(targteCon);
}
}
import java.lang.reflect.Constructor;
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class claz = Class.forName("test.student"); //获取Class对象
Constructor con = claz.getConstructor(); //获取单个的公共构造方法
Constructor[] cons = claz.getConstructors(); // 获取所有公共的构造方法
Constructor[] pcons = claz.getDeclaredConstructors(); //获取所有的构造方法
Constructor targteCon = claz.getDeclaredConstructor(String.class); // 获取指定形参的构造方法
System.out.println("单个的公共构造方法:");
System.out.println(con);
System.out.println("----------------------------------------");
System.out.println("所有公共的构造方法:");
for (Constructor constructor : cons) {
System.out.println(constructor);
}
System.out.println("----------------------------------------");
System.out.println("获取所有的构造方法");
for (Constructor pcon : pcons) {
System.out.println(pcon);
}
System.out.println("----------------------------------------");
System.out.println("获取指定的构造方法");
System.out.println(targteCon);
}
}
结果
2、访问成员变量
访问成员变量是使用Field类来进行的。
获取成员变量的常用方法:
Field getField(Object obj):获取指定对象的成员变量。
Field[] getFields():获取该类的所有公共(public)成员变量。
Field[] getDeclaredFields():获取该类的所有成员变量,包括公共和非公共的。
Field getDeclaredField(String name):获取具有指定名称的成员变量,包括公共和非公共的。
Field[] getFields():获取该类的所有公共(public)成员变量。
Field[] getDeclaredFields():获取该类的所有成员变量,包括公共和非公共的。
Field getDeclaredField(String name):获取具有指定名称的成员变量,包括公共和非公共的。
FIeld类中常用方法
对获取出来的成员变量进行操作的话,需要使用Field类,以下是常用的方法,具体详见Java1.8api文档。
对获取出来的成员变量进行操作的话,需要使用Field类,以下是常用的方法,具体详见Java1.8api文档。
示例
首先创建一个studen类用于演示
package test;
public final class student {
private String name;
public int age;
public student(){}
private student(String name){
this.name=name;
}
protected student(int age){
this.age=age;
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
}
public final class student {
private String name;
public int age;
public student(){}
private student(String name){
this.name=name;
}
protected student(int age){
this.age=age;
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
}
获取成员变量
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
Class claz = Class.forName("test.student"); //获取Class对象
Field age = claz.getField("age"); //获取指定变量名的公共成员变量
Field[] fields = claz.getFields(); //获取所有公共的成员变量
Field name = claz.getDeclaredField("name");//获取指定变量的成员变量(可获取被private修饰的)
Field[] pfields = claz.getDeclaredFields(); // 获取所有的成员变量
// 下列仅获取成员变量名
System.out.println("获取指定成员变量");
System.out.println(age.getName());
System.out.println("-----------------------------");
System.out.println("获取所有公共的成员变量");
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("-----------------------------");
System.out.println("获取指定的成员变量(可获取私有的)");
System.out.println(name.getName());
System.out.println("-----------------------------");
System.out.println("获取所有的成员变量");
for (Field pfield : pfields) {
System.out.println(pfield.getName());
}
System.out.println("-----------------------------");
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
Class claz = Class.forName("test.student"); //获取Class对象
Field age = claz.getField("age"); //获取指定变量名的公共成员变量
Field[] fields = claz.getFields(); //获取所有公共的成员变量
Field name = claz.getDeclaredField("name");//获取指定变量的成员变量(可获取被private修饰的)
Field[] pfields = claz.getDeclaredFields(); // 获取所有的成员变量
// 下列仅获取成员变量名
System.out.println("获取指定成员变量");
System.out.println(age.getName());
System.out.println("-----------------------------");
System.out.println("获取所有公共的成员变量");
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("-----------------------------");
System.out.println("获取指定的成员变量(可获取私有的)");
System.out.println(name.getName());
System.out.println("-----------------------------");
System.out.println("获取所有的成员变量");
for (Field pfield : pfields) {
System.out.println(pfield.getName());
}
System.out.println("-----------------------------");
}
}
运行结果
3、访问成员方法
访问某个类的成员方法是使用Method对象来进行操作的。
常用的方法有下图所示,具体详见Java1.8Api文档
获取Method对象常用的方法有:
Method[] getMethods():获取所有公共(public)成员方法,包括从Object类继承的方法。
Method[] getDeclaredMethods():获取所有声明的成员方法,不包括从父类继承的方法。
Method getMethod(String name, Class<?>… parameterTypes):获取具有指定名称和参数类型的公共成员方法。
Method getDeclaredMethod(String name, Class<?>… parameterTypes):获取具有指定名称和参数类型的声明的成员方法。
Method[] getDeclaredMethods():获取所有声明的成员方法,不包括从父类继承的方法。
Method getMethod(String name, Class<?>… parameterTypes):获取具有指定名称和参数类型的公共成员方法。
Method getDeclaredMethod(String name, Class<?>… parameterTypes):获取具有指定名称和参数类型的声明的成员方法。
示例:
给student类创建几个成员方法用于演示。
package test;
public final class student {
private String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public student(){}
private student(String name){
this.name=name;
}
protected student(int age){
this.age=age;
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
private void show(){
System.out.println("芜湖");
}
}
public final class student {
private String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public student(){}
private student(String name){
this.name=name;
}
protected student(int age){
this.age=age;
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
private void show(){
System.out.println("芜湖");
}
}
获取成员方法
需要注意的是,如果使用getMethods方法来获取成员方法,那么它会返回本类的公共成员方法,也会返回从父类继承的成员方法。而使用getDeclaredMethods方法来获取的话,那么就不会返回父类的方法。
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
Class claz=Class.forName("test.student");
Method[] ms = claz.getMethods(); //获取所有公共的成员方法(包括从父类继承的方法)
Method getAge = claz.getMethod("getAge"); // 获取指定名称与形参的公共方法,无形参则省略
Method[] pms = claz.getDeclaredMethods(); //获取所有成员方法,不包括从父类继承的方法
Method show = claz.getDeclaredMethod("show"); // 获取指定名称与形参的方法(包括私有化的)
System.out.println("取所有公共的成员方法(包括从父类继承的方法)");
for (Method m : ms) {
System.out.println(m); // 获取方法名称
}
System.out.println("------------------------------------------------");
System.out.println("获取指定名称与形参的公共方法,无形参则省略");
System.out.println(getAge);
System.out.println("------------------------------------------------");
System.out.println("获取所有的成员方法,不包括从父类继承的");
for (Method pm : pms) {
System.out.println(pm);
}
System.out.println("------------------------------------------------");
System.out.println("获取指定名称与形参的方法(包括私有化的)");
System.out.println(show);
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class demo_1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
Class claz=Class.forName("test.student");
Method[] ms = claz.getMethods(); //获取所有公共的成员方法(包括从父类继承的方法)
Method getAge = claz.getMethod("getAge"); // 获取指定名称与形参的公共方法,无形参则省略
Method[] pms = claz.getDeclaredMethods(); //获取所有成员方法,不包括从父类继承的方法
Method show = claz.getDeclaredMethod("show"); // 获取指定名称与形参的方法(包括私有化的)
System.out.println("取所有公共的成员方法(包括从父类继承的方法)");
for (Method m : ms) {
System.out.println(m); // 获取方法名称
}
System.out.println("------------------------------------------------");
System.out.println("获取指定名称与形参的公共方法,无形参则省略");
System.out.println(getAge);
System.out.println("------------------------------------------------");
System.out.println("获取所有的成员方法,不包括从父类继承的");
for (Method pm : pms) {
System.out.println(pm);
}
System.out.println("------------------------------------------------");
System.out.println("获取指定名称与形参的方法(包括私有化的)");
System.out.println(show);
}
}
执行结果
注解
在Java中,注解(Annotation)是一种特殊的注释,它提供了一种元数据机制,可以用于描述代码中的信息和元数据。注解是Java 5.0引入的一个新特性,它提供了一种将信息嵌入到Java代码中的方法,并且可以在编译时、运行时和代码生成时使用。
注解的作用域可以是类、方法、变量、参数等。例如,可以使用注解标记类、方法、变量等。
注解可以具有参数,参数可以是常量、字符串、整数等类型。例如:
@MyAnnotation(name="example", value=123)。
注解可以被继承,子类可以继承父类中的注解。
语法:
注解的基本语法很简单,它使用 @符号来标识,后面跟着注解的名称和参数。例如:
@Override // 这是一个注解,表示覆盖从父类继承的方法
public void myMethod() {
// method body
}
public void myMethod() {
// method body
}
用处:
提供文档信息:注解可以用于描述代码中的方法和变量,提供可读性更好的文档信息。
跟踪代码依赖性:注解可以用于标记代码中的依赖关系,方便跟踪和管理代码的依赖性。
实现AOP(面向切面编程):通过注解定义切面行为,实现非侵入式增强。
替代配置文件:注解可以用于简化配置和注入依赖关系的管理,减少配置文件的数量。
编译时检查:某些注解可以用于检查代码中的格式或参数,例如@Override注解用于检查方法是否覆盖了超类方法。
跟踪代码依赖性:注解可以用于标记代码中的依赖关系,方便跟踪和管理代码的依赖性。
实现AOP(面向切面编程):通过注解定义切面行为,实现非侵入式增强。
替代配置文件:注解可以用于简化配置和注入依赖关系的管理,减少配置文件的数量。
编译时检查:某些注解可以用于检查代码中的格式或参数,例如@Override注解用于检查方法是否覆盖了超类方法。
注解的分类:
1、预定义注解:包括常见的注解,如@Override、@Deprecated和@SuppressWarning等。这些注解通常用于标记代码中的特定元素,以便编译器在编译时进行警告或错误检查。
2、元注解:元注解是用于注解其他注解的注解,包括@Target、@Retention和@Inherited等。这些注解主要用于定义注解的元数据,例如注解的应用范围、注解的生命周期以及注解的继承方式等。
3、自定义注解:用户可以根据自己的需求定义注解。自定义注解可以根据需要添加参数和属性,以便更灵活地描述代码中的信息。
2、元注解:元注解是用于注解其他注解的注解,包括@Target、@Retention和@Inherited等。这些注解主要用于定义注解的元数据,例如注解的应用范围、注解的生命周期以及注解的继承方式等。
3、自定义注解:用户可以根据自己的需求定义注解。自定义注解可以根据需要添加参数和属性,以便更灵活地描述代码中的信息。
合理的使用注解可以在编译时进行检查,确保代码符合特定的规范或要求。但是同样注解也会增加代码的复杂度,使代码难以理解。注解有好处也有坏处,因此需要合理的使用注解。
目前来看反射貌似没什么作用,但是在后序的学习中,反射还是很重要的,需要掌握好这个机制。
数据库操作
前言
本文主要讲述的是如何使用JDBC技术连接本地的数据库,编写Java语言代码来对本地的MySQL数据库进行基础的增删改查操作,所以阅读本文章之前还得对数据库的操作有基本的了解,望周知。
JDBC技术
JDBC(Java Database Connectivity)是Java中用于连接和执行SQL语句来与数据库进行交互的一种技术。 JDBC API包含了多种接口和类,允许Java程序与数据库进行通信。
使用JDBC技术连接MySQL数据库的步骤:
1、导入JDBC包
你需要将MySQL的JDBC驱动包含在你的项目中。一般来说,这可以通过将相关的jar文件添加到项目的类路径中来完成。这个jar文件通常被称为mysql-connector-java-version-bin.jar,其中“version”是你的JDBC驱动的版本号。
在你的Java代码中,你需要在文件的顶部导入相关的包。这些包包括java.sql包和MySQL的JDBC驱动包。
import java.sql.*;
import com.mysql.jdbc.*;
import com.mysql.jdbc.*;
2、建立连接
接下来,你需要创建一个连接到你的MySQL数据库的连接对象。这需要你的数据库的URL,用户名和密码。下面是一个例子:
String url = "jdbc:mysql://localhost:3306/mydatabase";
String user = "root";
String password = "mypassword";
Connection conn = DriverManager.getConnection(url, user, password);
String user = "root";
String password = "mypassword";
Connection conn = DriverManager.getConnection(url, user, password);
在上面的例子中,“localhost:3306”是你的MySQL服务器的地址和端口(通常为3306),“mydatabase”是你的数据库名,“root”和“mypassword”是你的用户名和密码。
3、创建语句和执行查询
一但设置了连接对象,你就可以创建一个Statement对象,然后使用它来执行SQL查询
例如:
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");
ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");
在上面这个例子中,“mytable”是你的表名。执行查询后,你将得到一个ResultSet对象,你可以使用它来获取查询的结果。
4、处理结果和清理资源
在执行查询后,你需要处理查询的结果,并且清理你的资源。下面是一个例子:
while(rs.next()) {
String column1 = rs.getString("column1");
int column2 = rs.getInt("column2");
//...处理结果...
}
rs.close(); // 关闭ResultSet
stmt.close(); // 关闭Statement
conn.close(); // 关闭Connection
String column1 = rs.getString("column1");
int column2 = rs.getInt("column2");
//...处理结果...
}
rs.close(); // 关闭ResultSet
stmt.close(); // 关闭Statement
conn.close(); // 关闭Connection
在这个例子中,你需要替换"column1"和"column2"等为你的列的名字。在处理完结果后,你需要关闭ResultSet、Statement和Connection对象。这可以确保你的资源被正确地清理,防止内存泄漏和其他问题。
JDBC中常用的类和接口
1、DriverManager类:用于加载和管理JDBC驱动程序。DriverManager类提供了一个静态方法getConnection(),它返回一个Connection对象,该对象表示与数据库的连接。
2、Connection接口:代表与数据库的连接。Connection接口提供了一些方法来创建Statement、PreparedStatement和CallableStatement等对象,用于执行SQL语句和存储过程等。
3、Statement接口:用于执行静态SQL语句并返回ResultSet对象。可以使用Statement接口的executeQuery()方法执行查询,返回ResultSet对象表示查询结果集;使用executeUpdate()方法执行更新操作,返回一个int值表示受影响的行数。
4、PreparedStatement接口:用于执行动态SQL语句。PreparedStatement接口继承了Statement接口,并提供了额外的setXXX()方法来设置SQL语句中的参数。使用PreparedStatement接口可以提高性能和安全性。
5、ResultSet接口:用于获取查询结果集中的数据。ResultSet接口提供了一些方法来获取列值、列名等。
6、CallableStatement接口:用于调用存储过程。CallableStatement接口继承了PreparedStatement接口,并提供了一些方法来设置存储过程的参数和获取返回值。
7、Driver接口:JDBC驱动程序必须实现的接口。Driver接口定义了一些标准方法,如connect()、getMajorVersion()和getMinorVersion()等,用于与DriverManager进行通信。
8、SQLException异常类:在JDBC操作中可能会抛出SQLException异常类,表示发生了某种数据库访问错误。
2、Connection接口:代表与数据库的连接。Connection接口提供了一些方法来创建Statement、PreparedStatement和CallableStatement等对象,用于执行SQL语句和存储过程等。
3、Statement接口:用于执行静态SQL语句并返回ResultSet对象。可以使用Statement接口的executeQuery()方法执行查询,返回ResultSet对象表示查询结果集;使用executeUpdate()方法执行更新操作,返回一个int值表示受影响的行数。
4、PreparedStatement接口:用于执行动态SQL语句。PreparedStatement接口继承了Statement接口,并提供了额外的setXXX()方法来设置SQL语句中的参数。使用PreparedStatement接口可以提高性能和安全性。
5、ResultSet接口:用于获取查询结果集中的数据。ResultSet接口提供了一些方法来获取列值、列名等。
6、CallableStatement接口:用于调用存储过程。CallableStatement接口继承了PreparedStatement接口,并提供了一些方法来设置存储过程的参数和获取返回值。
7、Driver接口:JDBC驱动程序必须实现的接口。Driver接口定义了一些标准方法,如connect()、getMajorVersion()和getMinorVersion()等,用于与DriverManager进行通信。
8、SQLException异常类:在JDBC操作中可能会抛出SQLException异常类,表示发生了某种数据库访问错误。
数据库操作
1.连接数据库:
String driver="com.mysql.cj.jdbc.Driver"; // 驱动类Driver在jar包中位置
String url="jdbc:mysql://localhost:3306/需要连接的数据库名";
/*
* 它的值是"jdbc:mysql://localhost:3306/javasql",
这通常是一个连接到MySQL数据库的JDBC(Java Database Connectivity)URL。
这个URL指定了如何连接到位于本地主机(localhost)的MySQL数据库服务器(端口号为3306),
以及要连接到的数据库名称为'javasql'。
* */
String user="数据库用户名"; // 用户名
String password="数据库密码"; // 登录密码
try {
Class.forName(driver); // 加载连接对象
Connection conn = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
// 加载失败
throw new RuntimeException(e);
} catch (SQLException e) {
// 连接失败
throw new RuntimeException(e);
}
String url="jdbc:mysql://localhost:3306/需要连接的数据库名";
/*
* 它的值是"jdbc:mysql://localhost:3306/javasql",
这通常是一个连接到MySQL数据库的JDBC(Java Database Connectivity)URL。
这个URL指定了如何连接到位于本地主机(localhost)的MySQL数据库服务器(端口号为3306),
以及要连接到的数据库名称为'javasql'。
* */
String user="数据库用户名"; // 用户名
String password="数据库密码"; // 登录密码
try {
Class.forName(driver); // 加载连接对象
Connection conn = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
// 加载失败
throw new RuntimeException(e);
} catch (SQLException e) {
// 连接失败
throw new RuntimeException(e);
}
查询操作
下面这个例子中代码会连接到一个名为"testDB"的MySQL数据库,并从"Users"表中查询所有的记录。查询的结果会显示每条记录的"name"和"email"字段。
import java.sql.*;
public class Main {
public static void main(String[] args) {
// 创建连接
String url = "jdbc:mysql://localhost:3306/testDB";
String username = "root";
String password = "password";
Connection conn = null;
Statement stmt = null;
try {
conn = DriverManager.getConnection(url, username, password);
stmt = conn.createStatement();
// 执行查询
String sql = "SELECT * FROM Users"; // Users是表的名称
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
// 通过列名获取相应的值
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println("Name: " + name + ", Email: " + email);
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(stmt != null) stmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
// 创建连接
String url = "jdbc:mysql://localhost:3306/testDB";
String username = "root";
String password = "password";
Connection conn = null;
Statement stmt = null;
try {
conn = DriverManager.getConnection(url, username, password);
stmt = conn.createStatement();
// 执行查询
String sql = "SELECT * FROM Users"; // Users是表的名称
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
// 通过列名获取相应的值
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println("Name: " + name + ", Email: " + email);
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(stmt != null) stmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
增、删、改操作
对于插入、更新和删除操作(增删改操作),我们首先需要创建一个PreparedStatement对象,然后设置SQL语句中的参数,并使用executeUpdate()方法执行这个语句。且增删改操作的不同点在于使用不同的SQL语句来创建PreparedStatement对象,其余并无差距,这里就只举例新增操作。
import java.sql.*;
public class Main {
public static void main(String[] args) {
// ...(省略连接部分的代码)
try {
// 创建一个PreparedStatement对象
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO Users (name, email) VALUES (?, ?)");
// 设置参数
pstmt.setString(1, "New User");
pstmt.setString(2, "newuser@email.com");
// 执行更新操作
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
// ...(省略连接部分的代码)
try {
// 创建一个PreparedStatement对象
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO Users (name, email) VALUES (?, ?)");
// 设置参数
pstmt.setString(1, "New User");
pstmt.setString(2, "newuser@email.com");
// 执行更新操作
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
上面代码将创建一个新的用户记录。
注意,"?"符号在SQL语句中代表一个通配符,我们在set()方法中为这些参数设置值,通配符顺序从1开始计算,且代表不同参数的通配符需要使用不同的set方法来设置值。
执行executeUpdate()方法会将这条SQL语句发送到数据库,创建一个新的用户记录。
注意,"?"符号在SQL语句中代表一个通配符,我们在set()方法中为这些参数设置值,通配符顺序从1开始计算,且代表不同参数的通配符需要使用不同的set方法来设置值。
执行executeUpdate()方法会将这条SQL语句发送到数据库,创建一个新的用户记录。
Swing程序设计
Swing概述
Swing是Java平台的一部分,它是一个用于开发Java应用程序用户界面的开发工具包。
Swing的主要目的是提供一个跨平台的用户界面工具包,让开发人员能够轻松地创建具有丰富用户界面的应用程序,并且这些应用程序可以在不同的操作系统上运行。Swing是基于Java AWT(抽象窗口工具包)构建的,通过提供一组跨平台的GUI组件和布局管理器来解决AWT主要问题的不跨平台。
Swing开发人员只用很少的代码就可以利用Swing丰富、灵活的功能和模块化组件来创建优雅的用户界面。
Swing常用窗体
Swing是Java的一个图形用户界面(GUI)工具包,它提供了创建窗口、对话框、按钮等图形元素所需要的类。
以下时Swing中的常用窗体简介:
1、JFrame:这是Swing中一个顶层窗口容器,可以用来创建窗口、对话框等。它包含了窗口的一些基本属性,如标题、大小、位置等。
2、JDialog:这是Swing中的一个对话框容器,通常用于在用户需要输入一些信息或者做出一些选择时弹出。它也包含了对话框的一些属性,如标题、内容、大小等。
3、JWindow:这是Swing中的一个无标题的顶级窗口容器,通常用于创建一些不需要标题的窗口。
4、JInternalFrame:这是Swing中的一个内部窗口容器,通常用于在桌面应用程序中创建多个窗口,这些窗口可以像浏览器标签一样堆叠在一起。
5、JFrame.JContentPane:这是Swing中的一个内容面板,它可以将组件放置在其上,并且可以包含滚动条、边框等。它通常用于创建一些需要放置多个组件的窗口。
6、JScrollPane:这是Swing中的一个滚动面板,它可以包含另一个面板或者组件,并且可以在需要时显示滚动条。它通常用于创建一些需要显示大量内容的窗口。
2、JDialog:这是Swing中的一个对话框容器,通常用于在用户需要输入一些信息或者做出一些选择时弹出。它也包含了对话框的一些属性,如标题、内容、大小等。
3、JWindow:这是Swing中的一个无标题的顶级窗口容器,通常用于创建一些不需要标题的窗口。
4、JInternalFrame:这是Swing中的一个内部窗口容器,通常用于在桌面应用程序中创建多个窗口,这些窗口可以像浏览器标签一样堆叠在一起。
5、JFrame.JContentPane:这是Swing中的一个内容面板,它可以将组件放置在其上,并且可以包含滚动条、边框等。它通常用于创建一些需要放置多个组件的窗口。
6、JScrollPane:这是Swing中的一个滚动面板,它可以包含另一个面板或者组件,并且可以在需要时显示滚动条。它通常用于创建一些需要显示大量内容的窗口。
1、JFrame窗体
JFrame是Java Swing库中的一个顶层窗口容器,它提供了创建窗口的基本功能,是Swing应用程序中创建窗口的基类。
JFrame具有以下特点:
1、JFrame是一个顶级窗口,必须添加内容才能显示窗口。
2、JFrame可以添加各种组件,如按钮、文本框、标签等。
3、JFrame具有默认的关闭操作,可以关闭窗口。
4、JFrame可以设置窗口大小、标题等属性。
2、JFrame可以添加各种组件,如按钮、文本框、标签等。
3、JFrame具有默认的关闭操作,可以关闭窗口。
4、JFrame可以设置窗口大小、标题等属性。
JFrame的主要方法包括:
1、setTitle(String title):设置窗口标题。
2、setDefaultCloseOperation(int operation):设置窗口关闭操作,例如JFrame.EXIT_ON_CLOSE(关闭时退出程序)、JFrame.DISPOSE_ON_CLOSE(关闭时结束程序并释放窗口)等。
3、setBounds(int x, int y, int width, int height):设置窗口大小和位置。
4、add(Component component):添加组件到窗口中。
5、remove(Component component):从窗口中移除组件。
6、setLayout(LayoutManager manager):设置窗口的布局管理器。
7、getContentPane():获取内容窗格。
8、getRootPane():获取根窗格。
9、getWindowDecorationStyle():获取窗口装饰样式。
10、setWindowDecorationStyle(int style):设置窗口装饰样式。
2、setDefaultCloseOperation(int operation):设置窗口关闭操作,例如JFrame.EXIT_ON_CLOSE(关闭时退出程序)、JFrame.DISPOSE_ON_CLOSE(关闭时结束程序并释放窗口)等。
3、setBounds(int x, int y, int width, int height):设置窗口大小和位置。
4、add(Component component):添加组件到窗口中。
5、remove(Component component):从窗口中移除组件。
6、setLayout(LayoutManager manager):设置窗口的布局管理器。
7、getContentPane():获取内容窗格。
8、getRootPane():获取根窗格。
9、getWindowDecorationStyle():获取窗口装饰样式。
10、setWindowDecorationStyle(int style):设置窗口装饰样式。
示例
public class Main {
public static void main(String[] args) {
JFrame jf = new JFrame("第一个窗体");
jf.setSize(500,500); // 设置大小
jf.setAlwaysOnTop(true); // 顶层显示方法
jf.setLocationRelativeTo(null); // 将窗口位置设置为屏幕中心
jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE); //设置关闭模式,关闭模式设置为关闭窗体时释放窗体资源并结束程序
jf.setVisible(true); //设置为显示
}
}
public static void main(String[] args) {
JFrame jf = new JFrame("第一个窗体");
jf.setSize(500,500); // 设置大小
jf.setAlwaysOnTop(true); // 顶层显示方法
jf.setLocationRelativeTo(null); // 将窗口位置设置为屏幕中心
jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE); //设置关闭模式,关闭模式设置为关闭窗体时释放窗体资源并结束程序
jf.setVisible(true); //设置为显示
}
}
2、JDialog对话框
JDialog是Java Swing库中的一个对话框窗体,它继承了AWT组件中的java.awt.Dialog类。JDialog窗体的功能是从一个窗体中弹出另一个窗体,类似于在使用IE浏览器时弹出的确定对话框。
JDialog窗体与JFrame窗体类似,它们都是顶层窗口容器,但是JDialog窗体通常用于创建模态对话框,可以与用户进行交互并获取用户输入。
JDialog窗体具有以下特点:
1、可以创建模式对话框和非模式对话框。模式对话框会阻塞用户对其他窗口的访问,直到用户关闭该对话框或通过操作按钮取消对话框。非模式对话框不会阻塞用户对其他窗口的访问。
2、可以添加各种组件,如按钮、文本框、标签等。
3、可以设置对话框的标题、大小、位置等属性。
4、对话框默认情况下没有关闭操作,需要手动添加关闭操作。
2、可以添加各种组件,如按钮、文本框、标签等。
3、可以设置对话框的标题、大小、位置等属性。
4、对话框默认情况下没有关闭操作,需要手动添加关闭操作。
JDialog的主要方法包括:
1、setTitle(String title):设置对话框标题。
2、setModal(boolean modal):设置对话框是否为模式对话框。
3、setBounds(int x, int y, int width, int height):设置对话框大小和位置。
4、add(Component component):添加组件到对话框中。
5、remove(Component component):从对话框中移除组件
6、setLayout(LayoutManager manager):设置对话框的布局管理器。
7、getContentPane():获取内容窗格。
8、getRootPane():获取根窗格。
9、getWindowDecorationStyle():获取窗口装饰样式。
10、setWindowDecorationStyle(int style):设置窗口装饰样式。
2、setModal(boolean modal):设置对话框是否为模式对话框。
3、setBounds(int x, int y, int width, int height):设置对话框大小和位置。
4、add(Component component):添加组件到对话框中。
5、remove(Component component):从对话框中移除组件
6、setLayout(LayoutManager manager):设置对话框的布局管理器。
7、getContentPane():获取内容窗格。
8、getRootPane():获取根窗格。
9、getWindowDecorationStyle():获取窗口装饰样式。
10、setWindowDecorationStyle(int style):设置窗口装饰样式。
示例
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DialogExample {
private JFrame frame;
private JButton button;
private JDialog dialog;
private JTextField textField;
public DialogExample() {
// 创建主窗口
frame = new JFrame("Dialog Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭模式
frame.setSize(300, 200); // 设置大小
frame.setLayout(new BorderLayout());
// 创建按钮并添加到主窗口中
button = new JButton("Show Dialog");
frame.add(button, BorderLayout.NORTH);
// 创建对话框
dialog = new JDialog();
dialog.setTitle("Input Dialog");
dialog.setModal(true); // 设置为模式对话框
dialog.setSize(300, 200);
dialog.setLayout(new BorderLayout());
// 创建文本框并添加到对话框中
textField = new JTextField(20);
dialog.add(textField, BorderLayout.CENTER);
// 显示主窗口
frame.setVisible(true);
}
public static void main(String[] args) {
// 创建示例对象
DialogExample example = new DialogExample();
}
}
import java.awt.*;
import java.awt.event.*;
public class DialogExample {
private JFrame frame;
private JButton button;
private JDialog dialog;
private JTextField textField;
public DialogExample() {
// 创建主窗口
frame = new JFrame("Dialog Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭模式
frame.setSize(300, 200); // 设置大小
frame.setLayout(new BorderLayout());
// 创建按钮并添加到主窗口中
button = new JButton("Show Dialog");
frame.add(button, BorderLayout.NORTH);
// 创建对话框
dialog = new JDialog();
dialog.setTitle("Input Dialog");
dialog.setModal(true); // 设置为模式对话框
dialog.setSize(300, 200);
dialog.setLayout(new BorderLayout());
// 创建文本框并添加到对话框中
textField = new JTextField(20);
dialog.add(textField, BorderLayout.CENTER);
// 显示主窗口
frame.setVisible(true);
}
public static void main(String[] args) {
// 创建示例对象
DialogExample example = new DialogExample();
}
}
在以上示例中,我们创建了一个主窗口(JFrame),并在其中添加了一个按钮(JButton)。当用户点击按钮时,会弹出一个模态对话框(JDialog),其中包含一个文本框(JTextField)。用户可以在文本框中输入内容,然后关闭对话框。在关闭对话框后,用户可以继续操作主窗口。
3、JOptionPane小型对话框
JOptionPane是Java Swing库中的一个用于显示对话框的类。它提供了一些方便的方法来创建各种类型的对话框,例如确认对话框、输入对话框、消息对话框等。
JOptionPane的主要方法包括:
1、showMessageDialog(Component parentComponent, String message):显示一个包含指定消息的对话框。
2、showInputDialog(Component parentComponent, String prompt, String title, int messageType):显示一个包含输入框的对话框,用于获取用户输入。
3、showConfirmDialog(Component parentComponent, String message, String title, int optionType):显示一个确认对话框,用于让用户选择是否继续操作。
2、showInputDialog(Component parentComponent, String prompt, String title, int messageType):显示一个包含输入框的对话框,用于获取用户输入。
3、showConfirmDialog(Component parentComponent, String message, String title, int optionType):显示一个确认对话框,用于让用户选择是否继续操作。
示例:
import javax.swing.*;
import java.awt.*;
public class OptionPaneExample {
public static void main(String[] args) {
// 创建JFrame窗口
JFrame frame = new JFrame("OptionPane Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setLayout(new BorderLayout());
// 添加按钮并添加事件监听器
JButton button = new JButton("Show Message Dialog");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 显示消息对话框
JOptionPane.showMessageDialog(frame, "Hello World!");
}
});
frame.add(button, BorderLayout.NORTH);
// 显示窗口
frame.setVisible(true);
}
}
import java.awt.*;
public class OptionPaneExample {
public static void main(String[] args) {
// 创建JFrame窗口
JFrame frame = new JFrame("OptionPane Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setLayout(new BorderLayout());
// 添加按钮并添加事件监听器
JButton button = new JButton("Show Message Dialog");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 显示消息对话框
JOptionPane.showMessageDialog(frame, "Hello World!");
}
});
frame.add(button, BorderLayout.NORTH);
// 显示窗口
frame.setVisible(true);
}
}
在以上示例中,我们创建了一个JFrame窗口,并在其中添加了一个按钮。当用户点击按钮时,会弹出一个包含"Hello World!"消息的消息对话框。
常用布局管理器
在Java的Swing库中,布局管理器是一种用于自动调整组件位置和大小的机制。它们使得开发人员可以创建复杂的用户界面,而无需手动计算每个组件的位置和大小。
以下是Java中常用的几种布局管理器:
1、BorderLayout:这是默认的布局管理器,它将容器分为5个区域:北(NORTH)、南(SOUTH)、东(EAST)、西(WEST)和中(CENTER。你可以将组件添加到这些区域中。注意,每个区域只能包含一个组件。
2、FlowLayout:此布局管理器将组件按照水平或垂直方向排列。如果容器宽度或高度不足以容纳所有的组件,那么会换行或换列。
3、GridLayout:此布局管理器将容器分为行和列,形成网格。你可以指定行数和列数,然后添加组件到网格的特定位置。
4、CardLayout:此布局管理器用于显示一个组件集合中的某一个组件。当用户切换卡时,显示不同的组件。例如,你可以使用它来在多个用户界面之间切
5、GridBagLayout:这是一个更复杂的布局管理器,允许组件占据多个行或列的空间。你可以设置组件的位置、大小、填充方式、对齐方式等。
6、BoxLayout:此布局管理器将组件在一行或一列中布局,可以指定组件的对齐方式。
7、SpringLayout:此布局管理器允许组件在网格中的位置和大小由周围的组件决定,就像弹簧一样。通常与其他布局管理器(如GridLayout)结合使用。
8、BorderLayoutManager:这是Java 11中新增的布局管理器,它实现了BorderLayout,但添加了一些额外的功能。例如,它可以处理组件的溢出,当组件的大小超过其容器的大小时,会显示一个滚动条。
2、FlowLayout:此布局管理器将组件按照水平或垂直方向排列。如果容器宽度或高度不足以容纳所有的组件,那么会换行或换列。
3、GridLayout:此布局管理器将容器分为行和列,形成网格。你可以指定行数和列数,然后添加组件到网格的特定位置。
4、CardLayout:此布局管理器用于显示一个组件集合中的某一个组件。当用户切换卡时,显示不同的组件。例如,你可以使用它来在多个用户界面之间切
5、GridBagLayout:这是一个更复杂的布局管理器,允许组件占据多个行或列的空间。你可以设置组件的位置、大小、填充方式、对齐方式等。
6、BoxLayout:此布局管理器将组件在一行或一列中布局,可以指定组件的对齐方式。
7、SpringLayout:此布局管理器允许组件在网格中的位置和大小由周围的组件决定,就像弹簧一样。通常与其他布局管理器(如GridLayout)结合使用。
8、BorderLayoutManager:这是Java 11中新增的布局管理器,它实现了BorderLayout,但添加了一些额外的功能。例如,它可以处理组件的溢出,当组件的大小超过其容器的大小时,会显示一个滚动条。
以上布局管理器各有优缺点,使用哪个取决于你的具体需求。
1、null绝对布局
Java中的null绝对布局是一种特殊的布局方式,它没有特定的布局管理器类来表示,而是通过设置组件的坐标和宽高来布置组件。
在这种布局方式下,开发人员需要明确指定每个组件的坐标和宽高,否则组件将无法显示。使用其他布局时,如果在窗口显示之后添加新组件,该组件也需要手动指定坐标和宽高。同样,如果在窗口显示之后修改之前添加的组件的坐标和宽高,该组件也会被当做绝对布局对待,此时修改坐标和宽高会生效。
在这种布局方式下,开发人员需要明确指定每个组件的坐标和宽高,否则组件将无法显示。使用其他布局时,如果在窗口显示之后添加新组件,该组件也需要手动指定坐标和宽高。同样,如果在窗口显示之后修改之前添加的组件的坐标和宽高,该组件也会被当做绝对布局对待,此时修改坐标和宽高会生效。
在进行null绝对布局时,setBounds方法是关键。setBounds方法的函数为public void setBounds(int x,int y,int width,int height),其中x、y表示组件右上角坐标,width、height分别表示组件的宽和高,单位为像素。
总的来说,null绝对布局是一种基于坐标和尺寸的布局方式,需要手动指定每个组件的位置和大小
总的来说,null绝对布局是一种基于坐标和尺寸的布局方式,需要手动指定每个组件的位置和大小
示例:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Null Layout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLayout(null); // 设置布局为null绝对布局
// 添加组件并设置位置和大小
JButton button1 = new JButton("按钮 1");
button1.setBounds(10, 10, 80, 30);
frame.add(button1);
JButton button2 = new JButton("按钮 2");
button2.setBounds(100, 10, 80, 30);
frame.add(button2);
JButton button3 = new JButton("按钮 3");
button3.setBounds(190, 10, 80, 30);
frame.add(button3);
// 显示窗口
frame.setVisible(true);
}
}
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Null Layout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLayout(null); // 设置布局为null绝对布局
// 添加组件并设置位置和大小
JButton button1 = new JButton("按钮 1");
button1.setBounds(10, 10, 80, 30);
frame.add(button1);
JButton button2 = new JButton("按钮 2");
button2.setBounds(100, 10, 80, 30);
frame.add(button2);
JButton button3 = new JButton("按钮 3");
button3.setBounds(190, 10, 80, 30);
frame.add(button3);
// 显示窗口
frame.setVisible(true);
}
}
效果:
2、FlowLayout流 布局管理器
Java中的FlowLayout流布局管理器是一种简单的布局管理器,它将组件按照水平或垂直方向排列。在FlowLayout中,组件的排列顺序取决于容器的组件添加顺序。
FlowLayout有两个主要的属性:hgap和vgap。hgap属性用于设置水平方向上两个组件之间的间距,vgap属性用于设置垂直方向上两个组件之间的间距。
在FlowLayout中,每个组件的位置是由其添加的顺序决定的。如果容器宽度不足以容纳所有组件,那么会换行或换列,以便容纳所有的组件。
如果容器高度不足以容纳所有组件,那么会根据组件的尺寸和排列顺序来决定是否换行或换列。
示例:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("FlowLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
// 创建FlowLayout布局管理器并设置间距
FlowLayout layout = new FlowLayout();
layout.setHgap(10);
layout.setVgap(10);
frame.setLayout(layout);
// 添加组件并设置位置和大小
JButton button1 = new JButton("Button 1");
frame.add(button1); // 直接添加到frame中,布局管理器会根据组件的尺寸和排列顺序自动调整位置和大小
JButton button2 = new JButton("Button 2");
frame.add(button2); // 直接添加到frame中,布局管理器会根据组件的尺寸和排列顺序自动调整位置和大小
JButton button3 = new JButton("Button 3");
frame.add(button3); // 直接添加到frame中,布局管理器会根据组件的尺寸和排列顺序自动调整位置和大小
// 显示窗口
frame.setVisible(true);
}
}
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("FlowLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
// 创建FlowLayout布局管理器并设置间距
FlowLayout layout = new FlowLayout();
layout.setHgap(10);
layout.setVgap(10);
frame.setLayout(layout);
// 添加组件并设置位置和大小
JButton button1 = new JButton("Button 1");
frame.add(button1); // 直接添加到frame中,布局管理器会根据组件的尺寸和排列顺序自动调整位置和大小
JButton button2 = new JButton("Button 2");
frame.add(button2); // 直接添加到frame中,布局管理器会根据组件的尺寸和排列顺序自动调整位置和大小
JButton button3 = new JButton("Button 3");
frame.add(button3); // 直接添加到frame中,布局管理器会根据组件的尺寸和排列顺序自动调整位置和大小
// 显示窗口
frame.setVisible(true);
}
}
效果:
3、BorderLayout 边界 布局管理器
Java中的BorderLayout边界布局管理器是一种常见的布局管理器,它将容器分为5个区域:北(NORTH)、南(SOUTH)、东(EAST)、西(WEST)和中(CENTER)。 你可以将组件添加到这些区域中。
使用BorderLayout布局管理器时,每个区域只能包含一个组件。如果尝试将多个组件添加到同一个区域,则只有最后一个组件会显示在该区域中。
以下是BorderLayout布局管理器的特点:
1、每个区域只能包含一个组件。
2、组件不能覆盖多个区域。
3、组件的添加顺序不重要。
4、组件的尺寸由其自身的大小和容器的大小决定。
5、可以使用组件的setBounds方法设置组件的位置和大小。
2、组件不能覆盖多个区域。
3、组件的添加顺序不重要。
4、组件的尺寸由其自身的大小和容器的大小决定。
5、可以使用组件的setBounds方法设置组件的位置和大小。
示例:
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("BorderLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLayout(new BorderLayout()); // 设置布局为BorderLayout
// 添加组件并设置位置和大小
JButton button1 = new JButton("北");
button1.setBounds(10, 10, 80, 30); // 设置位置和大小
frame.add(button1, BorderLayout.NORTH); // 将按钮添加到NORTH区域
JButton button2 = new JButton("中");
button2.setBounds(10, 50, 80, 30); // 设置位置和大小
frame.add(button2, BorderLayout.CENTER); // 将按钮添加到CENTER区域
JButton button3 = new JButton("南");
button3.setBounds(10, 90, 80, 30); // 设置位置和大小
frame.add(button3, BorderLayout.SOUTH); // 将按钮添加到SOUTH区域
JButton button4 = new JButton("东");
button4.setBounds(100, 10, 80, 30); // 设置位置和大小
frame.add(button4, BorderLayout.EAST); // 将按钮添加到EAST区域
JButton button5 = new JButton("西");
button5.setBounds(190, 10, 80, 30); // 设置位置和大小
frame.add(button5, BorderLayout.WEST); // 将按钮添加到WEST区域
// 显示窗口
frame.setVisible(true);
}
}
import java.awt.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("BorderLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLayout(new BorderLayout()); // 设置布局为BorderLayout
// 添加组件并设置位置和大小
JButton button1 = new JButton("北");
button1.setBounds(10, 10, 80, 30); // 设置位置和大小
frame.add(button1, BorderLayout.NORTH); // 将按钮添加到NORTH区域
JButton button2 = new JButton("中");
button2.setBounds(10, 50, 80, 30); // 设置位置和大小
frame.add(button2, BorderLayout.CENTER); // 将按钮添加到CENTER区域
JButton button3 = new JButton("南");
button3.setBounds(10, 90, 80, 30); // 设置位置和大小
frame.add(button3, BorderLayout.SOUTH); // 将按钮添加到SOUTH区域
JButton button4 = new JButton("东");
button4.setBounds(100, 10, 80, 30); // 设置位置和大小
frame.add(button4, BorderLayout.EAST); // 将按钮添加到EAST区域
JButton button5 = new JButton("西");
button5.setBounds(190, 10, 80, 30); // 设置位置和大小
frame.add(button5, BorderLayout.WEST); // 将按钮添加到WEST区域
// 显示窗口
frame.setVisible(true);
}
}
效果:
4、GridLayout 网格布局管理器
GridLayout 网格布局管理器能够把容器划分为网格,组件可以按行列进行排列。
在网格布局管理器中,网格的个数由行数和列数决定,且每个网格的大小都相同。从网格的左上角开始,按照从左到右,从上到下的顺序被添加到网格中,且每个组件都会填满整个网格。改变窗口大小的同时,组件的大小也会随之改变
网格布局管理器主要有以下两个常用的构造方法:
public GridLayout(int rows, int columns)
public GridLayout(int rows, int columns ,int hortizGap,int vertGap)
public GridLayout(int rows, int columns ,int hortizGap,int vertGap)
rows和columns这两个参数只允许有一个参数可以为零,被用于表示一行或一列可以排列任意多个组件
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container c=getContentPane();
//设置容器使用网格布局管理器设置7行3列的网格组件间,水平间距为5像素,垂直间距为5像素
setLayout(new GridLayout(7,3,5,5));
for(int i=0;i<20;i++) {
c.add(new JButton("button"+i));//循环添加按钮
}
setSize(300,300);
setTitle("这是一个使用网格布局管理器的窗体");
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container c=getContentPane();
//设置容器使用网格布局管理器设置7行3列的网格组件间,水平间距为5像素,垂直间距为5像素
setLayout(new GridLayout(7,3,5,5));
for(int i=0;i<20;i++) {
c.add(new JButton("button"+i));//循环添加按钮
}
setSize(300,300);
setTitle("这是一个使用网格布局管理器的窗体");
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main();
}
}
效果图
常用面板
在Swing程序设计中,面板是一个容器,被用于容纳其他组件,
但面板必须被添加到其他容器中。Swing中常用的面板包括JPanel面板和JScrollpane面板
JPanel面板继承Java.awt.Container类,JPanel面板必须在窗体容器中使用,无法脱离窗体显示
但面板必须被添加到其他容器中。Swing中常用的面板包括JPanel面板和JScrollpane面板
JPanel面板继承Java.awt.Container类,JPanel面板必须在窗体容器中使用,无法脱离窗体显示
示例:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container c=getContentPane();//获取窗体主容器
//将整个容器设置为2行2列的网格布局,组件水平间隔10像素,垂直间隔10像素
c.setLayout(new GridLayout(2,2,10,10));
//初始化一个面板,此面板使用1行4列的网格布局,组件水平间隔10像素,垂直间隔10像素
JPanel p1=new JPanel(new GridLayout(1,4,10,10));
//初始化一个面板,此面板使用边界布局
JPanel p2=new JPanel(new BorderLayout());
JPanel p3=new JPanel(new GridLayout(1,2,10,10));
JPanel p4=new JPanel(new GridLayout(2,1,10,10));
//给每个面板都添加边框和标题,使用 BorderFactory 工厂类生成带标题的边框对象
p1.setBorder(BorderFactory.createTitledBorder("面板1"));
p2.setBorder(BorderFactory.createTitledBorder("面板2"));
p3.setBorder(BorderFactory.createTitledBorder("面板3"));
p4.setBorder(BorderFactory.createTitledBorder("面板4"));
//向面板1中添加按钮
p1.add(new JButton("b1"));
p1.add(new JButton("b1"));
p1.add(new JButton("b1"));
p1.add(new JButton("b1"));
//向面板2中添加按钮
p2.add(new JButton("b2"),BorderLayout.WEST);
p2.add(new JButton("b2"),BorderLayout.EAST);
p2.add(new JButton("b2"),BorderLayout.NORTH);
p2.add(new JButton("b2"),BorderLayout.SOUTH);
p2.add(new JButton("b2"),BorderLayout.CENTER);
//向面板3中添加按钮
p3.add(new JButton("b3"));
p3.add(new JButton("b3"));
//向面板4中添加按钮
p4.add(new JButton("b4"));
p4.add(new JButton("b4"));
//向容器中添加面板
c.add(p1);
c.add(p2);
c.add(p3);
c.add(p4);
setTitle("这个窗体中使用了面板");
setSize(500,300);//窗体宽高
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);//关闭动作
}
public static void main(String[] args) {
Main p = new Main();
p.setVisible(true);
}
}
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container c=getContentPane();//获取窗体主容器
//将整个容器设置为2行2列的网格布局,组件水平间隔10像素,垂直间隔10像素
c.setLayout(new GridLayout(2,2,10,10));
//初始化一个面板,此面板使用1行4列的网格布局,组件水平间隔10像素,垂直间隔10像素
JPanel p1=new JPanel(new GridLayout(1,4,10,10));
//初始化一个面板,此面板使用边界布局
JPanel p2=new JPanel(new BorderLayout());
JPanel p3=new JPanel(new GridLayout(1,2,10,10));
JPanel p4=new JPanel(new GridLayout(2,1,10,10));
//给每个面板都添加边框和标题,使用 BorderFactory 工厂类生成带标题的边框对象
p1.setBorder(BorderFactory.createTitledBorder("面板1"));
p2.setBorder(BorderFactory.createTitledBorder("面板2"));
p3.setBorder(BorderFactory.createTitledBorder("面板3"));
p4.setBorder(BorderFactory.createTitledBorder("面板4"));
//向面板1中添加按钮
p1.add(new JButton("b1"));
p1.add(new JButton("b1"));
p1.add(new JButton("b1"));
p1.add(new JButton("b1"));
//向面板2中添加按钮
p2.add(new JButton("b2"),BorderLayout.WEST);
p2.add(new JButton("b2"),BorderLayout.EAST);
p2.add(new JButton("b2"),BorderLayout.NORTH);
p2.add(new JButton("b2"),BorderLayout.SOUTH);
p2.add(new JButton("b2"),BorderLayout.CENTER);
//向面板3中添加按钮
p3.add(new JButton("b3"));
p3.add(new JButton("b3"));
//向面板4中添加按钮
p4.add(new JButton("b4"));
p4.add(new JButton("b4"));
//向容器中添加面板
c.add(p1);
c.add(p2);
c.add(p3);
c.add(p4);
setTitle("这个窗体中使用了面板");
setSize(500,300);//窗体宽高
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);//关闭动作
}
public static void main(String[] args) {
Main p = new Main();
p.setVisible(true);
}
}
运行效果:
JScrollPane滚动面板
JScrollPane面板,是带滚动条的面板,被用于在较小的窗体中显示较大篇幅的内容,要注意的是,不能使用布局管理器,只能容纳一个组件,如果添加多个组件,那么需要先将多个组件添加到JPanel面板,再将JPanel面板添加到滚动面板
示例:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container c = getContentPane();//获取主容器
//创建文本区域组件,文本域默认大小为 20 行、50 列
JTextArea ta = new JTextArea(20,50);
//创建 JScrollPane 滚动面板,并将文本域放到滚动面板中
JScrollPane sp = new JScrollPane(ta);
c.add(sp);//将该面板添加到主容器中
setTitle("带滚动条的文字编译器");
setSize(400,200);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public static void main(String[] args) {
Main p = new Main();
p.setVisible(true);
}
}
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container c = getContentPane();//获取主容器
//创建文本区域组件,文本域默认大小为 20 行、50 列
JTextArea ta = new JTextArea(20,50);
//创建 JScrollPane 滚动面板,并将文本域放到滚动面板中
JScrollPane sp = new JScrollPane(ta);
c.add(sp);//将该面板添加到主容器中
setTitle("带滚动条的文字编译器");
setSize(400,200);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public static void main(String[] args) {
Main p = new Main();
p.setVisible(true);
}
}
运行结果:
文字标签组件与图标
标签被用于显示文本,图标等内容。用户能够通过标签上的文本图标等内容获取相应的提示信息。
1、JLabrl标签
JLabrl标签的父类是JComponent类,标签不能被添加监听器,但是标签显示的文本,图标等内容可以指定对齐方式,通过JLabrl类的构造方法可以创建多种标签,
常用的构造方法如下:
常用的构造方法如下:
示例:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container container=getContentPane();//获取主容器
JLabel jl=new JLabel("这是一个 JFrame 窗体");//创建标签
container.add(jl);
setSize(200,100);//设置窗体大小
setVisible(true);//设置窗体可见
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭窗体则停止程序
}
public static void main(String[] args) {
Main p = new Main();
}
}
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container container=getContentPane();//获取主容器
JLabel jl=new JLabel("这是一个 JFrame 窗体");//创建标签
container.add(jl);
setSize(200,100);//设置窗体大小
setVisible(true);//设置窗体可见
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭窗体则停止程序
}
public static void main(String[] args) {
Main p = new Main();
}
}
运行结果:
2、图标的使用
在swing程序设计中,图标经常被添加到标签,按钮等组件
它有多个常用方法如下:
它有多个常用方法如下:
示例:
import javax.swing.*;
import java.awt.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container container=getContentPane();
JLabel jl=new JLabel("这是一个JFrame窗体");//创建标签
URL url=Main.class.getResource("img\cell.png");//获取图片所在的URL
Icon icon =new ImageIcon(url);//获取图片的icon对象
jl.setIcon(icon);//为标签设置图片
jl.setHorizontalAlignment(SwingConstants.CENTER);//设置文字放置在标签中间
jl.setOpaque(true);//设置标签为不透明状态
container.add(jl);//将标签添加到容器中
setSize(300,200);//设置窗体大小
setVisible(true);//使窗体可见
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭窗体则停止程序
}
public static void main(String[] args) {
Main p = new Main();
}
}
import java.awt.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main extends JFrame {
public Main(){
Container container=getContentPane();
JLabel jl=new JLabel("这是一个JFrame窗体");//创建标签
URL url=Main.class.getResource("img\cell.png");//获取图片所在的URL
Icon icon =new ImageIcon(url);//获取图片的icon对象
jl.setIcon(icon);//为标签设置图片
jl.setHorizontalAlignment(SwingConstants.CENTER);//设置文字放置在标签中间
jl.setOpaque(true);//设置标签为不透明状态
container.add(jl);//将标签添加到容器中
setSize(300,200);//设置窗体大小
setVisible(true);//使窗体可见
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭窗体则停止程序
}
public static void main(String[] args) {
Main p = new Main();
}
}
按钮组件
在Swing程序设计中,按钮是较为常见的组件,被用于触发特定的动作提供了多种按钮,组件按钮,单选按钮,复选框等
1、JButto按钮
Swing按钮由JButto对象表示。
JButto常用的构造方法如下:
创建JButto对象后如果要JButto对象进行设置,那么可以使用JButto提供的方法,提供的方法如下表所示:
1、setText(String text):设置按钮上显示的文本。
2、setMnemonic(char mnemonic):设置按钮的快捷键。
3、setActionListener(ActionListener listener):设置按钮的监听器,当按钮被点击时触发。
4、setBackground(Color color):设置按钮的背景色。
5、setForeground(Color color):设置按钮上显示的文本的颜色。
6、setFont(Font font):设置按钮上显示的文本的字体。
7、setBorder(Border border):设置按钮的边框。
8、setRolloverIcon(Icon icon):设置按钮在鼠标指针滑过时显示的图标。
9、setDisabledIcon(Icon icon):设置按钮被禁用时显示的图标。
10、setDisabledSelectedIcon(Icon icon):设置按钮被禁用且被选中时显示的图标。
2、setMnemonic(char mnemonic):设置按钮的快捷键。
3、setActionListener(ActionListener listener):设置按钮的监听器,当按钮被点击时触发。
4、setBackground(Color color):设置按钮的背景色。
5、setForeground(Color color):设置按钮上显示的文本的颜色。
6、setFont(Font font):设置按钮上显示的文本的字体。
7、setBorder(Border border):设置按钮的边框。
8、setRolloverIcon(Icon icon):设置按钮在鼠标指针滑过时显示的图标。
9、setDisabledIcon(Icon icon):设置按钮被禁用时显示的图标。
10、setDisabledSelectedIcon(Icon icon):设置按钮被禁用且被选中时显示的图标。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
Icon icon=new ImageIcon("");//获取图片文件
setLayout(new GridLayout(3,2,5,5));//设置网格布局管理器
Container c=getContentPane();//获取主容器
JButton btn[]=new JButton[6];//创建按钮数组
for(int i=0;i<btn.length;i++) {
btn[i]=new JButton();//实例化数组中的对象
c.add(btn[i]);//将按钮添加到容器中
}
btn[0].setText("不可用");
btn[0].setEnabled(false);//设置按钮不可用
btn[1].setText("有背景色");
btn[1].setBackground(Color.YELLOW);
btn[2].setText("无边框");
btn[2].setBorderPainted(false);//设置按钮边框不显示
btn[3].setText("有边框");
btn[3].setBorder(BorderFactory.createLineBorder(Color.RED));//添加红色线性边框
btn[4].setIcon(icon);//为按钮设置图标
btn[4].setToolTipText("图片按钮");//设置鼠标悬停时提示的文字
btn[5].setText("可点击");
btn[5].addActionListener(new ActionListener() {//为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(Main.this,"点击按钮");//弹出确认对话框
}
});
setTitle("创建不同样式的按钮");
setBounds(100,100,400,200);//设置窗体大小
setVisible(true);//设置窗体可见
setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗体则停止程序
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
Icon icon=new ImageIcon("");//获取图片文件
setLayout(new GridLayout(3,2,5,5));//设置网格布局管理器
Container c=getContentPane();//获取主容器
JButton btn[]=new JButton[6];//创建按钮数组
for(int i=0;i<btn.length;i++) {
btn[i]=new JButton();//实例化数组中的对象
c.add(btn[i]);//将按钮添加到容器中
}
btn[0].setText("不可用");
btn[0].setEnabled(false);//设置按钮不可用
btn[1].setText("有背景色");
btn[1].setBackground(Color.YELLOW);
btn[2].setText("无边框");
btn[2].setBorderPainted(false);//设置按钮边框不显示
btn[3].setText("有边框");
btn[3].setBorder(BorderFactory.createLineBorder(Color.RED));//添加红色线性边框
btn[4].setIcon(icon);//为按钮设置图标
btn[4].setToolTipText("图片按钮");//设置鼠标悬停时提示的文字
btn[5].setText("可点击");
btn[5].addActionListener(new ActionListener() {//为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(Main.this,"点击按钮");//弹出确认对话框
}
});
setTitle("创建不同样式的按钮");
setBounds(100,100,400,200);//设置窗体大小
setVisible(true);//设置窗体可见
setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗体则停止程序
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
2、JRadioButton单选按钮
Swing单选按钮由JRadioButton对象表示,在swing程序设计中,需要把多个单选按钮添加到按钮组,当用户选中某个单选按钮时,按钮组中的其他单选按钮将不能被同时选中
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("单选按钮的使用");
setBounds(100,100,240,120);
getContentPane().setLayout(null);//设置绝对布局
JLabel lbINewLabel = new JLabel("请选择性别:");
//设置绝对布局
lbINewLabel.setBounds(5, 5,120,15);
getContentPane().add(lbINewLabel);
JRadioButton rbtnNormal =new JRadioButton("男");
rbtnNormal.setSelected(true);
rbtnNormal.setBounds(40, 30, 75,22);
getContentPane().add(rbtnNormal);
JRadioButton rbtnPwd = new JRadioButton("女");
rbtnPwd.setBounds(120,30,75,22);
getContentPane().add(rbtnPwd);
ButtonGroup group = new ButtonGroup(); //创建按钮组,把交互面板中的单选按钮添加到按钮组中
group.add(rbtnNormal);
group.add(rbtnPwd);
}
public static void main(String[] args) {
Main p = new Main();
p.setVisible(true);
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("单选按钮的使用");
setBounds(100,100,240,120);
getContentPane().setLayout(null);//设置绝对布局
JLabel lbINewLabel = new JLabel("请选择性别:");
//设置绝对布局
lbINewLabel.setBounds(5, 5,120,15);
getContentPane().add(lbINewLabel);
JRadioButton rbtnNormal =new JRadioButton("男");
rbtnNormal.setSelected(true);
rbtnNormal.setBounds(40, 30, 75,22);
getContentPane().add(rbtnNormal);
JRadioButton rbtnPwd = new JRadioButton("女");
rbtnPwd.setBounds(120,30,75,22);
getContentPane().add(rbtnPwd);
ButtonGroup group = new ButtonGroup(); //创建按钮组,把交互面板中的单选按钮添加到按钮组中
group.add(rbtnNormal);
group.add(rbtnPwd);
}
public static void main(String[] args) {
Main p = new Main();
p.setVisible(true);
}
}
运行结果:
3、JCheckBox复选框
复选框组件由JCheckBox对象表示,以单选按钮不同的是,窗体中的复选框可以被选中多个,这是因为每一个复选框都提供了被选中和不被选中两种状态。
常用构造方法如下:
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
setBounds(100,100,170,110);//窗口坐标和大小
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container c=getContentPane();//获取主容器
c.setLayout(new FlowLayout());//容器使用流布局
JCheckBox c1=new JCheckBox("1");//创建复选框
JCheckBox c2=new JCheckBox("2");
JCheckBox c3=new JCheckBox("3");
c.add(c1);//容器添加复选框
c.add(c2);
c.add(c3);
JButton btn=new JButton("打印");//创建打印按钮
btn.addActionListener(new ActionListener(){//打印按钮动作事件
public void actionPerformed(ActionEvent e) {
//在控制台分别输出三个复选框的选中状态
System.out.println(c1.getText()+"按钮选中状态:"+c1.isSelected());
System.out.println(c2.getText()+"按钮选中状态:"+c2.isSelected());
System.out.println(c3.getText()+"按钮选中状态:"+c3.isSelected());
}
});
c.add(btn);//容器添加打印按钮
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
setBounds(100,100,170,110);//窗口坐标和大小
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container c=getContentPane();//获取主容器
c.setLayout(new FlowLayout());//容器使用流布局
JCheckBox c1=new JCheckBox("1");//创建复选框
JCheckBox c2=new JCheckBox("2");
JCheckBox c3=new JCheckBox("3");
c.add(c1);//容器添加复选框
c.add(c2);
c.add(c3);
JButton btn=new JButton("打印");//创建打印按钮
btn.addActionListener(new ActionListener(){//打印按钮动作事件
public void actionPerformed(ActionEvent e) {
//在控制台分别输出三个复选框的选中状态
System.out.println(c1.getText()+"按钮选中状态:"+c1.isSelected());
System.out.println(c2.getText()+"按钮选中状态:"+c2.isSelected());
System.out.println(c3.getText()+"按钮选中状态:"+c3.isSelected());
}
});
c.add(btn);//容器添加打印按钮
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
列表组件
Swing中提供两种列表组件,分别为下拉列表框(JComboBox)和列表框(JList),下拉列表框与列表框都是带有一系列列表选项的组件,用户可以从中选择需要的列表项,列表框较下拉列表框更直观,他们将所有的列表项罗列在列表框,但是下拉列表这个表框更为便捷美观,它将所有的列表项隐藏起来,当用户用其中的列表项时才会显示出来
1、JComboBox下拉列表框
初次使用下拉列表框时,会感觉swing中的下拉列表框以WINDOWS操作系统中的下拉列表框有一些相似,实质上两者并不完全相同,因为swing中的下拉列表框不仅可以供用户从中选择,列表项也提供编辑列表项的功能。
JComboBox类的常用构造方法如下:
常用方法:
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("下拉列表框的使用");
setBounds(100,100,317,147);
getContentPane().setLayout(null);//设置绝对布局
JLabel lblNewLabel = new JLabel("请选择证件:");
lblNewLabel.setBounds(28,14,80,15);
getContentPane().add(lblNewLabel);
JComboBox<String>comboBox = new JComboBox<String>();//创建一个下拉列表框
comboBox.setBounds(110,11,80,21); //设置坐标
comboBox.addItem("身份证"); //为下拉列表中添加项
comboBox.addItem("军人证");
comboBox.addItem("学生证");
comboBox.addItem("工作证");
comboBox.setEditable(true); //将下拉列表添加到容器中
getContentPane().add(comboBox);
JButton btnNewButton= new JButton("确定");
btnNewButton.setBounds(200,10,67,23);
getContentPane().add(btnNewButton);
btnNewButton.addActionListener(new ActionListener() { //为按钮添加监听事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
lblNewLabel.setText("你的选择的是:"+ comboBox.getSelectedItem());
}
});
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("下拉列表框的使用");
setBounds(100,100,317,147);
getContentPane().setLayout(null);//设置绝对布局
JLabel lblNewLabel = new JLabel("请选择证件:");
lblNewLabel.setBounds(28,14,80,15);
getContentPane().add(lblNewLabel);
JComboBox<String>comboBox = new JComboBox<String>();//创建一个下拉列表框
comboBox.setBounds(110,11,80,21); //设置坐标
comboBox.addItem("身份证"); //为下拉列表中添加项
comboBox.addItem("军人证");
comboBox.addItem("学生证");
comboBox.addItem("工作证");
comboBox.setEditable(true); //将下拉列表添加到容器中
getContentPane().add(comboBox);
JButton btnNewButton= new JButton("确定");
btnNewButton.setBounds(200,10,67,23);
getContentPane().add(btnNewButton);
btnNewButton.addActionListener(new ActionListener() { //为按钮添加监听事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
lblNewLabel.setText("你的选择的是:"+ comboBox.getSelectedItem());
}
});
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
2、JList列表框
列表框组件被添加到窗体中后,就会被指定长和宽。如果列表框的大小不足以容纳列表项的个数,那么需要设置列表框具有滚动效果,即把列表框添加到滚动面板
列表框组件由j list对象表示常用构造方法如下:
常用方法:
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
Container cp=getContentPane();//获取窗体主容器
cp.setLayout(null);//容器使用绝对布局
//创建字符串数组保存列表中的数据
String[]contents= {"列表1","列表2","列表3","列表4","列表5","列表6"};
JList<String> jl=new JList<>(contents);//创建列表框并将字符串数组作为构造参数
JScrollPane js=new JScrollPane(jl);//将列表框放入滚动面板
js.setBounds(10, 10, 100, 109);//设定滚动面板的坐标和大小
cp.add(js);
JTextArea area=new JTextArea();//创建文本域
JScrollPane scrollPane=new JScrollPane(area);//将文本域放入滚动面板
scrollPane.setBounds(118,10,73,80);//设定滚动面板的坐标和大小
cp.add(scrollPane);
JButton bthNewButton=new JButton("确认");//创建确定按钮
bthNewButton.setBounds(120,96,71,23);//设定按钮的坐标和大小
cp.add(bthNewButton);
bthNewButton.addActionListener(new ActionListener() {//添加按钮事件
public void actionPerformed(ActionEvent e) {
//获取列表中选中的元素返回JAVA.util.list类型
java.util.List<String> values=jl.getSelectedValuesList();
area.setText("");//清空文本域
for(String value : values) {
area.append(value+"\n");//在文本域循环追加列表框中选中的值
}
}
});
setTitle("在这个窗口中使用了列表框");
setSize(300,200);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main(){
Container cp=getContentPane();//获取窗体主容器
cp.setLayout(null);//容器使用绝对布局
//创建字符串数组保存列表中的数据
String[]contents= {"列表1","列表2","列表3","列表4","列表5","列表6"};
JList<String> jl=new JList<>(contents);//创建列表框并将字符串数组作为构造参数
JScrollPane js=new JScrollPane(jl);//将列表框放入滚动面板
js.setBounds(10, 10, 100, 109);//设定滚动面板的坐标和大小
cp.add(js);
JTextArea area=new JTextArea();//创建文本域
JScrollPane scrollPane=new JScrollPane(area);//将文本域放入滚动面板
scrollPane.setBounds(118,10,73,80);//设定滚动面板的坐标和大小
cp.add(scrollPane);
JButton bthNewButton=new JButton("确认");//创建确定按钮
bthNewButton.setBounds(120,96,71,23);//设定按钮的坐标和大小
cp.add(bthNewButton);
bthNewButton.addActionListener(new ActionListener() {//添加按钮事件
public void actionPerformed(ActionEvent e) {
//获取列表中选中的元素返回JAVA.util.list类型
java.util.List<String> values=jl.getSelectedValuesList();
area.setText("");//清空文本域
for(String value : values) {
area.append(value+"\n");//在文本域循环追加列表框中选中的值
}
}
});
setTitle("在这个窗口中使用了列表框");
setSize(300,200);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
文本组件
文本组件在开发swing程序过程中经常被用到,尤其是文本框组件和密码框组件。
1、JTextField文本框
文本框组件由JTextField对象表示。
JTextField常用构造方法如下:
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
Container c = getContentPane();//获取窗体主容器
c.setLayout(new FlowLayout());
JTextField jt = new JTextField("请点击清除按钮");//设定文本框初始值
jt.setColumns(20);//设置文本框长度
jt.setFont(new Font("宋体", Font.PLAIN, 20));//设置字体
JButton jb = new JButton("清除");
jt.addActionListener(new ActionListener() {//为文本框添加回车事件
public void actionPerformed(ActionEvent arf0) {
jt.setText("触发事件");//设置文本框中的值
}
});
jt.addActionListener(new ActionListener() {// 为按钮添加事件
public void actionPerformed(ActionEvent arf0) {
System.out.println(jt.getText());//输出当前文本框的值
jt.setText("");//将文本框置空
jt.requestFocus();// 焦点回到文本框
}
});
c.add(jt);//窗体容器添加文本框
c.add(jb);//窗体添加按钮
setBounds(100, 100, 250, 110);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
Container c = getContentPane();//获取窗体主容器
c.setLayout(new FlowLayout());
JTextField jt = new JTextField("请点击清除按钮");//设定文本框初始值
jt.setColumns(20);//设置文本框长度
jt.setFont(new Font("宋体", Font.PLAIN, 20));//设置字体
JButton jb = new JButton("清除");
jt.addActionListener(new ActionListener() {//为文本框添加回车事件
public void actionPerformed(ActionEvent arf0) {
jt.setText("触发事件");//设置文本框中的值
}
});
jt.addActionListener(new ActionListener() {// 为按钮添加事件
public void actionPerformed(ActionEvent arf0) {
System.out.println(jt.getText());//输出当前文本框的值
jt.setText("");//将文本框置空
jt.requestFocus();// 焦点回到文本框
}
});
c.add(jt);//窗体容器添加文本框
c.add(jb);//窗体添加按钮
setBounds(100, 100, 250, 110);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
2、JPasswordField密码框
密码框组件由JPasswordField对象表示,其作用是把用户输入的字符串,以某种符号进行加密。
常用构造方法如下:
3、 JTextArea文本域
文本域组件由JTextArea对象表示,其作用是接受用户的多行文本输入。
常用构造方法如下:
JTrxtArea类提供了一个setLineWrap(boolean wrap)方法,这个方法被用于设置文本域中的文本内容,是否可以自动换行。如果参数为true,那么会自动换行,否则不会自动换行
此外,还提供了一个append(String str)方法,这个方法被用于向文本域中添加文本内容。
此外,还提供了一个append(String str)方法,这个方法被用于向文本域中添加文本内容。
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
setSize(200,100);
setTitle("定义自动换行的文本域");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Container cp = getContentPane(); //获取窗体主容器
//创建一个文本内容为“文本域”、行高和列宽均为 6 的文本域
JTextArea jt = new JTextArea("文本域",6,6);
jt.setLineWrap(true); //可以自动换行
cp.add(jt);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
setSize(200,100);
setTitle("定义自动换行的文本域");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Container cp = getContentPane(); //获取窗体主容器
//创建一个文本内容为“文本域”、行高和列宽均为 6 的文本域
JTextArea jt = new JTextArea("文本域",6,6);
jt.setLineWrap(true); //可以自动换行
cp.add(jt);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
表格组件
Swing表格由JTable表示其作用是把数据以表格的形式显示给用户。
1、创建表格
JTanle类除了提供了默认的构造方法外,还提供了被用于显示二维数组中的元素的构造方法。这个构造方法的语法如下:
JTanle(Object[][]rowDate,Object[]columnNames)
rowDate存储表格数据的二维数组
columnNames,存储表格列明的一维数组
rowDate存储表格数据的二维数组
columnNames,存储表格列明的一维数组
**在使用表格时,要先把表格添加到滚动面板,再把滚动面板添加到窗体的相应位置 **
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
setTitle("创建可以滚动的表格");
setBounds(100,100,240,150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] columnNames = {"A","B"}; //定义表格列名数
//定义表格数据数组
String[][] tableValues ={{"A1","B1"},{"A2","B2"},{"A3","B3"},
{"A4","B4"},{"A5","B5"}};
//创建指定列名和数据的表格
JTable table = new JTable(tableValues, columnNames);
//创建显示表格的滚动面板
JScrollPane scrollPane = new JScrollPane(table);
//将滚动面板添加到边界布局的中间
getContentPane().add(scrollPane, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
setTitle("创建可以滚动的表格");
setBounds(100,100,240,150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] columnNames = {"A","B"}; //定义表格列名数
//定义表格数据数组
String[][] tableValues ={{"A1","B1"},{"A2","B2"},{"A3","B3"},
{"A4","B4"},{"A5","B5"}};
//创建指定列名和数据的表格
JTable table = new JTable(tableValues, columnNames);
//创建显示表格的滚动面板
JScrollPane scrollPane = new JScrollPane(table);
//将滚动面板添加到边界布局的中间
getContentPane().add(scrollPane, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
2、DefaultTableModel表格数据模型
Swing使用TableModel接口定义了一个表格模型,AbstractDefaultTableModel抽象类实现了TableModel接口的大部分方法。
只有以下三个抽象方法没有实现:
为了实现使用表格模型,创建表格的功能swing提供了表格模型类,DefaultTableModel,DefaultTableModel常用构造方法如下:
示例:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
setTitle ("表演模型与表格");
setBounds(100,100,240,150);//窗体宽高
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane=new JScrollPane();
getContentPane().add(scrollPane,BorderLayout.CENTER);
String[] columnNames= {"A","B"};//定义表格列名数组
//定义表格数据数组
String[][] tableValues= {{"A1","B1"},{"A2","B2"},{"A3","B3"}};
//创建指定表格列名和表格数据的表格模型
DefaultTableModel tableModel=new DefaultTableModel(tableValues,columnNames);
JTable table=new JTable(tableModel);//创建指定表格模型的表格
table.setRowSorter(new TableRowSorter<>(tableModel));
scrollPane.setViewportView(table);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
public class Main extends JFrame {
public Main() {
setTitle ("表演模型与表格");
setBounds(100,100,240,150);//窗体宽高
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane=new JScrollPane();
getContentPane().add(scrollPane,BorderLayout.CENTER);
String[] columnNames= {"A","B"};//定义表格列名数组
//定义表格数据数组
String[][] tableValues= {{"A1","B1"},{"A2","B2"},{"A3","B3"}};
//创建指定表格列名和表格数据的表格模型
DefaultTableModel tableModel=new DefaultTableModel(tableValues,columnNames);
JTable table=new JTable(tableModel);//创建指定表格模型的表格
table.setRowSorter(new TableRowSorter<>(tableModel));
scrollPane.setViewportView(table);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
3、维护表格模型
表格中的数据内容需要用于维护。
使用getValueAt()方法获得表格中某一个单元格的值,
使用addRow()方法向表格中添加新的行
使用setValueAt方法修改表格中某一个单元格的值
使用removeRow方法从表格中删除指定行等
使用addRow()方法向表格中添加新的行
使用setValueAt方法修改表格中某一个单元格的值
使用removeRow方法从表格中删除指定行等
当删除表格模型中的指定行时,每删除一行,其后所有行的索引值将相应的减一,所以当连续删除多行时,需要注意对删除行索引的处理。
示例:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
public class Main extends JFrame {
private DefaultTableModel tableModel;//定义表格模型对象
private JTable table;//定义表格对象
private JTextField aTextFied;
private JTextField bTextFied;
public Main() {
setTitle("维护表格模型");
setBounds(100, 100, 520, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
String[] columnNames = {"A", "B"};//定义表格列名数组
//定义表格数据数组
String[][] tableValues = {{"A1", "B1"}, {"A2", "B2"}, {"A3", "B3"}};
//创建指定表格列名和表格数据的表格模型
tableModel = new DefaultTableModel(tableValues, columnNames);
table = new JTable(tableModel);//创建指定表格模型的表格
table.setRowSorter(new TableRowSorter<>(tableModel));//设置表格的排序器
//设置表格的选择模式为单选
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
//为表格添加鼠标事件监听器
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {//发生了单击事件
int selectedRow = table.getSelectedRow();//获得被选中行的索引
//从表格模型中获得指定单元格的值
Object oa = tableModel.getValueAt(selectedRow, 0);
//从表格模型中获得指定单元格的值
Object ob = tableModel.getValueAt(selectedRow, 1);
aTextFied.setText(oa.toString());//将值赋值给文本框
bTextFied.setText(ob.toString());//将值赋值给文本框
}
});
scrollPane.setViewportView(table);
JPanel panel = new JPanel();
getContentPane().add(panel, BorderLayout.SOUTH);
panel.add(new JLabel("A:"));
aTextFied = new JTextField("A4", 10);
panel.add(aTextFied);
panel.add(new JLabel("B:"));
bTextFied = new JTextField("B4", 10);
panel.add(bTextFied);
JButton addButton = new JButton("添加");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String[] rowValues = {aTextFied.getText(),
bTextFied.getText()};//创建表格行数组
tableModel.addRow(rowValues);//向表格模型中添加一行
int rowCount = table.getRowCount() + 1;
aTextFied.setText("A" + rowCount);
bTextFied.setText("B" + rowCount);
}
});
panel.add(addButton);
JButton updButton = new JButton("修改");
updButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectdRow = table.getSelectedRow();//获得被选中行的索引
if (selectdRow != 1) {//判断是否存在被选中行
//修改表格模型中的指定值
tableModel.setValueAt(aTextFied.getText(), selectdRow, 0);
//修改表格模型中的指定
tableModel.setValueAt(bTextFied.getText(), selectdRow, 1);
}
}
});
panel.add(updButton);
JButton delButton = new JButton("删除");
delButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectedRow = table.getSelectedRow();//获得被选中行的索引
if (selectedRow != -1)//判断是否存在被选中行
tableModel.removeRow(selectedRow);//从表格模型中删除指定行
}
});
panel.add(delButton);
}
public static void main(String[] args) {
Main frame = new Main();
frame.setVisible(true);
}
}
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
public class Main extends JFrame {
private DefaultTableModel tableModel;//定义表格模型对象
private JTable table;//定义表格对象
private JTextField aTextFied;
private JTextField bTextFied;
public Main() {
setTitle("维护表格模型");
setBounds(100, 100, 520, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
String[] columnNames = {"A", "B"};//定义表格列名数组
//定义表格数据数组
String[][] tableValues = {{"A1", "B1"}, {"A2", "B2"}, {"A3", "B3"}};
//创建指定表格列名和表格数据的表格模型
tableModel = new DefaultTableModel(tableValues, columnNames);
table = new JTable(tableModel);//创建指定表格模型的表格
table.setRowSorter(new TableRowSorter<>(tableModel));//设置表格的排序器
//设置表格的选择模式为单选
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
//为表格添加鼠标事件监听器
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {//发生了单击事件
int selectedRow = table.getSelectedRow();//获得被选中行的索引
//从表格模型中获得指定单元格的值
Object oa = tableModel.getValueAt(selectedRow, 0);
//从表格模型中获得指定单元格的值
Object ob = tableModel.getValueAt(selectedRow, 1);
aTextFied.setText(oa.toString());//将值赋值给文本框
bTextFied.setText(ob.toString());//将值赋值给文本框
}
});
scrollPane.setViewportView(table);
JPanel panel = new JPanel();
getContentPane().add(panel, BorderLayout.SOUTH);
panel.add(new JLabel("A:"));
aTextFied = new JTextField("A4", 10);
panel.add(aTextFied);
panel.add(new JLabel("B:"));
bTextFied = new JTextField("B4", 10);
panel.add(bTextFied);
JButton addButton = new JButton("添加");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String[] rowValues = {aTextFied.getText(),
bTextFied.getText()};//创建表格行数组
tableModel.addRow(rowValues);//向表格模型中添加一行
int rowCount = table.getRowCount() + 1;
aTextFied.setText("A" + rowCount);
bTextFied.setText("B" + rowCount);
}
});
panel.add(addButton);
JButton updButton = new JButton("修改");
updButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectdRow = table.getSelectedRow();//获得被选中行的索引
if (selectdRow != 1) {//判断是否存在被选中行
//修改表格模型中的指定值
tableModel.setValueAt(aTextFied.getText(), selectdRow, 0);
//修改表格模型中的指定
tableModel.setValueAt(bTextFied.getText(), selectdRow, 1);
}
}
});
panel.add(updButton);
JButton delButton = new JButton("删除");
delButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectedRow = table.getSelectedRow();//获得被选中行的索引
if (selectedRow != -1)//判断是否存在被选中行
tableModel.removeRow(selectedRow);//从表格模型中删除指定行
}
});
panel.add(delButton);
}
public static void main(String[] args) {
Main frame = new Main();
frame.setVisible(true);
}
}
运行结果:
事件监听器
Java中的事件监听器是一种用于监听特定事件并对其做出响应的机制。它由事件类和监听接口组成,当特定事件发生时,事件源会调用相应的监听器接口的方法,并在调用时将事件对象传递进去。
事件类是继承自java.util.EventObject的类 用于表示事件本身的属性和状态。例如,ActionEvent类表示用户界面组件的动作事件。
监听接口是继承自java.util.EventListener的类,它定义了事件发生时应执行的操作。例如,ActionListener接口定义了actionPerformed方法,当按钮被点击时,该方法会被调用。
使用事件监听器可以方便地实现对特定事件的管理和响应。
在Java中,事件监听器是通过将事件对象传递给监听器接口的方法来实现的。通过在方法中访问事件对象,可以获取有关事件的信息,例如事件源和事件类型,从而对事件进行适当的处理。
1、ActionEvent动作事件
在Java中,ActionEvent是用于监听用户界面(UI)组件(如按钮点击,菜单项选择等)的动作事件的一种事件。ActionEvent类是java.awt.event包的一部分,它包含有关发生的事件的信息,例如事件源,发生事件的时间以及事件的类型。
当用户执行某种动作(如点击按钮)时,相应的组件会生成一个ActionEvent对象,然后调用其监听器的actionPerformed方法。这个方法是在ActionListener接口中定义的。
当用户执行某种动作(如点击按钮)时,相应的组件会生成一个ActionEvent对象,然后调用其监听器的actionPerformed方法。这个方法是在ActionListener接口中定义的。
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main extends JFrame {
private JButton jb=new JButton("我是按钮,点击我");
public Main() {
setLayout(null);
setSize(200,100);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Container cp=getContentPane();
cp.add(jb);
jb.setBounds(10,10,150,30);
jb.addActionListener(new jbAction());
setVisible(true);
}
class jbAction implements ActionListener{
public void actionPerformed(ActionEvent arg0) {
jb.setText("我被点击了");
}
}
public static void main(String[] args) {
new Main();
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main extends JFrame {
private JButton jb=new JButton("我是按钮,点击我");
public Main() {
setLayout(null);
setSize(200,100);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Container cp=getContentPane();
cp.add(jb);
jb.setBounds(10,10,150,30);
jb.addActionListener(new jbAction());
setVisible(true);
}
class jbAction implements ActionListener{
public void actionPerformed(ActionEvent arg0) {
jb.setText("我被点击了");
}
}
public static void main(String[] args) {
new Main();
}
}
运行结果:
2、KeyEvent键盘事件监听器
在Java中,KeyEvent是用于捕获键盘事件的一个类。
在Java中,KeyEvent是用于捕获键盘事件的一个类。
当向文本框中输入内容时,会发出键盘事件。KeyEvent类负责捕获这些键盘事件,并且可以通过为组件添加实现了KeyListener接口的监听器类来处理相应的键盘事件。
KeyListener接口定义了三个抽象方法,它们分别在发生击键事件、按键被按下和释放时被触发。具体地,当按下一个键时会调用KeyPressed处理器,当松开一个键时会调用KeyReleased处理器,当输入一个统一编码时会调用KeyTyped处理器。
1、public void keyTyped(KeyEvent e):发生击键事件时被触发
2、public void keyPressed(KeyEvent e):按键被按下时被触发
3、public void keyReleased(KeyEvent e):按键被释放时被触发
2、public void keyPressed(KeyEvent e):按键被按下时被触发
3、public void keyReleased(KeyEvent e):按键被释放时被触发
KeyListener接口的这些方法可以在用户执行键盘操作时被调用,从而实现对键盘事件的处理。例如,当用户按下键盘上的一个键时,相应的KeyPressed方法就会被调用,这个方法中可以编写处理按键按下的代码。
在Java的Swing库中,很多组件(如JTextField等)都提供了添加KeyListener的方法,使得这些组件在用户执行键盘操作时能够触发事件。例如,JTextField提供了addKeyListener方法来添加一个KeyListener。
在Java的Swing库中,很多组件(如JTextField等)都提供了添加KeyListener的方法,使得这些组件在用户执行键盘操作时能够触发事件。例如,JTextField提供了addKeyListener方法来添加一个KeyListener。
KeyListener常用方法:
示例:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.border.TitledBorder;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JTextField;
/**
* 虚拟键盘(键盘的按下与释放)
*/
public class Main extends JFrame { // 创建“键盘”类继承JFrame
// 声明窗体中的成员组件
private JPanel contentPane;
private JTextField textField;
private JButton btnQ;
private JButton btnW;
private JButton btnE;
private JButton btnR;
private JButton btnT;
private JButton btnY;
private JButton btnU;
private JButton btnI;
private JButton btnO;
private JButton btnP;
private JButton btnA;
private JButton btnS;
private JButton btnD;
private JButton btnF;
private JButton btnG;
private JButton btnH;
private JButton btnJ;
private JButton btnK;
private JButton btnL;
private JButton btnZ;
private JButton btnX;
private JButton btnC;
private JButton btnV;
private JButton btnB;
private JButton btnN;
private JButton btnM;
Color green = Color.GREEN;// 定义Color对象,用来表示按下键的颜色
Color white = Color.WHITE;// 定义Color对象,用来表示释放键的颜色
Color red=Color.RED;
ArrayList<JButton> btns = new ArrayList<JButton>();// 定义一个集合,用来存储所有的按键ID
// 自定义一个方法,用来将容器中的所有JButton组件添加到集合中
private void addButtons() {
for (Component cmp : contentPane.getComponents()) {// 遍历面板中的所有组件
if (cmp instanceof JButton) {// 判断组件的类型是否为JButton类型
btns.add((JButton) cmp);// 将JButton组件添加到集合中
}
}
}
/**
* 主方法
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() { // 使得Runnable中的的run()方法在the system EventQueue的指派线程中被调用
public void run() {
try {
Main frame = new Main(); // 创建KeyBoard对象
frame.setVisible(true); // 使frame可视
frame.addButtons();// 初始化存储所有按键的集合
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 创建JFrame窗体
*/
public Main() { // KeyBoard的构造方法
setTitle("\u865A\u62DF\u952E\u76D8\uFF08\u6A21\u62DF\u952E\u76D8\u7684\u6309\u4E0B\u4E0E\u91CA\u653E\uFF09"); // 设置窗体题目
setResizable(false); // 不可改变窗体宽高
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置窗体关闭的方式
setBounds(100, 100, 560, 280); // 设置窗体的位置和宽高
/**
* 创建JPanel面板contentPane置于JFrame窗体中,并设置面板的背景色、边距和布局
*/
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
/**
* 创建按钮button置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnQ = new JButton("Q");
btnQ.setBackground(white);
btnQ.setVerticalAlignment(SwingConstants.TOP);
btnQ.setHorizontalAlignment(SwingConstants.LEADING);
btnQ.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnQ.setBounds(0, 60, 47, 45);
contentPane.add(btnQ);
/**
* 创建按钮button_2置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnW = new JButton("W");
btnW.setBackground(white);
btnW.setVerticalAlignment(SwingConstants.TOP);
btnW.setHorizontalAlignment(SwingConstants.LEADING);
btnW.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnW.setBounds(55, 60, 49, 45);
contentPane.add(btnW);
/**
* 创建按钮button_3置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnE = new JButton("E");
btnE.setBackground(white);
btnE.setVerticalAlignment(SwingConstants.TOP);
btnE.setHorizontalAlignment(SwingConstants.LEADING);
btnE.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnE.setBounds(110, 60, 45, 45);
contentPane.add(btnE);
/**
* 创建按钮button_4置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnR = new JButton("R");
btnR.setBackground(white);
btnR.setVerticalAlignment(SwingConstants.TOP);
btnR.setHorizontalAlignment(SwingConstants.LEADING);
btnR.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnR.setBounds(165, 60, 45, 45);
contentPane.add(btnR);
/**
* 创建按钮button_5置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnF = new JButton("F");
btnF.setBackground(white);
btnF.setVerticalAlignment(SwingConstants.TOP);
btnF.setHorizontalAlignment(SwingConstants.LEADING);
btnF.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnF.setBounds(195, 125, 45, 45);
contentPane.add(btnF);
/**
* 创建按钮button_6置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnD = new JButton("D");
btnD.setBackground(white);
btnD.setVerticalAlignment(SwingConstants.TOP);
btnD.setHorizontalAlignment(SwingConstants.LEADING);
btnD.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnD.setBounds(137, 125, 45, 45);
contentPane.add(btnD);
btnT = new JButton("T");
btnT.setVerticalAlignment(SwingConstants.TOP);
btnT.setHorizontalAlignment(SwingConstants.LEADING);
btnT.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnT.setBackground(white);
btnT.setBounds(220, 60, 45, 45);
contentPane.add(btnT);
btnY = new JButton("Y");
btnY.setVerticalAlignment(SwingConstants.TOP);
btnY.setHorizontalAlignment(SwingConstants.LEADING);
btnY.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnY.setBackground(white);
btnY.setBounds(275, 60, 45, 45);
contentPane.add(btnY);
btnU = new JButton("U");
btnU.setVerticalAlignment(SwingConstants.TOP);
btnU.setHorizontalAlignment(SwingConstants.LEADING);
btnU.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnU.setBackground(white);
btnU.setBounds(330, 60, 45, 45);
contentPane.add(btnU);
btnI = new JButton("I");
btnI.setVerticalAlignment(SwingConstants.TOP);
btnI.setHorizontalAlignment(SwingConstants.LEADING);
btnI.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnI.setBackground(white);
btnI.setBounds(385, 60, 45, 45);
contentPane.add(btnI);
btnO = new JButton("O");
btnO.setVerticalAlignment(SwingConstants.TOP);
btnO.setHorizontalAlignment(SwingConstants.LEADING);
btnO.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnO.setBackground(white);
btnO.setBounds(440, 60, 46, 45);
contentPane.add(btnO);
btnP = new JButton("P");
btnP.setVerticalAlignment(SwingConstants.TOP);
btnP.setHorizontalAlignment(SwingConstants.LEADING);
btnP.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnP.setBackground(white);
btnP.setBounds(495, 60, 45, 45);
contentPane.add(btnP);
btnA = new JButton("A");
btnA.setVerticalAlignment(SwingConstants.TOP);
btnA.setHorizontalAlignment(SwingConstants.LEADING);
btnA.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnA.setBackground(white);
btnA.setBounds(23, 125, 45, 45);
contentPane.add(btnA);
btnS = new JButton("S");
btnS.setVerticalAlignment(SwingConstants.TOP);
btnS.setHorizontalAlignment(SwingConstants.LEADING);
btnS.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnS.setBackground(white);
btnS.setBounds(82, 125, 45, 45);
contentPane.add(btnS);
btnG = new JButton("G");
btnG.setVerticalAlignment(SwingConstants.TOP);
btnG.setHorizontalAlignment(SwingConstants.LEADING);
btnG.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnG.setBackground(white);
btnG.setBounds(251, 125, 45, 45);
contentPane.add(btnG);
btnH = new JButton("H");
btnH.setVerticalAlignment(SwingConstants.TOP);
btnH.setHorizontalAlignment(SwingConstants.LEADING);
btnH.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnH.setBackground(white);
btnH.setBounds(306, 125, 45, 45);
contentPane.add(btnH);
btnJ = new JButton("J");
btnJ.setVerticalAlignment(SwingConstants.TOP);
btnJ.setHorizontalAlignment(SwingConstants.LEADING);
btnJ.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnJ.setBackground(white);
btnJ.setBounds(361, 125, 45, 45);
contentPane.add(btnJ);
btnK = new JButton("K");
btnK.setVerticalAlignment(SwingConstants.TOP);
btnK.setHorizontalAlignment(SwingConstants.LEADING);
btnK.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnK.setBackground(white);
btnK.setBounds(416, 125, 47, 45);
contentPane.add(btnK);
btnL = new JButton("L");
btnL.setVerticalAlignment(SwingConstants.TOP);
btnL.setHorizontalAlignment(SwingConstants.LEADING);
btnL.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnL.setBackground(white);
btnL.setBounds(471, 125, 45, 45);
contentPane.add(btnL);
btnZ = new JButton("Z");
btnZ.setVerticalAlignment(SwingConstants.TOP);
btnZ.setHorizontalAlignment(SwingConstants.LEADING);
btnZ.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnZ.setBackground(white);
btnZ.setBounds(39, 190, 45, 45);
contentPane.add(btnZ);
btnX = new JButton("X");
btnX.setVerticalAlignment(SwingConstants.TOP);
btnX.setHorizontalAlignment(SwingConstants.LEADING);
btnX.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnX.setBackground(white);
btnX.setBounds(107, 190, 45, 45);
contentPane.add(btnX);
btnC = new JButton("C");
btnC.setVerticalAlignment(SwingConstants.TOP);
btnC.setHorizontalAlignment(SwingConstants.LEADING);
btnC.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnC.setBackground(white);
btnC.setBounds(178, 190, 45, 45);
contentPane.add(btnC);
btnV = new JButton("V");
btnV.setVerticalAlignment(SwingConstants.TOP);
btnV.setHorizontalAlignment(SwingConstants.LEADING);
btnV.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnV.setBackground(white);
btnV.setBounds(250, 190, 45, 45);
contentPane.add(btnV);
btnB = new JButton("B");
btnB.setVerticalAlignment(SwingConstants.TOP);
btnB.setHorizontalAlignment(SwingConstants.LEADING);
btnB.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnB.setBackground(white);
btnB.setBounds(315, 190, 45, 45);
contentPane.add(btnB);
btnN = new JButton("N");
btnN.setVerticalAlignment(SwingConstants.TOP);
btnN.setHorizontalAlignment(SwingConstants.LEADING);
btnN.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnN.setBackground(white);
btnN.setBounds(382, 190, 47, 45);
contentPane.add(btnN);
btnM = new JButton("M");
btnM.setVerticalAlignment(SwingConstants.TOP);
btnM.setHorizontalAlignment(SwingConstants.LEADING);
btnM.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnM.setBackground(white);
btnM.setBounds(449, 190, 48, 45);
contentPane.add(btnM);
/**
* 创建面板panel置于面板contentPane中,设置面板panel的位置、宽高、TitledBorder、背景色以及布局方式(边界布局)
*/
JPanel panel = new JPanel();
panel.setBorder(new TitledBorder(null, "文本显示区", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBackground(Color.WHITE);
panel.setBounds(0, 0, 540, 45);
contentPane.add(panel);
panel.setLayout(new BorderLayout(0, 0));
/**
* 创建文本框textField置于面板panel的中间
*/
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() { // 文本框添加键盘事件的监听
char word;
@Override
public void keyPressed(KeyEvent e) { // 按键被按下时被触发
word = e.getKeyChar();// 获取按下键表示的字符
for (int i = 0; i < btns.size(); i++) {// 遍历存储按键ID的ArrayList集合
// 判断按键是否与遍历到的按键的文本相同
if (String.valueOf(word).equalsIgnoreCase(btns.get(i).getText())) {
btns.get(i).setBackground(green);// 将指定按键颜色设置为绿色
}
}
}
@Override
public void keyReleased(KeyEvent e) { // 按键被释放时被触发
word = e.getKeyChar();// 获取释放键表示的字符
for (int i = 0; i < btns.size(); i++) {// 遍历存储按键ID的ArrayList集合
// 判断按键是否与遍历到的按键的文本相同
if (String.valueOf(word).equalsIgnoreCase(btns.get(i).getText())) {
btns.get(i).setBackground(red);// 将指定按键颜色设置为白色
}
}
}
});
panel.add(textField, BorderLayout.CENTER);
textField.setColumns(10);
}
}
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.border.TitledBorder;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JTextField;
/**
* 虚拟键盘(键盘的按下与释放)
*/
public class Main extends JFrame { // 创建“键盘”类继承JFrame
// 声明窗体中的成员组件
private JPanel contentPane;
private JTextField textField;
private JButton btnQ;
private JButton btnW;
private JButton btnE;
private JButton btnR;
private JButton btnT;
private JButton btnY;
private JButton btnU;
private JButton btnI;
private JButton btnO;
private JButton btnP;
private JButton btnA;
private JButton btnS;
private JButton btnD;
private JButton btnF;
private JButton btnG;
private JButton btnH;
private JButton btnJ;
private JButton btnK;
private JButton btnL;
private JButton btnZ;
private JButton btnX;
private JButton btnC;
private JButton btnV;
private JButton btnB;
private JButton btnN;
private JButton btnM;
Color green = Color.GREEN;// 定义Color对象,用来表示按下键的颜色
Color white = Color.WHITE;// 定义Color对象,用来表示释放键的颜色
Color red=Color.RED;
ArrayList<JButton> btns = new ArrayList<JButton>();// 定义一个集合,用来存储所有的按键ID
// 自定义一个方法,用来将容器中的所有JButton组件添加到集合中
private void addButtons() {
for (Component cmp : contentPane.getComponents()) {// 遍历面板中的所有组件
if (cmp instanceof JButton) {// 判断组件的类型是否为JButton类型
btns.add((JButton) cmp);// 将JButton组件添加到集合中
}
}
}
/**
* 主方法
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() { // 使得Runnable中的的run()方法在the system EventQueue的指派线程中被调用
public void run() {
try {
Main frame = new Main(); // 创建KeyBoard对象
frame.setVisible(true); // 使frame可视
frame.addButtons();// 初始化存储所有按键的集合
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 创建JFrame窗体
*/
public Main() { // KeyBoard的构造方法
setTitle("\u865A\u62DF\u952E\u76D8\uFF08\u6A21\u62DF\u952E\u76D8\u7684\u6309\u4E0B\u4E0E\u91CA\u653E\uFF09"); // 设置窗体题目
setResizable(false); // 不可改变窗体宽高
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置窗体关闭的方式
setBounds(100, 100, 560, 280); // 设置窗体的位置和宽高
/**
* 创建JPanel面板contentPane置于JFrame窗体中,并设置面板的背景色、边距和布局
*/
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
/**
* 创建按钮button置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnQ = new JButton("Q");
btnQ.setBackground(white);
btnQ.setVerticalAlignment(SwingConstants.TOP);
btnQ.setHorizontalAlignment(SwingConstants.LEADING);
btnQ.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnQ.setBounds(0, 60, 47, 45);
contentPane.add(btnQ);
/**
* 创建按钮button_2置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnW = new JButton("W");
btnW.setBackground(white);
btnW.setVerticalAlignment(SwingConstants.TOP);
btnW.setHorizontalAlignment(SwingConstants.LEADING);
btnW.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnW.setBounds(55, 60, 49, 45);
contentPane.add(btnW);
/**
* 创建按钮button_3置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnE = new JButton("E");
btnE.setBackground(white);
btnE.setVerticalAlignment(SwingConstants.TOP);
btnE.setHorizontalAlignment(SwingConstants.LEADING);
btnE.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnE.setBounds(110, 60, 45, 45);
contentPane.add(btnE);
/**
* 创建按钮button_4置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnR = new JButton("R");
btnR.setBackground(white);
btnR.setVerticalAlignment(SwingConstants.TOP);
btnR.setHorizontalAlignment(SwingConstants.LEADING);
btnR.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnR.setBounds(165, 60, 45, 45);
contentPane.add(btnR);
/**
* 创建按钮button_5置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnF = new JButton("F");
btnF.setBackground(white);
btnF.setVerticalAlignment(SwingConstants.TOP);
btnF.setHorizontalAlignment(SwingConstants.LEADING);
btnF.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnF.setBounds(195, 125, 45, 45);
contentPane.add(btnF);
/**
* 创建按钮button_6置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnD = new JButton("D");
btnD.setBackground(white);
btnD.setVerticalAlignment(SwingConstants.TOP);
btnD.setHorizontalAlignment(SwingConstants.LEADING);
btnD.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnD.setBounds(137, 125, 45, 45);
contentPane.add(btnD);
btnT = new JButton("T");
btnT.setVerticalAlignment(SwingConstants.TOP);
btnT.setHorizontalAlignment(SwingConstants.LEADING);
btnT.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnT.setBackground(white);
btnT.setBounds(220, 60, 45, 45);
contentPane.add(btnT);
btnY = new JButton("Y");
btnY.setVerticalAlignment(SwingConstants.TOP);
btnY.setHorizontalAlignment(SwingConstants.LEADING);
btnY.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnY.setBackground(white);
btnY.setBounds(275, 60, 45, 45);
contentPane.add(btnY);
btnU = new JButton("U");
btnU.setVerticalAlignment(SwingConstants.TOP);
btnU.setHorizontalAlignment(SwingConstants.LEADING);
btnU.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnU.setBackground(white);
btnU.setBounds(330, 60, 45, 45);
contentPane.add(btnU);
btnI = new JButton("I");
btnI.setVerticalAlignment(SwingConstants.TOP);
btnI.setHorizontalAlignment(SwingConstants.LEADING);
btnI.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnI.setBackground(white);
btnI.setBounds(385, 60, 45, 45);
contentPane.add(btnI);
btnO = new JButton("O");
btnO.setVerticalAlignment(SwingConstants.TOP);
btnO.setHorizontalAlignment(SwingConstants.LEADING);
btnO.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnO.setBackground(white);
btnO.setBounds(440, 60, 46, 45);
contentPane.add(btnO);
btnP = new JButton("P");
btnP.setVerticalAlignment(SwingConstants.TOP);
btnP.setHorizontalAlignment(SwingConstants.LEADING);
btnP.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnP.setBackground(white);
btnP.setBounds(495, 60, 45, 45);
contentPane.add(btnP);
btnA = new JButton("A");
btnA.setVerticalAlignment(SwingConstants.TOP);
btnA.setHorizontalAlignment(SwingConstants.LEADING);
btnA.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnA.setBackground(white);
btnA.setBounds(23, 125, 45, 45);
contentPane.add(btnA);
btnS = new JButton("S");
btnS.setVerticalAlignment(SwingConstants.TOP);
btnS.setHorizontalAlignment(SwingConstants.LEADING);
btnS.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnS.setBackground(white);
btnS.setBounds(82, 125, 45, 45);
contentPane.add(btnS);
btnG = new JButton("G");
btnG.setVerticalAlignment(SwingConstants.TOP);
btnG.setHorizontalAlignment(SwingConstants.LEADING);
btnG.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnG.setBackground(white);
btnG.setBounds(251, 125, 45, 45);
contentPane.add(btnG);
btnH = new JButton("H");
btnH.setVerticalAlignment(SwingConstants.TOP);
btnH.setHorizontalAlignment(SwingConstants.LEADING);
btnH.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnH.setBackground(white);
btnH.setBounds(306, 125, 45, 45);
contentPane.add(btnH);
btnJ = new JButton("J");
btnJ.setVerticalAlignment(SwingConstants.TOP);
btnJ.setHorizontalAlignment(SwingConstants.LEADING);
btnJ.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnJ.setBackground(white);
btnJ.setBounds(361, 125, 45, 45);
contentPane.add(btnJ);
btnK = new JButton("K");
btnK.setVerticalAlignment(SwingConstants.TOP);
btnK.setHorizontalAlignment(SwingConstants.LEADING);
btnK.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnK.setBackground(white);
btnK.setBounds(416, 125, 47, 45);
contentPane.add(btnK);
btnL = new JButton("L");
btnL.setVerticalAlignment(SwingConstants.TOP);
btnL.setHorizontalAlignment(SwingConstants.LEADING);
btnL.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnL.setBackground(white);
btnL.setBounds(471, 125, 45, 45);
contentPane.add(btnL);
btnZ = new JButton("Z");
btnZ.setVerticalAlignment(SwingConstants.TOP);
btnZ.setHorizontalAlignment(SwingConstants.LEADING);
btnZ.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnZ.setBackground(white);
btnZ.setBounds(39, 190, 45, 45);
contentPane.add(btnZ);
btnX = new JButton("X");
btnX.setVerticalAlignment(SwingConstants.TOP);
btnX.setHorizontalAlignment(SwingConstants.LEADING);
btnX.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnX.setBackground(white);
btnX.setBounds(107, 190, 45, 45);
contentPane.add(btnX);
btnC = new JButton("C");
btnC.setVerticalAlignment(SwingConstants.TOP);
btnC.setHorizontalAlignment(SwingConstants.LEADING);
btnC.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnC.setBackground(white);
btnC.setBounds(178, 190, 45, 45);
contentPane.add(btnC);
btnV = new JButton("V");
btnV.setVerticalAlignment(SwingConstants.TOP);
btnV.setHorizontalAlignment(SwingConstants.LEADING);
btnV.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnV.setBackground(white);
btnV.setBounds(250, 190, 45, 45);
contentPane.add(btnV);
btnB = new JButton("B");
btnB.setVerticalAlignment(SwingConstants.TOP);
btnB.setHorizontalAlignment(SwingConstants.LEADING);
btnB.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnB.setBackground(white);
btnB.setBounds(315, 190, 45, 45);
contentPane.add(btnB);
btnN = new JButton("N");
btnN.setVerticalAlignment(SwingConstants.TOP);
btnN.setHorizontalAlignment(SwingConstants.LEADING);
btnN.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnN.setBackground(white);
btnN.setBounds(382, 190, 47, 45);
contentPane.add(btnN);
btnM = new JButton("M");
btnM.setVerticalAlignment(SwingConstants.TOP);
btnM.setHorizontalAlignment(SwingConstants.LEADING);
btnM.setFont(new Font("Times New Roman", Font.PLAIN, 14));
btnM.setBackground(white);
btnM.setBounds(449, 190, 48, 45);
contentPane.add(btnM);
/**
* 创建面板panel置于面板contentPane中,设置面板panel的位置、宽高、TitledBorder、背景色以及布局方式(边界布局)
*/
JPanel panel = new JPanel();
panel.setBorder(new TitledBorder(null, "文本显示区", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBackground(Color.WHITE);
panel.setBounds(0, 0, 540, 45);
contentPane.add(panel);
panel.setLayout(new BorderLayout(0, 0));
/**
* 创建文本框textField置于面板panel的中间
*/
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() { // 文本框添加键盘事件的监听
char word;
@Override
public void keyPressed(KeyEvent e) { // 按键被按下时被触发
word = e.getKeyChar();// 获取按下键表示的字符
for (int i = 0; i < btns.size(); i++) {// 遍历存储按键ID的ArrayList集合
// 判断按键是否与遍历到的按键的文本相同
if (String.valueOf(word).equalsIgnoreCase(btns.get(i).getText())) {
btns.get(i).setBackground(green);// 将指定按键颜色设置为绿色
}
}
}
@Override
public void keyReleased(KeyEvent e) { // 按键被释放时被触发
word = e.getKeyChar();// 获取释放键表示的字符
for (int i = 0; i < btns.size(); i++) {// 遍历存储按键ID的ArrayList集合
// 判断按键是否与遍历到的按键的文本相同
if (String.valueOf(word).equalsIgnoreCase(btns.get(i).getText())) {
btns.get(i).setBackground(red);// 将指定按键颜色设置为白色
}
}
}
});
panel.add(textField, BorderLayout.CENTER);
textField.setColumns(10);
}
}
运行结果:
3、MouseEvent鼠标事件
所有组件都能发生鼠标事件,MouseEvent类负责捕捉鼠标事件,可以通过为组件添加实现了MouseListener接口的监听器类来处理相应的鼠标事件
MouseListener接口有5个抽象方法:
public void mouseEntered(MouseEvent e):光标移入组件时被触发
public void mousePressed(MouseEvent e):鼠标按键被按下时被触发
public void mouseReleased(MouseEvent e):鼠标按键被释放时被触发
public void mouseClicked(MouseEvent e):发生单机事件时被触发
public void mouseExited(MouseEvent e):光标移出组件时被触发
public void mousePressed(MouseEvent e):鼠标按键被按下时被触发
public void mouseReleased(MouseEvent e):鼠标按键被释放时被触发
public void mouseClicked(MouseEvent e):发生单机事件时被触发
public void mouseExited(MouseEvent e):光标移出组件时被触发
常用方法:
静态常量:
分别代表:左键、滚轮和右键。
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Main extends JFrame {
public static void main(String args[]) {
Main frame = new Main();
frame.setVisible(true); // 设置窗体可见,默认为不可见
}
/**
* 判断按下的鼠标键,并输出相应提示
*
* @param e 鼠标事件
*/
private void mouseOper(MouseEvent e) {
int i=e.getButton();
if(i==MouseEvent.BUTTON1)
System.out.println("按下的是鼠标左键");
else if (i==MouseEvent.BUTTON2)
System.out.println("按下的是鼠标滚轮");
else if(i==MouseEvent.BUTTON3)
System.out.println("按下的是鼠标右键");
}
public Main() {
super(); // 继承父类的构造方法
setTitle("鼠标事件示例"); // 设置窗体的标题
setBounds(100, 100, 500, 375); // 设置窗体的显示位置及大小
// 设置窗体关闭按钮的动作为退出
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel label = new JLabel();
label.addMouseListener(new MouseListener() {
public void mouseEntered(MouseEvent e) {
System.out.println("光标移入组件");
}
public void mousePressed (MouseEvent e) {
System.out.println("鼠标按键被按下");
mouseOper(e);
}
public void mouseReleased (MouseEvent e) {
System.out.println("鼠标按键被释放");
mouseOper(e);
}
public void mouseClicked (MouseEvent e) {
System.out.println("单击了鼠标按键");
mouseOper(e);
int clickCount=e.getClickCount();
System.out.println("单击次数为"+clickCount+"下");
}
public void mouseExited(MouseEvent e) {
System.out.println("光标移出组件");
}
});
getContentPane().add(label, BorderLayout.CENTER);
}
}
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Main extends JFrame {
public static void main(String args[]) {
Main frame = new Main();
frame.setVisible(true); // 设置窗体可见,默认为不可见
}
/**
* 判断按下的鼠标键,并输出相应提示
*
* @param e 鼠标事件
*/
private void mouseOper(MouseEvent e) {
int i=e.getButton();
if(i==MouseEvent.BUTTON1)
System.out.println("按下的是鼠标左键");
else if (i==MouseEvent.BUTTON2)
System.out.println("按下的是鼠标滚轮");
else if(i==MouseEvent.BUTTON3)
System.out.println("按下的是鼠标右键");
}
public Main() {
super(); // 继承父类的构造方法
setTitle("鼠标事件示例"); // 设置窗体的标题
setBounds(100, 100, 500, 375); // 设置窗体的显示位置及大小
// 设置窗体关闭按钮的动作为退出
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel label = new JLabel();
label.addMouseListener(new MouseListener() {
public void mouseEntered(MouseEvent e) {
System.out.println("光标移入组件");
}
public void mousePressed (MouseEvent e) {
System.out.println("鼠标按键被按下");
mouseOper(e);
}
public void mouseReleased (MouseEvent e) {
System.out.println("鼠标按键被释放");
mouseOper(e);
}
public void mouseClicked (MouseEvent e) {
System.out.println("单击了鼠标按键");
mouseOper(e);
int clickCount=e.getClickCount();
System.out.println("单击次数为"+clickCount+"下");
}
public void mouseExited(MouseEvent e) {
System.out.println("光标移出组件");
}
});
getContentPane().add(label, BorderLayout.CENTER);
}
}
运行结果:
Java绘图
Java绘图是指在Java程序中创建和显示图形的过程。Java提供了许多类和方法来支持绘图。
Java绘图类
Java中主要的绘图类是Graphics类,它提供了基本的绘图方法和属性设置方法。
Graphics类的一些常用方法:
setColor(Color c):设置绘图颜色。
setFont(Font f):设置绘图字体。
drawRect(int x, int y, int width, int height):绘制矩形。
drawOval(int x, int y, int width, int height):绘制椭圆形。
drawPolygon(int[] xPoints, int[] yPoints, int nPoints):绘制多边形。
drawString(String str, int x, int y):绘制文本。
drawImage(Image img, int x, int y, int width, int height, ImageObserver observer):绘制图像。
setFont(Font f):设置绘图字体。
drawRect(int x, int y, int width, int height):绘制矩形。
drawOval(int x, int y, int width, int height):绘制椭圆形。
drawPolygon(int[] xPoints, int[] yPoints, int nPoints):绘制多边形。
drawString(String str, int x, int y):绘制文本。
drawImage(Image img, int x, int y, int width, int height, ImageObserver observer):绘制图像。
示例:
package demo_1;
import sun.java2d.loops.DrawPath;
import javax.swing.*;
import java.awt.*;
public class text_1 extends JFrame {
public text_1() throws HeadlessException {
initialize();
}
public void initialize(){
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new DrawPath());
setTitle("芜湖");
}
class DrawPath extends JPanel{
public void paint(Graphics g){
g.drawOval(10,10,80,80);
g.drawOval(80,10,80,80);
g.drawOval(150,10,80,80);
g.drawOval(50,70,80,80);
g.drawOval(120,70,80,80);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
import sun.java2d.loops.DrawPath;
import javax.swing.*;
import java.awt.*;
public class text_1 extends JFrame {
public text_1() throws HeadlessException {
initialize();
}
public void initialize(){
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new DrawPath());
setTitle("芜湖");
}
class DrawPath extends JPanel{
public void paint(Graphics g){
g.drawOval(10,10,80,80);
g.drawOval(80,10,80,80);
g.drawOval(150,10,80,80);
g.drawOval(50,70,80,80);
g.drawOval(120,70,80,80);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
运行结果:
Graphics2D类
Java中的Graphics2D类是Graphics类的扩展,提供了更高级的绘图功能和更灵活的绘图控制。Graphics2D类可以控制绘图颜色、线条粗细、填充方式等,并支持更复杂的图形绘制和渲染效果。
示例:
public class Mian{
public static void main(String[] args) {
JFrame jf=new JFrame("wuhu");
jf.setSize(500,500);
jf.add(new MyPanel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
class MyPanel extends JPanel { // 定义一个名为 MyPanel 的类,继承自 JPanel 类,用于绘制图形
public void paintComponent(Graphics g) { // 重写 JPanel 类中的 paintComponent 方法,用于绘制图形
super.paintComponent(g); // 调用父类的 paintComponent 方法,进行默认的界面绘制
// 获取 Graphics 对象并强制转换为 Graphics2D 对象
Graphics2D g2d = (Graphics2D) g;
// 设置绘图颜色为红色
g2d.setColor(Color.RED);
// 设置线条粗细为 2f
g2d.setStroke(new BasicStroke(2f));
// 绘制一个填充的矩形,左上角坐标为 (50,50),宽度为 100,高度为 100,填充颜色为红色
g2d.fillRect(50, 50, 100, 100);
// 设置绘图颜色为黑色
g2d.setColor(Color.BLACK);
// 设置字体为 Arial 字体,字号为 24
g2d.setFont(new Font("Arial", Font.PLAIN, 24));
// 绘制文本,文本内容为 "Hello World!",左上角坐标为 (100,150)
g2d.drawString("Hello World!", 100, 150);
}
}
public static void main(String[] args) {
JFrame jf=new JFrame("wuhu");
jf.setSize(500,500);
jf.add(new MyPanel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
class MyPanel extends JPanel { // 定义一个名为 MyPanel 的类,继承自 JPanel 类,用于绘制图形
public void paintComponent(Graphics g) { // 重写 JPanel 类中的 paintComponent 方法,用于绘制图形
super.paintComponent(g); // 调用父类的 paintComponent 方法,进行默认的界面绘制
// 获取 Graphics 对象并强制转换为 Graphics2D 对象
Graphics2D g2d = (Graphics2D) g;
// 设置绘图颜色为红色
g2d.setColor(Color.RED);
// 设置线条粗细为 2f
g2d.setStroke(new BasicStroke(2f));
// 绘制一个填充的矩形,左上角坐标为 (50,50),宽度为 100,高度为 100,填充颜色为红色
g2d.fillRect(50, 50, 100, 100);
// 设置绘图颜色为黑色
g2d.setColor(Color.BLACK);
// 设置字体为 Arial 字体,字号为 24
g2d.setFont(new Font("Arial", Font.PLAIN, 24));
// 绘制文本,文本内容为 "Hello World!",左上角坐标为 (100,150)
g2d.drawString("Hello World!", 100, 150);
}
}
运行结果:
绘图颜色与画笔属性
Java语言使用Color类封装颜色的各种颜色,并对颜色进行管理。另外,在绘制图形时还可以指定线的粗细和虚实等画笔属性。
设置颜色
使用Color类可以创建任意颜色的对象,不用担心平台是否支持该颜色,因为Java是以跨平台和与硬件无关的方式支持对颜色的管理。
绘图类可以使用setColor()方法设置当前颜色。语法如下:
绘图类可以使用setColor()方法设置当前颜色。语法如下:
setColor(Color color); // 设置当前颜色
Color类提供了多个构造方法,以下为常用的构造方法。
Color类还提供了多个常量表示常用颜色。
设置画笔
默认情况下,Graphics类使用的画笔属性是粗细为1个像素的正方形,而Graphics2D类可以调用setStroke()方法设置画笔的属性,如改变线条的粗细、虚实,定义线段端点的形状,风格等。
格式如下:
setStroke(Stroke stroke);
设置笔刷
setPaint(Paint p): 此方法用于设置画笔的刷子。参数p是一个Paint对象,表示所需的刷子。可以使用Color对象创建Paint对象。
设置粗细
setStroke(Stroke s): 此方法用于设置画笔的线条粗细。参数s是一个Stroke对象,表示所需的线条样式。可以使用BasicStroke类创建不同的线条样式。
绘制文本
在Java中,可以使用Graphics或Graphics2D类来绘制文本。这些类提供了许多方法来设置文本的字体、大小、颜色等属性,以及绘制文本的位置和内容
常用方法
1、setFont(Font f): 此方法用于设置文本的字体。参数f是一个Font对象,表示所需的字体。可以使用Font类的静态常量来创建字体对象,也可以使用构造函数来创建自定义字体对象。
2、setColor(Color c): 此方法用于设置文本的颜色。参数c是一个Color对象,表示所需的颜色。可以使用Color类的静态常量来创建颜色对象,也可以使用构造函数来创建自定义颜色对象。
3、drawString(String str, int x, int y): 此方法用于绘制文本。参数str是要绘制的文本,x和y是文本的左上角坐标。
4、drawChars(char[] chars, int offset, int length, int x, int y): 此方法用于绘制字符数组中的一部分字符。参数chars是字符数组,offset是开始绘制的偏移量,length是绘制的字符数,x和y是文本的左上角坐标。
5、drawString(AttributedString as, float x, float y): 此方法用于绘制具有附加属性的文本。参数as是一个AttributedString对象,表示具有附加属性的文本,x和y是文本的左上角坐标。附加属性可以包括字体、颜色、大小等属性。
2、setColor(Color c): 此方法用于设置文本的颜色。参数c是一个Color对象,表示所需的颜色。可以使用Color类的静态常量来创建颜色对象,也可以使用构造函数来创建自定义颜色对象。
3、drawString(String str, int x, int y): 此方法用于绘制文本。参数str是要绘制的文本,x和y是文本的左上角坐标。
4、drawChars(char[] chars, int offset, int length, int x, int y): 此方法用于绘制字符数组中的一部分字符。参数chars是字符数组,offset是开始绘制的偏移量,length是绘制的字符数,x和y是文本的左上角坐标。
5、drawString(AttributedString as, float x, float y): 此方法用于绘制具有附加属性的文本。参数as是一个AttributedString对象,表示具有附加属性的文本,x和y是文本的左上角坐标。附加属性可以包括字体、颜色、大小等属性。
示例:
package demo_1;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Date;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame{
public text_1() {
setSize(230,140);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭模式
add(new CanvasPanel());//设置窗体面板为绘图面板对象
setTitle("绘图文本");//设置窗体标题
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D) g;
Rectangle2D rect=new Rectangle2D.Double(10, 10, 200, 80);
g2.setColor(Color.CYAN);//设置当前绘图颜色
g2.fill(rect);//填充矩形
Font font=new Font("宋体",Font.BOLD,16);
g2.setColor(Color.BLUE);//设置当前绘图颜色
g2.setFont(font);//设置字体
g2.drawString("现在时间是", 20, 30);//绘制文本
Date date=new Date();
g2.drawString(String.format("%tr", date), 50, 60);//绘制时间文本
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Date;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame{
public text_1() {
setSize(230,140);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭模式
add(new CanvasPanel());//设置窗体面板为绘图面板对象
setTitle("绘图文本");//设置窗体标题
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D) g;
Rectangle2D rect=new Rectangle2D.Double(10, 10, 200, 80);
g2.setColor(Color.CYAN);//设置当前绘图颜色
g2.fill(rect);//填充矩形
Font font=new Font("宋体",Font.BOLD,16);
g2.setColor(Color.BLUE);//设置当前绘图颜色
g2.setFont(font);//设置字体
g2.drawString("现在时间是", 20, 30);//绘制文本
Date date=new Date();
g2.drawString(String.format("%tr", date), 50, 60);//绘制时间文本
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
运行结果:
显示图片
在Java中,可以使用Graphics或Graphics2D类来显示图片。这些类提供了许多方法来加载图片、调整图片大小和位置、绘制图片等。
常用方法
1、ImageIcon(URL): 此构造函数用于创建一个ImageIcon对象,该对象可以加载来自指定URL的图片。
2、ImageIcon(URL, String): 此构造函数用于创建一个ImageIcon对象,并为其提供一个描述性字符串。该对象可以加载来自指定URL的图片。
3、ImageIcon(InputStream): 此构造函数用于创建一个ImageIcon对象,该对象可以加载来自指定输入流的图片。
4、setBounds(int x, int y, int width, int height): 此方法用于设置图片的显示区域。参数x和y是左上角的坐标,width和height是显示区域的宽度和高度。
5、paintIcon(Component c, Graphics g, int x, int y): 此方法用于绘制图片。参数c是包含图片的组件,g是绘图上下文,x和y是左上角的坐标。
2、ImageIcon(URL, String): 此构造函数用于创建一个ImageIcon对象,并为其提供一个描述性字符串。该对象可以加载来自指定URL的图片。
3、ImageIcon(InputStream): 此构造函数用于创建一个ImageIcon对象,该对象可以加载来自指定输入流的图片。
4、setBounds(int x, int y, int width, int height): 此方法用于设置图片的显示区域。参数x和y是左上角的坐标,width和height是显示区域的宽度和高度。
5、paintIcon(Component c, Graphics g, int x, int y): 此方法用于绘制图片。参数c是包含图片的组件,g是绘图上下文,x和y是左上角的坐标。
这些方法可以在Java Swing和Java AWT组件中使用,例如在JFrame、JPanel、JLabel等组件中显示图片。还可以使用其他类和方法来进一步控制图片的样式和布局,例如使用ImageObserver接口来观察图片的加载和绘制过程,使用AffineTransform类来对图片进行变换等。
示例:
package demo_1;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame{
Image img;//展示的图片
public text_1(){
try {
img=ImageIO.read(new File("img/up.png"));//读取图片文件
}catch(IOException e){
e.printStackTrace();
}
setSize(440,300);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭模式
add(new CanvasPanel());//设置窗体面板为绘图面板对象
setTitle("绘制图片");//设置窗体标题
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D)g;
g2.drawImage(img, 100, 0, this );//显示图片
}
}
public static void main(String [] args) {
new text_1().setVisible(true);
}
}
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame{
Image img;//展示的图片
public text_1(){
try {
img=ImageIO.read(new File("img/up.png"));//读取图片文件
}catch(IOException e){
e.printStackTrace();
}
setSize(440,300);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭模式
add(new CanvasPanel());//设置窗体面板为绘图面板对象
setTitle("绘制图片");//设置窗体标题
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D)g;
g2.drawImage(img, 100, 0, this );//显示图片
}
}
public static void main(String [] args) {
new text_1().setVisible(true);
}
}
运行结果:
图像处理
1、放大与缩小
使用了 drawImage() 方法将图片以原始大小显示在窗体中,要想实现图片的放大与缩小,则需要使用他的重载方法。
示例:
package demo_1;
import java.awt.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class text_1 extends JFrame {
Image img;
private int W,H;
private JSlider jSlider;
public text_1() {
try {
img=ImageIO.read(new File("img/down.png"));//读取图片
}catch(IOException e) {
e.printStackTrace();
}
CanvasPanel can=new CanvasPanel();
jSlider=new JSlider();
jSlider.setMaximum(1000);
jSlider.setValue(100);
jSlider.setMinimum(1);
jSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
can.repaint();
}
});
JPanel center=new JPanel();
center.setLayout(new BorderLayout());
center.add(jSlider,BorderLayout.SOUTH);
center.add(can,BorderLayout.CENTER);
setContentPane(center);
setBounds(100,100,800,600);//窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭模式
setTitle("绘制图片");
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
int newW=0,newH=0;
W=img.getWidth(this);//获取图片宽度
H=img.getHeight(this);//获取图片高度
float value=jSlider.getValue();//滑块组件的取值
newW=(int)(W*value/100);//计算图片放大后的宽度
newH=(int)(H*value/100);//计算图片放大后的高度
g.drawImage(img,0,0,newW,newH,this);//绘制指定大小的图片
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
import java.awt.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class text_1 extends JFrame {
Image img;
private int W,H;
private JSlider jSlider;
public text_1() {
try {
img=ImageIO.read(new File("img/down.png"));//读取图片
}catch(IOException e) {
e.printStackTrace();
}
CanvasPanel can=new CanvasPanel();
jSlider=new JSlider();
jSlider.setMaximum(1000);
jSlider.setValue(100);
jSlider.setMinimum(1);
jSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
can.repaint();
}
});
JPanel center=new JPanel();
center.setLayout(new BorderLayout());
center.add(jSlider,BorderLayout.SOUTH);
center.add(can,BorderLayout.CENTER);
setContentPane(center);
setBounds(100,100,800,600);//窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭模式
setTitle("绘制图片");
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
int newW=0,newH=0;
W=img.getWidth(this);//获取图片宽度
H=img.getHeight(this);//获取图片高度
float value=jSlider.getValue();//滑块组件的取值
newW=(int)(W*value/100);//计算图片放大后的宽度
newH=(int)(H*value/100);//计算图片放大后的高度
g.drawImage(img,0,0,newW,newH,this);//绘制指定大小的图片
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
运行结果:
2、图像翻转
图像的翻转需要使用 drawImage() 方法的另一个重载方法。
此方法总是用来非缩放的图像来呈现缩放的矩形,并动态地执行所需要的缩放。此操作不使用缓存的缩放图像。执行图像从源到目标的缩放,要将源矩形的第一个坐标映射到目标矩形的第一个坐标,源矩形的第二个坐标映射到目标矩形的第二个坐标,按需要缩放和翻转子图像,以保持这些映射关系。
示例:
package demo_1;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class text_1 extends JFrame {
private Image img;
private int dx1,dy1,dx2,dy2;
private int sx1,sy1,sx2,sy2;
private int W=300,H=200;
private JButton v=null;
private JButton h=null;
private CanvasPanel canvasPanel=null;
public text_1() {
try {
img=ImageIO.read(new File("img/left.png"));
}catch(IOException e) {
e.printStackTrace();
}
dx2=sx2=W;
dy2=sy2=H;
v=new JButton("垂直旋转");
h=new JButton("水平翻转");
JPanel botton=new JPanel();
botton.add(h);
botton.add(v);
Container c=getContentPane();
c.add(botton,BorderLayout.SOUTH);
canvasPanel =new CanvasPanel();
c.add(canvasPanel,BorderLayout.CENTER);
addListener();
setBounds(100,100,300,260);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("图片翻转");
}
private void addListener() {
v.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sy1=Math.abs(sy1-H);
sy2=Math.abs(sy2-H);
canvasPanel.repaint();
}
});
h.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sx1=Math.abs(sx1-W);
sx2=Math.abs(sx2-W);
canvasPanel.repaint();
}
});
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, this);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class text_1 extends JFrame {
private Image img;
private int dx1,dy1,dx2,dy2;
private int sx1,sy1,sx2,sy2;
private int W=300,H=200;
private JButton v=null;
private JButton h=null;
private CanvasPanel canvasPanel=null;
public text_1() {
try {
img=ImageIO.read(new File("img/left.png"));
}catch(IOException e) {
e.printStackTrace();
}
dx2=sx2=W;
dy2=sy2=H;
v=new JButton("垂直旋转");
h=new JButton("水平翻转");
JPanel botton=new JPanel();
botton.add(h);
botton.add(v);
Container c=getContentPane();
c.add(botton,BorderLayout.SOUTH);
canvasPanel =new CanvasPanel();
c.add(canvasPanel,BorderLayout.CENTER);
addListener();
setBounds(100,100,300,260);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("图片翻转");
}
private void addListener() {
v.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sy1=Math.abs(sy1-H);
sy2=Math.abs(sy2-H);
canvasPanel.repaint();
}
});
h.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sx1=Math.abs(sx1-W);
sx2=Math.abs(sx2-W);
canvasPanel.repaint();
}
});
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, this);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
运行结果:
3、图像旋转
图像旋转需要调用 Graphics2D 类的 rotate()方法,该方法将根据指定的弧度旋转图像。
示例:
package demo_1;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame {
private Image img;
private text_1() {
try {
img=ImageIO.read(new File("img/right.png"));//读取图片
}catch(IOException e) {
e.printStackTrace();
}
setBounds(100,100,400,350);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭模式
setTitle("图片旋转");//设置窗体标题
add(new CanvasPanel());
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D) g;
g2.rotate(Math.toRadians(5));//旋转5°,传入的是弧度值
g2.drawImage(img, 70, 10, 300, 200, this);
g2.rotate(Math.toRadians(5));
g2.drawImage(img, 70, 10, 300, 200, this);
g2.rotate(Math.toRadians(5));
g2.drawImage(img, 70, 10, 300, 200, this);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame {
private Image img;
private text_1() {
try {
img=ImageIO.read(new File("img/right.png"));//读取图片
}catch(IOException e) {
e.printStackTrace();
}
setBounds(100,100,400,350);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭模式
setTitle("图片旋转");//设置窗体标题
add(new CanvasPanel());
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D) g;
g2.rotate(Math.toRadians(5));//旋转5°,传入的是弧度值
g2.drawImage(img, 70, 10, 300, 200, this);
g2.rotate(Math.toRadians(5));
g2.drawImage(img, 70, 10, 300, 200, this);
g2.rotate(Math.toRadians(5));
g2.drawImage(img, 70, 10, 300, 200, this);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
运行结果:
4、图像倾斜
可以使用 Graphics2D 类提供的 shear()方法设置绘图的倾斜方向,从而使图像实现倾斜的效果。
示例:
package demo_1;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame{
private Image img;
public text_1() {
try {
img=ImageIO.read(new File("img/cell.png"));//读取图片
}catch(IOException e) {
e.printStackTrace();
}
setBounds(100,100,400,300);//窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭模式
setTitle("图片倾斜");//窗体标题
add(new CanvasPanel());
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D)g;
g2.shear(0.3,0);//倾斜30%
g2.drawImage(img,0,0,300,200,this);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class text_1 extends JFrame{
private Image img;
public text_1() {
try {
img=ImageIO.read(new File("img/cell.png"));//读取图片
}catch(IOException e) {
e.printStackTrace();
}
setBounds(100,100,400,300);//窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭模式
setTitle("图片倾斜");//窗体标题
add(new CanvasPanel());
}
class CanvasPanel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2=(Graphics2D)g;
g2.shear(0.3,0);//倾斜30%
g2.drawImage(img,0,0,300,200,this);
}
}
public static void main(String[] args) {
new text_1().setVisible(true);
}
}
运行结果:
多线程
前言
Java是支持多线程的编程语言,所谓多线程就是程序能够同时完成多种操作。
计算机完成可以多种操作同时进行,这种思想在Java中被称为并发,而将并发完成的多种操作被称为线程。
计算机完成可以多种操作同时进行,这种思想在Java中被称为并发,而将并发完成的多种操作被称为线程。
线程的创建
在Java中线程的创建一般分为两种方式:
继承Thread类创建
实现Runnable接口创建
实现Runnable接口创建
1、继承Thread类
Java中的Thread类是java.lang包中的核心类,它代表一个线程。它主要用于创建新线程并在其中执行自定义任务。
Thread类的主要特点包括:
1、继承性:Thread类是java.lang.Object的子类,因此可以继承Object类的属性和方法。
2、抽象性:Thread类是一个抽象类,这意味着它不能直接实例化。为了使用Thread类,我们需要创建一个Thread的子类,并重写其run()方法。
3、线程安全性:Thread类是线程安全的,这意味着多个线程可以同时调用Thread类的方法,而不会导致数据不一致或其他并发问题。
4、常用方法:Thread类有许多有用的方法,包括start()(启动线程)、run()(执行线程)、sleep()(使线程休眠)、interrupt()(中断线程)等。
2、抽象性:Thread类是一个抽象类,这意味着它不能直接实例化。为了使用Thread类,我们需要创建一个Thread的子类,并重写其run()方法。
3、线程安全性:Thread类是线程安全的,这意味着多个线程可以同时调用Thread类的方法,而不会导致数据不一致或其他并发问题。
4、常用方法:Thread类有许多有用的方法,包括start()(启动线程)、run()(执行线程)、sleep()(使线程休眠)、interrupt()(中断线程)等。
继承Thread类创建一个新的线程语法:
public class MyThread extends Thread {
@Override
public void run() {
// 在这里编写线程需要执行的代码
System.out.println("My thread is running.");
}
}
@Override
public void run() {
// 在这里编写线程需要执行的代码
System.out.println("My thread is running.");
}
}
完成线程真正功能的代码放置在run方法中执行,该线程在执行完run方法中的代码后就会停止。
示例:
public class demo_1 {
public static void main(String[] args) {
/*
实现方式:1
自定义一个类继承Thread、或者构建Thread对象,重写run方法
重写run方法
启动线程
*/
MyThread t1=new MyThread();
MyThread t2=new MyThread();
// 为线程指定名字
t1.setName("线程一");
t2.setName("线程二");
t1.start(); // 开启线程
t2.start(); // 开启线程
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+ "芜湖");
}
}
}
public static void main(String[] args) {
/*
实现方式:1
自定义一个类继承Thread、或者构建Thread对象,重写run方法
重写run方法
启动线程
*/
MyThread t1=new MyThread();
MyThread t2=new MyThread();
// 为线程指定名字
t1.setName("线程一");
t2.setName("线程二");
t1.start(); // 开启线程
t2.start(); // 开启线程
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+ "芜湖");
}
}
}
2、实现Runnable接口
上一种方式创建线程的方式,是通过继承Thread类的方式创建的,但是Java是只支持单继承的语言,所以如果通过上一个方式创建线程的话,拓展性不太好。因此就可以使用实现接口的方式来创建线程。
实现过程:
1、自定义一个类实现Runnable接口
2、重写run方法,
3、创建自己类的对象,
4、创建Thread对象开启线程
2、重写run方法,
3、创建自己类的对象,
4、创建Thread对象开启线程
示例:
package text_1;
public class demo_2 {
public static void main(String[] args) {
/*
* 第二种实现方式:
* 自定义一个类实现Runnable接口
* 重写run方法,
* 创建自己类的对象,
* 创建Thread对象开启线程
*
* */
MyRun mr=new MyRun();
Thread t1=new Thread(mr);
Thread t2=new Thread(mr);
t1.setName("芜湖");
t2.setName("呀呼");
t1.start();
t2.start();
}
}
class MyRun implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThread(); // 获取当前线程的对象
for (int i = 0; i < 10; i++) {
System.out.println(thread.getName()+ "爱坤");
}
}
}
public class demo_2 {
public static void main(String[] args) {
/*
* 第二种实现方式:
* 自定义一个类实现Runnable接口
* 重写run方法,
* 创建自己类的对象,
* 创建Thread对象开启线程
*
* */
MyRun mr=new MyRun();
Thread t1=new Thread(mr);
Thread t2=new Thread(mr);
t1.setName("芜湖");
t2.setName("呀呼");
t1.start();
t2.start();
}
}
class MyRun implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThread(); // 获取当前线程的对象
for (int i = 0; i < 10; i++) {
System.out.println(thread.getName()+ "爱坤");
}
}
}
只所以能通过这中方式创建线程,是因为Thread类就是Runnable接口的实现类。
且在Thread类中的构造方法中有Runnable的实例,使用这种构造方法就可以将Runnable实例与Thread实例相关联,也就是说,使用这种构造方法后,Thread类调用的run方法就是Runnable中的run方法。
线程的生命周期
操作线程的方法
操作线程的方法有很多,这些方法可以使得线程从某种状态过度到另一种状态。
1、线程的休眠
sleep方法
该方法使得当前线程在指定的时代内不会进入就绪状态。
该方法是被static修饰的,所以可以直接使用类名调用。
该方法是被static修饰的,所以可以直接使用类名调用。
示例:
package text_2;
public class demo_1 {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
mt1.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
// 以毫秒为单位
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("芜湖");
}
}
}
public class demo_1 {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
mt1.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
// 以毫秒为单位
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("芜湖");
}
}
}
2、线程的加入
join方法
在Java多线程编程中,join方法是一个非常重要的概念。它用于确保主线程等待其他线程完成其任务后再继续执行。当一个线程调用另一个线程的join方法时,调用线程会阻塞,直到被调用线程结束执行。
join方法通常在创建线程时使用,以确保主线程不会在子线程完成前结束。这有助于防止数据竞争和其他并发问题。
示例:
package text_2;
public class demo_1 {
public static void main(String[] args) throws InterruptedException {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.setName("wuhu");
mt2.setName("yahu");
mt1.start();
mt1.join();
mt2.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 4; i++) {
try {
// 以毫秒为单位
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName());
}
}
}
public class demo_1 {
public static void main(String[] args) throws InterruptedException {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.setName("wuhu");
mt2.setName("yahu");
mt1.start();
mt1.join();
mt2.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 4; i++) {
try {
// 以毫秒为单位
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName());
}
}
}
3、线程的礼让
在Java中,线程礼让是指在线程A和线程B执行的时候,线程B由于某种原因需要先一步执行,那么可以对线程A执行yield方法,先让线程B执行一步。请注意,这里和join方法不一样,join方法是将CPU资源全都分出,直到线程B执行完,而yield只会让出一步。
4、线程的优先级
在Java中,线程的优先级是一个整数,范围从1(最低优先级)到10(最高优先级)。默认情况下,新创建的线程的优先级为5。线程优先级越小,线程越优先被执行;线程优先级越大,线程越后被执行。可以通过Thread类的setPriority(int)方法来设置线程的优先级。
请注意,如果优先级相同的线程同时存在,那么会按照提交顺序(也就是代码编写顺序)执行的方式。
package text_2;
public class demo_2 {
public static void main(String[] args) {
/*
* 设置优先级 :setPriority()
* 获取优先级 : get
* 守护线程 :setDaemon(boolean)
* 细节:守护线程会在所有非守护线程结束后结束
* */
// System.out.println(Thread.currentThread().getPriority());
MyThread_2 mt1 = new MyThread_2();
MyThread_2 mt2 = new MyThread_2();
mt1.setName("芜湖");
mt2.setName("呀呼");
System.out.println(mt1.getPriority()); // 获取当前优先级
mt1.setPriority(10);
System.out.println(mt1.getPriority()); // 获取当前优先级
// MyThread_3 mt3 = new MyThread_3();
// mt3.setName("run");
// mt3.setDaemon(true);
mt1.start();
mt2.start();
}
}
class MyThread_2 extends Thread{
@Override
public void run() {
Thread thread = Thread.currentThread();
for (int i = 0; i < 10; i++) {
System.out.println(thread.getName()+"i");
}
}
}
class MyThread_3 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+""+i);
}
}
}
public class demo_2 {
public static void main(String[] args) {
/*
* 设置优先级 :setPriority()
* 获取优先级 : get
* 守护线程 :setDaemon(boolean)
* 细节:守护线程会在所有非守护线程结束后结束
* */
// System.out.println(Thread.currentThread().getPriority());
MyThread_2 mt1 = new MyThread_2();
MyThread_2 mt2 = new MyThread_2();
mt1.setName("芜湖");
mt2.setName("呀呼");
System.out.println(mt1.getPriority()); // 获取当前优先级
mt1.setPriority(10);
System.out.println(mt1.getPriority()); // 获取当前优先级
// MyThread_3 mt3 = new MyThread_3();
// mt3.setName("run");
// mt3.setDaemon(true);
mt1.start();
mt2.start();
}
}
class MyThread_2 extends Thread{
@Override
public void run() {
Thread thread = Thread.currentThread();
for (int i = 0; i < 10; i++) {
System.out.println(thread.getName()+"i");
}
}
}
class MyThread_3 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+""+i);
}
}
}
线程同步
Java线程同步是一个非常重要的概念,主要用于解决多线程并发控制问题。当多个线程同时操作一个可共享的资源变量时,可能会产生数据不准确和相互冲突的问题。为了解决这些问题,Java提供了多种同步机制,包括synchronized关键字、Lock接口和AtomicInteger类等。
其中,synchronized关键字是最基本的同步机制,可以用于方法或代码块的同步。当一个线程在执行一个synchronized方法时,其他试图访问该对象的线程将被阻塞,直到第一个线程执行完毕。这样可以确保同一时间只有一个线程可以访问共享资源,避免了数据不一致和程序异常的问题。
一般情况:窗口售票
package text_3;
public class demo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class MyThread extends Thread {
static int ticket = 0;
@Override
public void run() {
while (true) {
// 同步线程:线程锁(锁对象) 需要注意的是锁对象一定是要唯一的
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket < 100) {
++ticket;
System.out.println(getName() + "正在卖第" + ticket + "张票");
} else {
break;
}
}
}
}
public class demo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class MyThread extends Thread {
static int ticket = 0;
@Override
public void run() {
while (true) {
// 同步线程:线程锁(锁对象) 需要注意的是锁对象一定是要唯一的
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket < 100) {
++ticket;
System.out.println(getName() + "正在卖第" + ticket + "张票");
} else {
break;
}
}
}
}
运行结果:
通过运行结果,我们可以看出没有加线程同步的情况,多个线程对同一资源的访问,因为系统cpu轮转的情况,某一线程可能已经售出了某张票,但是另一个线程也在售出这张票,所以导致了重复售出的情况。
线程同步机制
线程同步机制是Java多线程编程中的重要概念,主要用于解决多线程并发控制问题。线程同步机制可以让多个线程按照一定的顺序执行,避免出现数据不一致和相互冲突的问题。Java中实现线程同步的方式有多种,包括synchronized关键字、Lock接口、信号量Semaphore、倒计时门闩CountDownLatch、循环栅栏CyclicBarrier和闭包等。
其中,synchronized关键字是最基本的线程同步机制之一,可以用于方法或代码块的同步。当一个线程在执行一个synchronized方法时,其他试图访问该对象的线程将被阻塞,直到第一个线程执行完毕。这样可以确保同一时间只有一个线程可以访问共享资源,避免了数据不一致和程序异常的问题。
需要注意的是,使用synchronized块进行同步线程时,同步代码块的对象一定需要是唯一的。
同步代码块改进
package text_3;
public class demo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class MyThread extends Thread {
static int ticket = 0;
@Override
public void run() {
while (true) {
// 同步线程:线程锁(锁对象) 需要注意的是锁对象一定是要唯一的
synchronized (MyThread.class) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket < 100) {
++ticket;
System.out.println(getName() + "正在卖第" + ticket + "张票");
} else {
break;
}
}
}
}
}
public class demo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class MyThread extends Thread {
static int ticket = 0;
@Override
public void run() {
while (true) {
// 同步线程:线程锁(锁对象) 需要注意的是锁对象一定是要唯一的
synchronized (MyThread.class) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket < 100) {
++ticket;
System.out.println(getName() + "正在卖第" + ticket + "张票");
} else {
break;
}
}
}
}
}
运行结果: 杜绝了重复票的情况
网络通信
网络程序设计基础
网络程序设计编写的是与其他计算机进行通信的程序。Java 已经将网络程序所需要的元素封
装成不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络支持,也可
以编写出高质量的网络通信程序。
装成不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络支持,也可
以编写出高质量的网络通信程序。
局域网与互联网
为了实现两台计算机的通信,必须用一个网络线路连接两台算计。
服务器是指提供信息的计算机程序
客户机是指请求信息的计算机或程序
网络用于连接服务器与客户机,实现两者的相互通信。但是,有时在某个网络中很难将服务器与客户机区分开。局域网 (LAN) 是一群通过一定形式连接起来的计算机,它可以由两台计算机组成,也可以由同一区域内地上千台计算机组成。将 LAN 延伸到更大的范围,这样的网络成为广域网(WAN)。互联网是由无数的 LAN 和 WAN 组成的。
客户机是指请求信息的计算机或程序
网络用于连接服务器与客户机,实现两者的相互通信。但是,有时在某个网络中很难将服务器与客户机区分开。局域网 (LAN) 是一群通过一定形式连接起来的计算机,它可以由两台计算机组成,也可以由同一区域内地上千台计算机组成。将 LAN 延伸到更大的范围,这样的网络成为广域网(WAN)。互联网是由无数的 LAN 和 WAN 组成的。
网络协议
网络协议规定了计算机之间连接的物理、机械(网络与网卡的连接规定)、电气(有效的电平范围)等特征,计算机之间的相互寻址规则,数据发送冲突的解决方式,长数据如何分段传送与接收等内容。
IP协议
IP 是 Internet Protocol 的简称,是一种网络协议。Internet 网络采用的协议是 TCP/IP协议。TCP/IP 模式是一种层次结构,共分为 4 层,分别为应用层、传输层、互联网层和网络层。各层实现特定的功能,提供特定服务和访问接口,并具有相对的独立性。
TCP/IP 协议
在TCP/IP 协议栈中有两个高级协议 :
传输控制协议(TCP)
用户数据报协议(UDP)
用户数据报协议(UDP)
端口域套接字
一般而言,一台计算机只有单一的连接到网络的物理连接,所以的数据读通过此连接对内、
对外送达特定的计算机,这就是端口。网络程序设计的端口(port)并非真实的物理存在,而是一个假想的连接装置。
网络程序中的套接字(Socket)用于将应用程序 与端口连接起来。
对外送达特定的计算机,这就是端口。网络程序设计的端口(port)并非真实的物理存在,而是一个假想的连接装置。
网络程序中的套接字(Socket)用于将应用程序 与端口连接起来。
套接字是一个假想的连接装置,就像插座一样可以连接电器与电线。
TCP 程序
TCP 网络程序设计是利用 Socket 类编写通信程序。利用 TCP 协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个称为客户机程序,两者的功能和编写方法大不一样。
InterAddress 类
java.net 包中的 InterAddress 类是与 IP 地址相关的类,利用该类可以获取 IP 地址、主机地址等信息。
示例:
import java.net.*;
public class Demo21_1 {
public static void main(String[] args) {
InetAddress ip;//创建InetAddress对象
try {//捕捉异常
ip=InetAddress.getLocalHost();//实例化对象
String ming=ip.getHostName();//获取本机名
String dizi=ip.getHostAddress();//获取本机地址
System.out.println("本机名:"+ming);//输出本机名
System.out.println("本机IP地址:"+dizi);//将本机IP地址输出
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();//输出异常
}
}
}
public class Demo21_1 {
public static void main(String[] args) {
InetAddress ip;//创建InetAddress对象
try {//捕捉异常
ip=InetAddress.getLocalHost();//实例化对象
String ming=ip.getHostName();//获取本机名
String dizi=ip.getHostAddress();//获取本机地址
System.out.println("本机名:"+ming);//输出本机名
System.out.println("本机IP地址:"+dizi);//将本机IP地址输出
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();//输出异常
}
}
}
ServerSocket 类
java.net 包中的 ServerSocket 类用于表示服务器套接字,其主要功能是等待来自网络上的
“请求”,它可以通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字。如果
多台客户机同时提供出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出
一个套接字,与服务器新建的套接字连接起来。若请求连接大于最大容纳数,则多出的连接请求被
拒绝。队列的默认大小是 50。
“请求”,它可以通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字。如果
多台客户机同时提供出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出
一个套接字,与服务器新建的套接字连接起来。若请求连接大于最大容纳数,则多出的连接请求被
拒绝。队列的默认大小是 50。
ServerSocket 类的构造方法通常会抛出 IOException 异常,具体有以下几种形式:
ServerSocket(): 创建非绑定服务器套接字。
ServerSocket(int port): 创建绑定到特定端口的服务器套接字。
ServerSocket(int port,int backlog): 利用指定的 backlog 创建服务器套接字,并将其绑定到指定的本地端口号上。
ServerSocket(int port,int backlog,InetAddress bindAddress): 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。这种情况适用于计算机上有多块网卡和多个IP 地址的情况,用户可以明确规定 ServerSocket 在哪块网卡或哪个 IP 地址上等待客户的连接请求。
ServerSocket(int port): 创建绑定到特定端口的服务器套接字。
ServerSocket(int port,int backlog): 利用指定的 backlog 创建服务器套接字,并将其绑定到指定的本地端口号上。
ServerSocket(int port,int backlog,InetAddress bindAddress): 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。这种情况适用于计算机上有多块网卡和多个IP 地址的情况,用户可以明确规定 ServerSocket 在哪块网卡或哪个 IP 地址上等待客户的连接请求。
示例:创建 TCP/IP 协议服务器,本实例是一个 TCP服务器端程序。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Demo21_2 {
private ServerSocket s;//服务器套接字
private Socket sk;//客户端套接字
void start() {//启动服务器
try {
s=new ServerSocket(8998);//服务器启用8998端口
System.out.println("服务器套接字已经创建成功");
while(true) {
System.out.println("等待客户机的接入");
sk=s.accept();//监听客户机的连接
BufferedReader r=new BufferedReader(new InputStreamReader(sk.getInputStream()));
while(true) {//循环接收信息
String m=r.readLine();//读取一行文本
if("退出".equals(m)) {//如果客户机发来的内容为退出
System.out.println("客户机退出");
break;//停止接收信息
}
System.out.println("客户机"+m);
}
r.close();//关闭流
sk.close();//关闭套接字
}
}catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo21_2 tcp=new Demo21_2();
tcp.start();//启动服务器
}
}
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Demo21_2 {
private ServerSocket s;//服务器套接字
private Socket sk;//客户端套接字
void start() {//启动服务器
try {
s=new ServerSocket(8998);//服务器启用8998端口
System.out.println("服务器套接字已经创建成功");
while(true) {
System.out.println("等待客户机的接入");
sk=s.accept();//监听客户机的连接
BufferedReader r=new BufferedReader(new InputStreamReader(sk.getInputStream()));
while(true) {//循环接收信息
String m=r.readLine();//读取一行文本
if("退出".equals(m)) {//如果客户机发来的内容为退出
System.out.println("客户机退出");
break;//停止接收信息
}
System.out.println("客户机"+m);
}
r.close();//关闭流
sk.close();//关闭套接字
}
}catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo21_2 tcp=new Demo21_2();
tcp.start();//启动服务器
}
}
服务器端
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Demo21_2_2 extends JFrame{
private PrintWriter w;//字符输出流
Socket s;//客户端套接字
private JTextArea area=new JTextArea();//文本域
private JTextField text=new JTextField();//文本框
public Demo21_2_2() {
setTitle("向服务器送数据");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c=getContentPane();//主容器
JScrollPane scrollPane=new JScrollPane(area);//滚动面板
getContentPane().add(scrollPane,BorderLayout.CENTER);
c.add(text,"South");//将文本框放到窗体下部
text.addActionListener(new ActionListener() {//文本框触发回车事件
public void actionPerformed(ActionEvent e) {
w.println(text.getText().trim());//将文本框的信息写入流
area.append(text.getText()+"\n");//将文本框的信息显示在文本域中
text.setText("");//将文本框清空
}
});
}
public void c() {//连接服务器方法
area.append("尝试连接\n");//文本域中提示信息
try {
s=new Socket("127.0.0.1",8998);//连接本地计算机的端口8998
w=new PrintWriter(s.getOutputStream(),true);
area.append("完成连接\n");
}catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo21_2_2 c=new Demo21_2_2();
c.setSize(200, 200);//窗体大小
c.setVisible(true);//是否显示
c.c();//连接服务器
}
}
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Demo21_2_2 extends JFrame{
private PrintWriter w;//字符输出流
Socket s;//客户端套接字
private JTextArea area=new JTextArea();//文本域
private JTextField text=new JTextField();//文本框
public Demo21_2_2() {
setTitle("向服务器送数据");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c=getContentPane();//主容器
JScrollPane scrollPane=new JScrollPane(area);//滚动面板
getContentPane().add(scrollPane,BorderLayout.CENTER);
c.add(text,"South");//将文本框放到窗体下部
text.addActionListener(new ActionListener() {//文本框触发回车事件
public void actionPerformed(ActionEvent e) {
w.println(text.getText().trim());//将文本框的信息写入流
area.append(text.getText()+"\n");//将文本框的信息显示在文本域中
text.setText("");//将文本框清空
}
});
}
public void c() {//连接服务器方法
area.append("尝试连接\n");//文本域中提示信息
try {
s=new Socket("127.0.0.1",8998);//连接本地计算机的端口8998
w=new PrintWriter(s.getOutputStream(),true);
area.append("完成连接\n");
}catch(IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo21_2_2 c=new Demo21_2_2();
c.setSize(200, 200);//窗体大小
c.setVisible(true);//是否显示
c.c();//连接服务器
}
}
UDP 程序
用户数据报协议 (UDP) 是网络信息传输的另一种形式。基于 UDP 的通信和基于 TCP 的通信基于 UDP的信息传递更快,但不提供可靠性保证。使用 UDP 传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送相同。虽然 UDP 是一种不可靠的员议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用 UDP。
基于 UDP 通信的基本模式如下:
1、将数据打包 (称为数据包),然后将数据包发往目的地。
2、接收别人发来的数据包,然后查看数据包。
2、接收别人发来的数据包,然后查看数据包。
发送数据包的步骤如下:
1、使用 DatagramSocket() 创建一个数据包套接字。
使用 DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)创建要发送的
数据包。
2、使用 DatagramSocket 类的 send() 方法发送数据包。
使用 DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)创建要发送的
数据包。
2、使用 DatagramSocket 类的 send() 方法发送数据包。
接收数据包的步骤如下:
1、使用 DatagramSocket(int port) 创建数据包套接字,绑定到指定的端口。
2、使用 DatagramPacket(byte[]buf,int length) 创建字节数组来接收数据包。
3、使用 DatagramPacket 类的 receive() 方法接收UDP包。
2、使用 DatagramPacket(byte[]buf,int length) 创建字节数组来接收数据包。
3、使用 DatagramPacket 类的 receive() 方法接收UDP包。
DatagramPacket 类
java.net 包的 DatagramPacket 类用来表示数据包。DatagramPacket 类的构造方法如下:
第一种构造方法在创建 DatagramPacket 对象时,指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和口、在发送数据时,必须指定接收方的 Socket 地址和端口号,因此使用第二种构造方法可创建发送数据的 DamgramPacket 对象。
DatagramSocket 类
javanet 包中的 DatagramSocket 类用于表示发送和接收数据包的套接字。该类的构造方法如下:
第一种构造方法创建 DatagramSocket 对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。第二种构造方法创建 DatagramSocket 对象,创建数据报套字,并将其绑定到本地主机的指定端口上。第三种构造方法创建 DatagramSocket 对象,创建数据报套接字,并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个 IP 地址的情况。
示例:创建 UDP 协议广播电台程序,广播主机程序不断地向外播出信息。
发送数据部分:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class Demo21_3 extends Thread{
String weather="节目预报:八点有大型晚会,请收听";
int port=9898;
InetAddress iaddress=null;
MulticastSocket socket=null;
Demo21_3(){
try {
iaddress=InetAddress.getByName("224.225.10.1");
socket=new MulticastSocket(port);
socket.setTimeToLive(1);
socket.joinGroup(iaddress);
}catch(IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
DatagramPacket packet=null;
byte date[]=weather.getBytes();
packet=new DatagramPacket(date,date.length,iaddress,port);
System.out.println(weather);
try {
socket.send(packet);
sleep(3000);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Demo21_3 w=new Demo21_3();
w.start();
}
}
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class Demo21_3 extends Thread{
String weather="节目预报:八点有大型晚会,请收听";
int port=9898;
InetAddress iaddress=null;
MulticastSocket socket=null;
Demo21_3(){
try {
iaddress=InetAddress.getByName("224.225.10.1");
socket=new MulticastSocket(port);
socket.setTimeToLive(1);
socket.joinGroup(iaddress);
}catch(IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
DatagramPacket packet=null;
byte date[]=weather.getBytes();
packet=new DatagramPacket(date,date.length,iaddress,port);
System.out.println(weather);
try {
socket.send(packet);
sleep(3000);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Demo21_3 w=new Demo21_3();
w.start();
}
}
接收数据部分:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
public class Demo21_3_2 extends JFrame implements Runnable,ActionListener{
int port=9898;
InetAddress group=null;
MulticastSocket socket=null;
JButton inceBth=new JButton("开始接收");
JButton stopBth=new JButton("停止接收");
JTextArea inceAr=new JTextArea(10,10);
JTextArea inced=new JTextArea(10,10);
Thread thread;
boolean stop=false;
public Demo21_3_2() {
setTitle("广播数据");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
thread=new Thread(this);
inceBth.addActionListener(this);
stopBth.addActionListener(this);
inceAr.setForeground(Color.blue);
JPanel north=new JPanel();
north.add(inceBth);
north.add(stopBth);
add(north,BorderLayout.NORTH);
JPanel center=new JPanel();
center.setLayout(new GridLayout(1,2));
center.add(inceAr);
center.add(inced);
add(center,BorderLayout.CENTER);
validate();
try {
group=InetAddress.getByName("224.225.10.1");
socket=new MulticastSocket(port);
socket.joinGroup(group);
}catch(IOException e) {
e.printStackTrace();
}
setBounds(100,50,360,380);
setVisible(true);
}
public void run() {
while(!stop) {
byte date[] = new byte[1024];
DatagramPacket packet=null;
packet=new DatagramPacket(date,date.length,group,port);
try {
socket.receive(packet);
String message=new String(packet.getData(),0,packet.getLength());
inceAr.setText("正在接收内容:\n"+message);
inced.append(message+"\n");
}catch(IOException e) {
e.printStackTrace();
}
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==inceBth) {
inceBth.setBackground(Color.red);
stopBth.setBackground(Color.yellow);
if(!(thread.isAlive())) {
thread=new Thread(this);
}
thread.start();
stop=false;
}
if(e.getSource()==stopBth) {
inceBth.setBackground(Color.yellow);
stopBth.setBackground(Color.red);
stop=true;
}
}
public static void main(String[]args) {
Demo21_3_2 rec=new Demo21_3_2();
rec.setSize(460, 200);
}
}
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
public class Demo21_3_2 extends JFrame implements Runnable,ActionListener{
int port=9898;
InetAddress group=null;
MulticastSocket socket=null;
JButton inceBth=new JButton("开始接收");
JButton stopBth=new JButton("停止接收");
JTextArea inceAr=new JTextArea(10,10);
JTextArea inced=new JTextArea(10,10);
Thread thread;
boolean stop=false;
public Demo21_3_2() {
setTitle("广播数据");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
thread=new Thread(this);
inceBth.addActionListener(this);
stopBth.addActionListener(this);
inceAr.setForeground(Color.blue);
JPanel north=new JPanel();
north.add(inceBth);
north.add(stopBth);
add(north,BorderLayout.NORTH);
JPanel center=new JPanel();
center.setLayout(new GridLayout(1,2));
center.add(inceAr);
center.add(inced);
add(center,BorderLayout.CENTER);
validate();
try {
group=InetAddress.getByName("224.225.10.1");
socket=new MulticastSocket(port);
socket.joinGroup(group);
}catch(IOException e) {
e.printStackTrace();
}
setBounds(100,50,360,380);
setVisible(true);
}
public void run() {
while(!stop) {
byte date[] = new byte[1024];
DatagramPacket packet=null;
packet=new DatagramPacket(date,date.length,group,port);
try {
socket.receive(packet);
String message=new String(packet.getData(),0,packet.getLength());
inceAr.setText("正在接收内容:\n"+message);
inced.append(message+"\n");
}catch(IOException e) {
e.printStackTrace();
}
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==inceBth) {
inceBth.setBackground(Color.red);
stopBth.setBackground(Color.yellow);
if(!(thread.isAlive())) {
thread=new Thread(this);
}
thread.start();
stop=false;
}
if(e.getSource()==stopBth) {
inceBth.setBackground(Color.yellow);
stopBth.setBackground(Color.red);
stop=true;
}
}
public static void main(String[]args) {
Demo21_3_2 rec=new Demo21_3_2();
rec.setSize(460, 200);
}
}
收藏
0 条评论
下一页