黑马程序员—java基础之GUI与前期补充
------- android培训、java培训、期待与您交流! ----------
成功者永不放弃,放弃者绝不成功,因此,我们要坚持下去.
前期帖子补充:
什么是API
API全名:ApplicationProgramming Interface,API是应用程序编程接口,指一些预先定义好的类。
例如我们想要一台电脑,并不需要自己生产每个零件,只要从各个厂商买到组装电脑的零件就可以,然后根据说明书学会使用,将零件安装在一起就得到了电脑。电脑就像是我们要的程序,而零件就是API,说明书就是帮助文档
Java API
Java API就是Sun公司提供给我们使用的类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用。
我们可以通过查帮助文档来了解Java提供的API如何使用
Java中常用API
String类
对字符串进行操作通常我们使用String类,相关的还有StringBuffer和StringBuilder
集合类
集合是一种容器,用来存取对象(Collection、Map)
包装类
Java定义了一组包装类对基本数据类型进行了包装(Integer、Double、Boolean)
时间类
Java定义了一些类方便用户对时间、日期进行处理(Date、Calendar)
系统类
Java定义了一些类针对系统进行操作(System、Runtime)
IO流
Java定义了一些类对数据传输进行了封装(输入输出流、File文件对象)
Socket
Java定义了一些类方便用户进行网络编程(Socket、DatagramSocket)
线程间的通信
1)线程间通信:
其实就是多个线程在操作同一个资源,但操作的动作不同。
(2)等待唤醒机制:
<1>wait(),notify(),notifyAll()都使用在同步中,因为只有同步才具有锁,所以要对持有锁的
线程操作。阻塞的线程都放在线程池中。notify唤醒的都是线程池中的线程,通常是线程池中的第一个线程。notifyAll唤醒线程池中的所有阻塞线程。
注意:优化后锁都是Res类中的this,时刻记住,wait()、notify、notifyAll()方法操作的是以这些方法所属对象为锁的线程
<2>这些用来操作线程的方法为什么定义在Object类中?
a.这些方法存在于同步中。
b.使用这些方法时必须要标识所属的同步的锁。
c.等待和唤醒必须是同一个锁。
d.锁可以是任意对象,所以任意对象调用的方法一定定义在Object中。
(3)wait(),sleep()的区别:
wait():释放资源,释放锁。
sleep():释放资源,不释放锁。
JDK1.5中提供了多线程的升级解决方案:将同步synchronized替换成Lock操作;将Objec(监视器对象)的wait,notify,notifyAll,替换成Condition对象的相应操作,Condition对象可以通过Lock锁进行获取。这是一种显式的锁机制和显式的锁对象上的等待唤醒操作机制,它把等待唤醒动作封装成了Condition类对象,让一个锁可以对应多个Condition对象(监视器对象),即一个锁可以对应多组wait-notify。
停止线程:
(1)stop方法已经过时。
(2)如何停止线程?
只有一种,就是让run方法结束,开启多线程运行,运行代码通常是循环结构。只要控制住循环,
就可以让run方法结束,也就是线程结束。
(3)特殊情况:
<1>当线程处于了冻结状态,就不会读到标记,那么线程就不会结束。
<2>当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除,强制让线程恢复
到运行状态中来,这样就可以操作标记让线程结束。
(4)Thread类提供该方法:interrupt()
join方法:
join://抢夺CPU执行权
public final void join()
throws InterruptedException
等待该线程终止
(1)当A线程执行到了B线程的join()方法时,A就会等待,等B线程都执行完,A才会执行。
(2)join可以用来临时加入线程执行。
yield:临时停止
public static void yield()
暂停当前正在执行的线程对象,并执行其他线程。yield可稍微减缓线程的运行,
使线程达到接*均运行的效果。
通信练习:
package com.itheima.thread;
public classDemo4_Notify{
public static void main(String[] args) {
final Demo4_Printer p = new Demo4_Printer();
new Thread() {
public void run() {
while (true)
try {
p.print1();
}catch(InterruptedExceptione) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
while (true)
try {
p.print2();
}catch(InterruptedExceptione) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
while (true)
try {
p.print3();
}catch(InterruptedExceptione) {
e.printStackTrace();
}
}
}.start();
}
}
class Demo4_Printer{
private int flag = 1; // 标记, 用来标记应该执行哪个方法
public synchronized void print1() throws InterruptedException {
if (flag != 1) { // 如果不该1
wait(); // 等待(让出CPU),等到notify()为止
}
System.out.print("传");
System.out.print("智");
System.out.print("播");
System.out.print("客");
System.out.print("\r\n");
flag = 2; // 1结束后轮到2了
notifyAll(); // 通知
}
public synchronized void print2() throws InterruptedException {
while (flag != 2) { // 如果不该2
wait(); // 等待(让出CPU),等到notify()为止
}
System.out.print("黑");
System.out.print("马");
System.out.print("程");
System.out.print("序");
System.out.print("员");
System.out.print("\r\n");
flag = 3; // 2结束后轮到3了
notifyAll(); // 通知
}
public synchronized void print3() throws InterruptedException {
while (flag != 3) { // 如果不该3
wait(); // 等待(让出CPU),等到notify()为止
}
System.out.print("C");
System.out.print("S");
System.out.print("D");
System.out.print("N");
System.out.print("\r\n");
flag = 1; // 3结束后轮到1了
notifyAll(); // 通知
}
}
1.5之后的通信代码
Jdk1.5之后有了完善的通信方式:
package com.itheima.thread.jdk5;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public classDemo4_Notify{
public static void main(String[] args) {
final Demo4_Printer p = new Demo4_Printer();
new Thread() {
public void run() {
while (true)
try {
p.print1();
}catch(InterruptedExceptione) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
while (true)
try {
p.print2();
}catch(InterruptedExceptione) {
e.printStackTrace();
}
}
}.start();
new Thread(new Runnable(){
public void run() {
while (true)
try {
p.print3();
}catch(InterruptedExceptione) {
e.printStackTrace();
}
}
}).start();
}
}
class Demo4_Printer{
private int flag = 1; // 标记, 用来标记应该执行哪个方法
ReentrantLock lock= newReentrantLock();
private Conditionc1 = lock.newCondition();
private Conditionc2 = lock.newCondition();
private Conditionc3 = lock.newCondition();
// privateCondition c4 = lock.newCondition();
public void print1() throws InterruptedException {
lock.lock();
if (flag != 1) // 如果不该1
c1.await(); // 等待(让出CPU),等到notify()为止
System.out.print("传");
System.out.print("智");
System.out.print("播");
System.out.print("客");
System.out.print("\r\n");
flag = 2; // 1结束后轮到2了
c2.signal(); // 通知
lock.unlock();
}
public void print2() throws InterruptedException {
lock.lock();
if (flag != 2) { // 如果不该2
c2.await(); // 等待(让出CPU),等到notify()为止
}
System.out.print("黑");
System.out.print("马");
System.out.print("程");
System.out.print("序");
System.out.print("员");
System.out.println();
flag = 3; // 2结束后轮到1了
c3.signal(); // 通知
lock.unlock();
}
public void print3() throws InterruptedException {
lock.lock();
if (flag != 3) {
c3.await();
}
System.out.print("C");
System.out.print("S");
System.out.print("D");
System.out.print("N");
System.out.print("\r\n");
flag = 1;
c1.signal();
lock.unlock();
}
}
GUI
GUI是GraphicalUser Interface的缩写,图形化用户界面
awt和swing
Java为GUI提供的对象都存在java.awt,javax.swing两个包中
awt依赖于本地系统平台,如颜色样式显示
swing跨平台
组件与容器
组件Component,是GUI图形界面的组成单元。
容器Container,可以存放组件,也可以存放容器
布局管理
FlowLayout(流式布局管理器)
从左到右的顺序排列。
BorderLayout(边界布局管理器)
东,南,西,北,中
GridLayout(网格布局管理器)
规则的矩阵
CardLayout(卡片布局管理器)
选项卡
GridBagLayout(网格包布局管理器)
窗体的建立:
非规则的矩阵
窗体中可以存放各种组件,所以窗体是容器Container。创建时我们使用的是它的子类
Container的常用子类有两个,Window和Panel。Window是我们常用的窗体,Panel是用来布局的不可见的。
Window也有两个常用子类,Frame和Dialog。Frame是我们常用的带有标题和边框的顶层窗口,Dialog是对话框。
所有AWT包中的类都会运行在AWT线程上
事件处理
事件:用户对组件的一个操作。
事件源:发生事件的组件。
监听器:我们需要处理某个事件,就需要在发生事件的组件上添加监听器,也就是java.awt.event包中XxxListener接口的子类。
事件处理器:监听器中的方法。监听器被添加在组件上之后,组件上发生了对应事件就会执行指定方法
常用事件分类
窗体事件,WindowEvent,窗体打开、关闭、正在关闭、激活、最小化等。
鼠标事件,MouseEvent,鼠标按下、抬起、进入、移出等。
键盘事件,KeyEvent,键盘按下、抬起等。
动作事件,ActionEvent,在某一组件上发生了定义好的动作,例如按钮上鼠标点击或按空格,菜单上鼠标点击或按回车等
Adapter
通常Listener接口中都是有多个抽象方法的,而我们使用的时候有可能不会全部需要,如果定义子类实现接口那么就必须重写所有方法,这是比较麻烦的。Java中为我们提供了一些抽象的实现类,在类中对接口的抽象方法进行了空的实现,我们再定义监听器时只要继承这些抽象类就可以,这样那些不需要的方法就可以不再去重写了
理清思路, 主要还是要运用.
练习及代码分享:
1.创建一个GUI程序:
package com.itheima.gui;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public classDemo1_Frame{
public static void main(String[] args) {
Frame frame = newFrame("这是我的第一个GUI程序"); // 创建一个窗口
frame.setSize(400,300); // 设置大小
frame.setLocation(800,100); // 设置位置
frame.setLayout(newFlowLayout()); // 设置布局方式
Button button = newButton("退出"); // 创建一个按钮
frame.add(button); // 向frame中添加按钮
frame.addWindowListener(newMyWindowListener()); // 给窗口添加一个窗体监听器
// button.addMouseListener(newMyMouseListener()); //给按钮添加鼠标监听器
// button.addKeyListener(newMyKeyListener()); //给按钮添加键盘监听器
button.addActionListener(newMyActionListener()); // 给按钮添加动作监听器(默认事件就是鼠标点击和键盘上空格键抬起)
frame.setVisible(true); // 设置可见
}
}
class MyWindowListenerextendsWindowAdapter/*implements WindowListener*/ { // 定义类实现监听器接口或者继承适配器
public void windowClosing(WindowEvent e) { // 实现事件处理方法
// Frameframe = (Frame) e.getSource(); //获取事件源
// frame.setVisible(false); //隐藏, 暂时不显示
// frame.dispose(); //摧毁, 释放资源
System.exit(0); // 退出程序
}
}
class MyMouseListenerextendsMouseAdapter/*implements MouseListener*/ {
public void mouseClicked(MouseEvent e) {
System.exit(0);
}
}
class MyKeyListenerextendsKeyAdapter/*implements KeyListener*/ {
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() ==KeyEvent.VK_SPACE) // 如果按下的是空格键
System.exit(0);
}
}
class MyActionListenerimplementsActionListener {// 由于只有1个方法,没有适配器
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
2. 简单事件处理
做一个窗体
要求,点击X 按钮时会弹出新窗口
具备两个按钮,一个为关闭当前,点击关闭当前按钮,
一个为关闭所有,点击关闭所有窗口
package com.itheima.gui.exercise;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public classExercise1{
private static int x = 100;
private static int y = 100;
public static void main(String[] args) {
final Frame frame = new Frame("练习1");// 创建窗体
frame.setSize(400,300); // 设置大小
frame.setLocation(x,y); // 设置位置
frame.setLayout(newFlowLayout()); //设置布局
Button currentButton = new Button("关闭当前"); // 创建按钮(关闭当前)
Button allButton = new Button("关闭所有"); // 创建按钮(关闭所有)
frame.add(currentButton); // 把按钮添加到窗体
frame.add(allButton);
frame.addWindowListener(newWindowAdapter(){ // 给窗体添加监听器
public void windowClosing(WindowEvent e) {
Point p = frame.getLocation(); // 获取当前位置
x = p.x + 30; // 改变下次弹出的x轴
y = p.y + 30; // 改变下次弹出的y轴
main(null); // 窗体关闭的时候,弹出相同的窗体
}
});
currentButton.addActionListener(new ActionListener() { // 给按钮(关闭当前)添加监听器
public void actionPerformed(ActionEvent e) {
Button button = (Button) e.getSource(); // 获取事件源(发生事件的对象)
Frame frame = (Frame) button.getParent(); // 获取按钮的父级容器(Frame)
frame.dispose(); // 关闭1个Frame
}
});
allButton.addActionListener(new ActionListener() { // 给按钮(关闭所有)添加监听器
public void actionPerformed(ActionEvent e) {
System.exit(0); // 点击时,退出程序
}
});
frame.setVisible(true); // 显示窗体
}
}
3.设置窗体背景色
建立三个按钮,颜色各不相同
要求鼠标进入时背景为按钮色,移出还原,点击时为按钮色并不再还原.
package com.itheima.gui.exercise;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public classExercise3{
public static void main(String[] args) {
// 创建窗体,设置....
Frame frame = newFrame("练习3");
frame.setSize(400,300);
frame.setLocation(600,100);
frame.setLayout(newFlowLayout());
// 创建3个按钮,设置颜色, 添加到窗体
Button redButton = new Button("Red");
Button greenButton = new Button("Green");
Button blueButton = new Button("Blue");
redButton.setBackground(Color.RED);
greenButton.setBackground(Color.GREEN);
blueButton.setBackground(Color.BLUE);
frame.add(redButton);
frame.add(greenButton);
frame.add(blueButton);
// 窗体关闭事件处理
frame.addWindowListener(newWindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// 按钮添加鼠标监听器
MouseListenerlistener = newMyMouseListener();
redButton.addMouseListener(listener);
greenButton.addMouseListener(listener);
blueButton.addMouseListener(listener);
// 显示
frame.setVisible(true);
}
}
class MyMouseListenerextendsMouseAdapter{
private Color color = Color.WHITE; // 窗体的颜色, 默认为白色
public void mouseEntered(MouseEvent e) { // 把窗体颜色改为按钮颜色
Button button = (Button) e.getSource();
Frame frame = (Frame) button.getParent();
frame.setBackground(button.getBackground());
}
public void mouseExited(MouseEvent e) { // 把Frame的颜色改为color记住的颜色
Button button = (Button) e.getSource();
Frame frame = (Frame) button.getParent();
frame.setBackground(color);
}
public void mouseClicked(MouseEvent e) { // color记住Button的颜色
Button button = (Button) e.getSource();
color =button.getBackground();
}
}
------- android培训、java培训、期待与您交流! ----------