黑马程序员---GUI(Graphical User Interface)

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

 

Java为GUI提供的对象都存在 java.Awt 和 javax.Swing 两个包中。

 

Awt与Swing

java.Awt:Abstract Window ToolKit (抽象窗口工具包),需要调用本地系统方法实现功能。属重量级控件。平台的依赖性较强一些。

javax.Swing:在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全 由Java实现。增强了移植性,属轻量级控件。不依赖平台。

 

swt组件外观包可以在Eclipse网站下载。

 

 

容器中的组件的排放方式,就是布局

常见的布局管理器

FlowLayout(流式布局管理器)

    • 从左到右的顺序排列。
    • Panel默认的布局管理器。

BorderLayout(边界布局管理器)

    • 东,南,西,北,中
    • Frame默认的布局管理器。

GridLayout(网格布局管理器)

    • 规则的矩阵

CardLayout(卡片布局管理器)

    • 选项卡

GridBagLayout(网格包布局管理器)

    • 非规则的矩阵

 

 

建立一个简单的窗体
Container常用子类:Window、 Panel(面板, 不能单独存在。)
Window常用子类:Frame 、Dialog

 

java.awt
Component

public abstract class Component

extends Object

implements ImageObserver,MenuContainer,Serializable

component 是一个具有图形表示能力的对象,可在屏幕上显示,并可与用户进行交互。典型图形用户界面中的按钮、复选框和滚动条都是组件示例。

 voidsetVisible(boolean b) 将隐藏组件显示或。。。
          根据参数 b 的值显示或隐藏此组件。
 voidshow()
          已过时。 从 JDK version 1.1 开始,由 setVisible(boolean) 取代。

 

 voidsetLocation(int x, int y) 设置组件位置
          将组件移到新位置。

 

public class Container

extends Component

一般的 Abstract Window Toolkit(AWT) 容器对象是一个可包含其他 AWT 组件的组件。

添加到容器中的组件放在一个列表中。列表的顺序将定义组件在容器内的正向堆栈顺序。如果将组件添加到容器中时未指定索引,则该索引将被添加到列表尾部(此后它位于堆栈顺序的底部)。

 Componentadd(Component comp, int index) 内部封装了一个ArrayList集合。
          将指定组件添加到此容器的给定位置上。

 

Componentadd(Component comp)
          将指定组件追加到此容器的尾部。

 

 voidsetLayout(LayoutManager mgr)
          设置此容器的布局管理器。

 

public class FlowLayout

extends Object implements LayoutManager, Serializable
构造方法摘要
FlowLayout()
          构造一个新的 FlowLayout,它是居中对齐的,默认的水平和垂直间隙是 5 个单位。
FlowLayout(int align)
          构造一个新的 FlowLayout,它具有指定的对齐方式,默认的水平和垂直间隙是 5 个单位。
FlowLayout(int align, int hgap, int vgap)
          创建一个新的流布局管理器,它具有指定的对齐方式以及指定的水平和垂直间隙。

public class Window

extends Container

implements Accessible

Window 对象是一个没有边界和菜单栏的顶层窗口。窗口的默认布局是 BorderLayout

构造窗口时,它必须拥有窗体、对话框或其他作为其所有者定义的窗口。

 voidsetSize(int width, int height)
          调整组件的大小,使其宽度为 width,高度为 height

 

建立Frame对象:

java.lang.Object 

         |--java.awt.Component     

                     |--java.awt.Container         

                                 |--java.awt.Window             

                                              |--java.awt.Frame

Frame 是带有标题和边框的顶层窗口。窗体的大小包括为边框指定的所有区域。

构造方法摘要
Frame()
          构造一个最初不可见的 Frame 新实例()。
Frame(String title)
          构造一个新的、最初不可见的、具有指定标题的 Frame 对象。

 

import java.awt.*;
class AwtDemo 
{
	public static void main(String[] args) 
	{
		Frame f = new Frame("my awt");
		//1.新建一个新的、不可见的Frame窗体。默认是BoarderLayout边界布局

		//2.对窗体进行基本设置:
		f.setSize(600,460);//设置窗体大小:宽,高
		f.setLocation(900,250);//设置窗体位于屏幕的位置。
		f.setLayout(new FlowLayout());//设置窗体为流式布局,默认居中对齐。

		Button b = new Button("我是第一个按钮");//3.定义组件
		Button b1 = new Button("我是第二个按钮");

		f.add(b);//4.将组件通过窗体的add方法添加到窗体中。
		f.add(b1);

		f.setVisible(true);//5.让窗体显示。
	}
}


创建图形化界面的步骤

1.创建Frame窗体。

2.对窗体进行基本设置:大小,位置,布局等。

3.定义组件。

4.将组件通过窗体的add方法添加到窗体中。

5.让窗体显示。

 

通过这5步你就能创建出一个图形界面。

创建图形界面不是重点的部分,关键是这个图形界面没有效果,最小化、最大化可以,关闭是关不掉的。

图形化出来以后。我们操作它该发生一些什么事情才是重点的部分。

 

dir
md 创建文件夹
rd 删除文件夹

del  *.class 删掉所有class文件

cd
cd.. 返回上一级

ctrl+Z 回退

 

事件监听机制组成:

1.事件源(组件)

2.事件(Event)

3.监听器(Listener)

4.事件处理方式(引发事件后处理方式)

 

事件源:就是awt包和swing包中提供的那些图形界面组件。

事件:每一个事件源都有自己特有的对应事件和共性事件。(事件只有动作才可以引发)

监听器:将可以触发某一个事件的动作(不只一个动作)都已经封装到了监听器中。

 

以上三者在Java中都已经定义好了。

直接获取其对象来用就可以了。

我们要做的事情是:对产生的动作进行处理。

处理动作才是我们编写awt编写图形化界面组件的时候最重要的部分

 

想给Frame窗体添加监听器,首先去它的父类Window里面找方法:

java.awt
类 Window

java.lang.Object 

          |--java.awt.Component     

                      |--java.awt.Container         

                                  |--java.awt.Window

 voidaddWindowListener(WindowListener l)
          添加指定的窗口侦听器,以从此窗口接收窗口事件。

找到添加窗口监听器WindowListener,监听器里面定义了操作窗口的动作。

 

所有监听器都是以Listener结尾的。

监听器都是注册到别人身上的东西,而且它里面定义的都是动作。

 

 

java.awt.event
接口 WindowListener

public interface WindowListener

extends EventListener

用于接收窗口事件的侦听器接口。旨在处理窗口事件的类要么实现此接口(及其包含的所有方法),要么扩展抽象类 WindowAdapter(仅重写所需的方法)。

方法摘要
 voidwindowActivated(WindowEvent e)
          将 Window 设置为活动 Window 时调用。
 voidwindowClosed(WindowEvent e)
          因对窗口调用 dispose 而将其关闭时调用。
 voidwindowClosing(WindowEvent e)
          用户试图从窗口的系统菜单中关闭窗口时调用。
 voidwindowDeactivated(WindowEvent e)
          当 Window 不再是活动 Window 时调用。
 voidwindowDeiconified(WindowEvent e)
          窗口从最小化状态变为正常状态时调用。
 voidwindowIconified(WindowEvent e)
          窗口从正常状态变为最小化状态时调用。
 voidwindowOpened(WindowEvent e)
          窗口首次变为可见时调用。

 

java.awt.event(记得导两包:import  java.awt.event.*;和 import  java.awt.*;)

类 WindowAdapter

public abstract class WindowAdapter

extends Object implements WindowListener, WindowStateListener, WindowFocusListener

接收窗口事件的抽象适配器类。此类中的方法为空。此类存在的目的是方便创建侦听器对象。

扩展此类可创建 WindowEvent 侦听器并为所需事件重写该方法。(如果要实现 WindowListener 接口,则必须定义该接口内的所有方法。此抽象类将所有方法都定义为 null,所以只需针对关心的事件定义方法。)

构造方法摘要
WindowAdapter()
           

 

方法摘要
 voidwindowActivated(WindowEvent e)
          激活窗口时调用。
 voidwindowClosed(WindowEvent e)
          当窗口已被关闭时调用。
 voidwindowClosing(WindowEvent e)
          窗口正处在关闭过程中时调用。
 voidwindowDeactivated(WindowEvent e)
          停用窗口时调用。
 voidwindowDeiconified(WindowEvent e)
          取消图标化窗口时调用。
 voidwindowGainedFocus(WindowEvent e)
          该 Window 被设置为聚焦 Window 时调用,聚焦 Window 意味着该 Window 或其某个子组件将接收键盘事件。
 voidwindowIconified(WindowEvent e)
          图标化窗口时调用。
 voidwindowLostFocus(WindowEvent e)
          该 Window 不再为聚焦 Window 时调用,不再为聚焦 Window 意味着键盘事件不再传递到该 Window 或其任意子组件。
 voidwindowOpened(WindowEvent e)
          已打开窗口时调用。
 voidwindowStateChanged(WindowEvent e)
          窗口状态改变时调用。

 

import java.awt.*;
import java.awt.event.*;
class AwtDemo 
{
	public static void main(String[] args) 
	{
		Frame f = new Frame("my awt");
		//1.新建一个新的、不可见的Frame窗体。默认是BoarderLayout边界布局

		//2.对窗体进行基本设置:
		f.setSize(600,460);//设置窗体大小:宽,高
		f.setLocation(900,250);//设置窗体位于屏幕的位置。
		f.setLayout(new FlowLayout());//设置窗体为流式布局,默认居中对齐。

		Button b = new Button("我是第一个按钮");//3.定义组件
		Button b1 = new Button("我是第二个按钮");

		f.add(b);//4.将组件通过窗体的add方法添加到窗体中。
		f.add(b1);

		//我只想关闭窗口:
		f.addWindowListener(new MyWindowListener());//这里添加一个窗口监听器。

		f.setVisible(true);//5.让窗体显示。
	}
}

/*
class MyWin implements WindowListener
{
	//覆盖7个方法。可以我只用到了关闭的动作。
	//其他动作都没有用到,可是却必须复写。
}
*/
//因为WindowListener的子类WindowAdapter已经实现了WindowListener接口。
//并覆盖了其中的所有方法。那么我只要继承自Windowadapter覆盖我需要的方法即可。
class MyWindowListener extends WindowAdapter
{
	public void windowClosing(WindowEvent e)//这里因为WindowEvent是java.awt.event包的。所以记得导包
	{
		System.out.println("window closing");
	}
}

这时的效果是:我点一次关闭按钮就会在控制台打印一次window closing


而且我一点击关闭按钮,就触发了窗体事件了,而且触发的是关闭动作,监听器就监听到这个动作了,所以监听器就会自动去调用windowClosing方法,

但是现在是不是没有用上参数里的 WindowEvent 对象啊?现在我们来将它打印看看:

import java.awt.*;
import java.awt.event.*;
class AwtDemo 
{
	public static void main(String[] args) 
	{
		Frame f = new Frame("my awt");
		//1.新建一个新的、不可见的Frame窗体。默认是BoarderLayout边界布局

		//2.对窗体进行基本设置:
		f.setSize(600,460);//设置窗体大小:宽,高
		f.setLocation(900,250);//设置窗体位于屏幕的位置。
		f.setLayout(new FlowLayout());//设置窗体为流式布局,默认居中对齐。

		Button b = new Button("我是第一个按钮");//3.定义组件
		Button b1 = new Button("我是第二个按钮");

		f.add(b);//4.将组件通过窗体的add方法添加到窗体中。
		f.add(b1);

		//我只想关闭窗口:
		f.addWindowListener(new MyWindowListener());//这里添加一个窗口监听器。

		f.setVisible(true);//5.让窗体显示。
	}
}

/*
class MyWin implements WindowListener
{
	//覆盖7个方法。可以我只用到了关闭的动作。
	//其他动作都没有用到,可是却必须复写。
}
*/
//因为WindowListener的子类WindowAdapter已经实现了WindowListener接口。
//并覆盖了其中的所有方法。那么我只要继承自Windowadapter覆盖我需要的方法即可。
class MyWindowListener extends WindowAdapter
{
	public void windowClosing(WindowEvent e)//这里因为WindowEvent是java.awt.event包的。所以记得导包
	{
		System.out.println("window closing-------"+e.toString());
		//现在我们看一下WindowEvent对象的作用,甭管什么,先打印一下toString()就可以看到效果。
	}
}


sun.awt.TimedWindowEvent   :WindowEvent事件

WINDOW_CLOSING   :事件里面封装了这个事件源所处的状态是被关闭状态

opposite=null

oldState=0,newState=0

on frame0    :所处的这个窗体的编号是0

这些就是事件信息。事件一产生了以后,它里面就包含了事件所属信息。

想关闭怎么办呀?

将windowClosing方法里面的内容改一下,改成:System.exit(0); 

 

public final class System

extends Object
static voidexit(int status)
          终止当前正在运行的 Java 虚拟机。

 

import java.awt.*;
import java.awt.event.*;
class AwtDemo 
{
	public static void main(String[] args) 
	{
		Frame f = new Frame("my awt");
		//1.新建一个新的、不可见的Frame窗体。默认是BoarderLayout边界布局

		//2.对窗体进行基本设置:
		f.setSize(600,460);//设置窗体大小:宽,高
		f.setLocation(900,250);//设置窗体位于屏幕的位置。
		f.setLayout(new FlowLayout());//设置窗体为流式布局,默认居中对齐。

		Button b = new Button("我是第一个按钮");//3.定义组件
		Button b1 = new Button("我是第二个按钮");

		f.add(b);//4.将组件通过窗体的add方法添加到窗体中。
		f.add(b1);

		//我只想关闭窗口:
		f.addWindowListener(new MyWindowListener());//这里添加一个窗口监听器。

		f.setVisible(true);//5.让窗体显示。
	}
}

/*
class MyWin implements WindowListener
{
	//覆盖7个方法。可以我只用到了关闭的动作。
	//其他动作都没有用到,可是却必须复写。
}
*/
//因为WindowListener的子类WindowAdapter已经实现了WindowListener接口。
//并覆盖了其中的所有方法。那么我只要继承自Windowadapter覆盖我需要的方法即可。
class MyWindowListener extends WindowAdapter
{
	public void windowClosing(WindowEvent e)//这里因为WindowEvent是java.awt.event包的。所以记得导包
	{
		//System.out.println("window closing-------"+e.toString());
		//现在我们看一下WindowEvent对象的作用,甭管什么,先打印一下toString()就可以看到效果。
		System.exit(0);
	}
}

MyWindowListener这个监听类里面只有一个方法,我们是不是可以写个匿名内部类啊?

import java.awt.*;
import java.awt.event.*;
class AwtDemo 
{
	public static void main(String[] args) 
	{
		Frame f = new Frame("my awt");
		//1.新建一个新的、不可见的Frame窗体。默认是BoarderLayout边界布局

		//2.对窗体进行基本设置:
		f.setSize(600,460);//设置窗体大小:宽,高
		f.setLocation(900,250);//设置窗体位于屏幕的位置。
		f.setLayout(new FlowLayout());//设置窗体为流式布局,默认居中对齐。

		Button b = new Button("我是第一个按钮");//3.定义组件
		Button b1 = new Button("我是第二个按钮");

		f.add(b);//4.将组件通过窗体的add方法添加到窗体中。
		f.add(b1);

		//我只想关闭窗口:
		f.addWindowListener(new WindowAdapter()
		{
			//windowClosing()是方法,window首字母要小写。否则写错方法名不报错,关不掉。
			public void windowClosing(WindowEvent e)//最常见的就是关的动作。
			{
				System.out.println("我关");
				System.exit(0);
			}
			public void windowActivated(WindowEvent e)//窗体只要处于最前端,就处于active状态,这个时候就引发了这个动作函数,并把这个动作所对应的事件对象传给了这个e。
			{
				System.out.println("我活了");
			}
			public void windowOpened(WindowEvent e)//打开这个动作只执行一次,有些软件一打开会出现一些动作,可以在这儿来完成。
			{
				System.out.println("我被打开了。。。。");
			}
		});//这里添加一个窗口监听器。

		f.setVisible(true);//5.让窗体显示。
	}
}

/*
class MyWin implements WindowListener
{
	//覆盖7个方法。可以我只用到了关闭的动作。
	//其他动作都没有用到,可是却必须复写。
}

//因为WindowListener的子类WindowAdapter已经实现了WindowListener接口。
//并覆盖了其中的所有方法。那么我只要继承自Windowadapter覆盖我需要的方法即可。
class MyWindowListener extends WindowAdapter
{
	public void windowClosing(WindowEvent e)//这里因为WindowEvent是java.awt.event包的。所以记得导包
	{
		//System.out.println("window closing-------"+e.toString());
		//现在我们看一下WindowEvent对象的作用,甭管什么,先打印一下toString()就可以看到效果。
		System.exit(0);
	}
}
*/

public void windowActivated(WindowEvent e)//窗体只要处于最前端,就处于active状态,这个时候就引发了这个动作函数,并把这个动作所对应的事件对象传给了这个e。

而且我一点击关闭按钮,就触发了窗体事件了,而且触发的是关闭动作,监听器就监听到这个动作了,所以监听器就会自动去调用windowClosing方法。

 

Window类的方法:

 voidsetBounds(int x, int y, int width, int height)
          移动组件并调整其大小。

 

java.awt
类 Button

java.lang.Object 

        |--java.awt.Component     

                   |--java.awt.Button

 voidaddActionListener(ActionListener l) 参数是活动监听器。
          添加指定的动作侦听器,以接收发自此按钮的动作事件。

 

java.awt.event
接口 ActionListener

public interface ActionListener

extends EventListener

ActionListener是少有的没有适配器的监听器,因为它的方法只有一个。(只要方法大于三个就会有适配器Adapter)

方法摘要
 voidactionPerformed(ActionEvent e)
          发生操作时调用。

 

我们将程序整理一下,给自定义按钮添加一个关闭窗口的功能:

import java.awt.*;
import java.awt.event.*;

class FrameDemo
{
	//1.定义该图形中所需组件的引用
	private Frame f;
	private Button b;

	FrameDemo()//5.在构造方法中调用一下init()方法。
	{
		init();
	}
	
	//2.初始化组件(这里面不要写事件,要把图形化组件和事件分离开来)
	public void init()
	{
		f = new Frame("my frame");

		//对Frame进行基本设置
		f.setBounds(600,150,300,200);//(int x, int y, int width, int height) 
		f.setLayout(new FlowLayout());
	
		b = new Button("我是一个按钮");
		f.add(b);

		//4.在显示窗体之前,加载一下myEvent()方法
		myEvent();

		f.setVisible(true);
	}

	//3.添加事件监听器
	public void myEvent()
	{
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
		//给自定义按钮添加监听器
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});
	}

	public static void main(String[] args) 
	{
		new FrameDemo();
	}
}


 

下面我们来说说,共性事件:(如鼠标、键盘事件)
java.awt
类 Component

鼠标事件:

public abstract class Component
 voidaddMouseListener(MouseListener l)
          添加指定的鼠标侦听器,以接收发自此组件的鼠标事件。


 java.awt.event
接口 MouseListener

public interface MouseListener

extends EventListener

用于接收组件上“感兴趣”的鼠标事件(按下、释放、单击、进入或离开)的侦听器接口。(要跟踪鼠标移动和鼠标拖动,请使用 MouseMotionListener。)

旨在处理鼠标事件的类要么实现此接口(及其包含的所有方法),要么扩展抽象类 MouseAdapter(仅重写所需的方法)。

构造方法摘要
MouseAdapter()
           

 

方法摘要
 voidmouseClicked(MouseEvent e)
          鼠标按键在组件上单击(按下并释放)时调用。
 voidmouseDragged(MouseEvent e)
          鼠标按键在组件上按下并拖动时调用。
 voidmouseEntered(MouseEvent e)
          鼠标进入到组件上时调用。
 voidmouseExited(MouseEvent e)
          鼠标离开组件时调用。
 voidmouseMoved(MouseEvent e)
          鼠标光标移动到组件上但无按键按下时调用。
 voidmousePressed(MouseEvent e)
          鼠标按键在组件上按下时调用。
 voidmouseReleased(MouseEvent e)
          鼠标按钮在组件上释放时调用。
 voidmouseWheelMoved(MouseWheelEvent e)
          鼠标滚轮旋转时调用。

 

java.awt
类 Button

 voidaddActionListener(ActionListener l)
          添加指定的动作侦听器,以接收发自此按钮的动作事件。

 

如果想监听鼠标双击的话,可以看看 MouseEvent 类的方法

java.awt.event
类 MouseEvent

 intgetClickCount()
          返回与此事件关联的鼠标单击次数。

 

 

键盘事件:

 voidaddKeyListener(KeyListener l)
          添加指定的按键侦听器,以接收发自此组件的按键事件。

java.awt.event
接口 KeyListener

public interface KeyListener

extends EventListener

用于接收键盘事件(击键)的侦听器接口。旨在处理键盘事件的类要么实现此接口(及其包含的所有方法),要么扩展抽象 KeyAdapter 类(仅重写有用的方法)。

java.awt.event
类 KeyAdapter

构造方法摘要
KeyAdapter()
           

 

方法摘要
 voidkeyPressed(KeyEvent e)
          按下某个键时调用此方法。
 voidkeyReleased(KeyEvent e)
          释放某个键时调用此方法。
 voidkeyTyped(KeyEvent e)
          键入某个键时调用此方法。

 

要想监听敲的到底是哪个键,我们来看看 KeyEvent 类的方法:

java.awt.event
类 KeyEvent

 chargetKeyChar()
          返回与此事件中的键关联的字符。
 intgetKeyCode()
          返回与此事件中的键关联的整数 keyCode。

 

static StringgetKeyText(int keyCode)
          返回描述 keyCode 的 String,如 "HOME"、"F1" 或 "A"。


java.awt.event
类 InputEvent

 booleanisControlDown()       组合键Ctrl+?
          返回 Control 键在此事件上是否按下。

 

 voidconsume()
          使用此事件,以便不会按照默认的方式由产生此事件的源代码来处理此事件。

 

java.awt
类 TextField

TextField 对象是允许编辑单行文本的文本组件。

构造方法摘要
TextField()
          构造新文本字段。
TextField(int columns)
          构造具有指定列数的新空文本字段。
TextField(String text)
          构造使用指定文本初始化的新文本字段。
TextField(String text, int columns)
          构造使用要显示的指定文本初始化的新文本字段,宽度足够容纳指定列数。

 

import java.awt.*;
import java.awt.event.*;

class MouseAndKeyEvent 
{
	private Frame f;
	private Button b;
	private TextField tf;

	MouseAndKeyEvent()
	{
		init();
	}
	
	public void init()
	{
		f = new Frame("my frame");
		b = new Button("我是一个按钮");
		tf = new TextField("QQ号,例如:123456",22);//单行文本框,只能指定列数。

		f.setBounds(600,150,300,200);
		f.setLayout(new FlowLayout());
	
		f.add(tf);
		f.add(b);

		myEvent();

		f.setVisible(true);
	}

	public void myEvent()
	{
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});

		//给文本框添加键盘监听器
		tf.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				int code = e.getKeyCode();
				if(!((code>=e.VK_0 && code<=e.VK_9)||(code>=e.VK_NUMPAD0 && code<=e.VK_NUMPAD9)||(code==e.VK_BACK_SPACE)))
				{
					System.out.println(code+"----是非法的");
					e.consume();//非法键将不写入文本框中。
				}
			}
		});

		/*
		//活动监听器(鼠标单击和键盘敲空格都起作用),建议创建这个
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				System.out.println("活动");
			}
		});
		*/

		b.addMouseListener(new MouseAdapter()
		{
			public void mouseEntered(MouseEvent e)
			{
				System.out.println("鼠标进入");
			}
			public void mouseExited(MouseEvent e)
			{
				System.out.println("鼠标离开");
			}
			//鼠标左右键单击(这个会比Action先执行,因为这个更具体一点)
			public void mouseClicked(MouseEvent e)
			{
				//鼠标双击
				if(e.getClickCount()==2)
				{
					System.out.println("双击");
				}
			}
		});

		b.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				//Ctrl+Enter组合键
				if(e.isControlDown() && e.getKeyCode()==e.VK_ENTER)
				{
					System.out.println("Ctrl+Enter");
				}
				//按下Esc键,退出程序。
				if(e.getKeyCode()==e.VK_ESCAPE)
				{
					System.exit(0);
				}
				//敲什么键打印什么字符 和 Key code。
				System.out.println(e.getKeyText(e.getKeyCode())+"---------"+e.getKeyCode());
			}
		});
	}

	public static void main(String[] args) 
	{
		new MouseAndKeyEvent();
	}
}


练习:

java.awt
类 TextArea

TextArea 对象是显示文本的多行区域。可以将它设置为允许编辑或只读。

构造方法摘要
TextArea()
          构造一个将空字符串作为文本的新文本区。
TextArea(int rows, int columns)
          构造一个新文本区,该文本区具有指定的行数和列数,并将空字符串作为文本。
TextArea(String text)
          构造具有指定文本的新文本区。
TextArea(String text, int rows, int columns)
          构造一个新文本区,该文本区具有指定的文本,以及指定的行数和列数。
TextArea(String text, int rows, int columns, int scrollbars)
          构造一个新文本区,该文本区具有指定的文本,以及指定的行数、列数和滚动条可见性。

 

想要获取文本框中的内容,查找其父类方法:

TextField 和 TextArea 有一个共同的父类 TextComponent。

java.awt
类 TextComponent

java.lang.Object 

         |--java.awt.Component     

                     |--java.awt.TextComponent

public class TextComponent

extends Component implements Accessible
TextComponent 类是所有允许编辑文本的组件的超类。

 StringgetText()
          返回此文本组件表示的文本。

 

import java.awt.*;
import java.awt.event.*;
import java.io.*;

class MyFrameDemo 
{
	private Frame f;
	private Button b;
	private TextField tf;
	private TextArea ta;
	
	MyFrameDemo()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my frame");
		tf = new TextField(42);
		b = new Button("转到");
		ta = new TextArea(20,50);

		f.setBounds(300,150,420,410);
		f.setLayout(new FlowLayout());

		f.add(tf);
		f.add(b);
		f.add(ta);

		myEvent();

		f.setVisible(true);
	}

	public void myEvent()
	{
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				String path = tf.getText();
				File f = new File(path);
				if(f.exists() && f.isDirectory())
				{
					ta.setText(null);//清屏
					String[] names = f.list();
					for(String name : names)
					{
						ta.append(name+"\r\n");
					}
				}
			}
		});

		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
	}

	public static void main(String[] args) 
	{
		new MyFrameDemo();
	}
}

 

java.awt
类 Dialog

public class Dialog

extends Window
构造方法摘要
Dialog(Frame owner,String title)
          构造一个最初不可见的、无模式的 Dialog,它带有指定的所有者 Frame 和标题。
Dialog(Frame owner,String title, boolean modal) modal模式:true-不关闭此对话框不能操作主窗体。false-不关闭此对话框也能操作主窗体。
          构造一个最初不可见的 Dialog,它带有指定的所有者 Frame、标题和模式。

 

java.awt
类 Label
java.lang.Object 

         |--java.awt.Component     

                     |--java.awt.Label

public class Label

extends Component implements Accessible Label 对象是一个可在容器中放置文本的组件。一个标签只显示一行只读文本。文本可由应用程序更改,但是用户不能直接对其进行编辑。
字段摘要
static intCENTER
          指示标签文本应居中。
static intLEFT
          指示标签文本应左对齐。
static intRIGHT
          指示标签文本应右对齐。

 

构造方法摘要
Label()
          构造一个空标签。
Label(String text)
          使用指定的文本字符串构造一个新的标签,其文本对齐方式为左对齐。
Label(String text, int alignment)
          构造一个显示指定的文本字符串的新标签,其文本对齐方式为指定的方式。

 

方法摘要
  StringgetText()
          获取此标签的文本。
 voidsetText(String text)
          将此标签的文本设置为指定的文本。

 

加入了错误路径提示对话框,和回车转到:

import java.awt.*;
import java.awt.event.*;
import java.io.*;

class MyFrameDemo 
{
	private Frame f;
	private Button b;
	private TextField tf;
	private TextArea ta;

	private Dialog d;
	private Button okButton;
	private Label label;
	
	MyFrameDemo()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my frame");
		tf = new TextField(42);
		b = new Button("转到");
		ta = new TextArea(20,50);

		f.setBounds(300,150,420,410);
		f.setLayout(new FlowLayout());

		f.add(tf);
		f.add(b);
		f.add(ta);

		d = new Dialog(f,"文件资源管理器",true);
		okButton = new Button("确定");
		label = new Label();

		d.setLayout(new FlowLayout());

		d.add(label);
		d.add(okButton);

		myEvent();

		f.setVisible(true);
	}

	public void myEvent()
	{
		//点击“关闭”按钮关闭对话框。
		d.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				d.setVisible(false);
			}
		});

		//点击“确定”按钮关闭对话框。
		okButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				d.setVisible(false);
			}
		});

		//敲“回车”获取文件列表内容。
		tf.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				if(e.getKeyCode()==e.VK_ENTER)
				{
					getList();
				}
			}
		});
		
		//点"转到"获取文件列表内容。
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				getList();
			}
		});
	
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
	}

	private void getList()
	{
		String path = tf.getText();
		File file = new File(path);
		if(file.exists() && file.isDirectory())
		{
			ta.setText(null);//清屏
			String[] names = file.list();
			for(String name : names)
			{
				ta.append(name+"\r\n");
			}
		}
		else
		{
			Rectangle rec = f.getBounds();
			label.setText("Windows找不到“"+path+"”。请检查拼写并重试。");
			int width = label.getText().length();
			d.setBounds(rec.x+50,rec.y+100,width*6+150,110);
			d.setVisible(true);
		}
	}

	public static void main(String[] args) 
	{
		new MyFrameDemo();
	}
}

效果如下:

 

 下面我们来学习菜单

菜单栏 : MenuBar

菜单栏里有很多菜单 : Menu

菜单里有很多菜单项 : MenuItem

有些菜单项里有子菜单

 

 java.awt
类 MenuBar

java.lang.Object 

         |--java.awt.MenuComponent     

                     |--java.awt.MenuBar

MenuBar 类封装绑定到框架的菜单栏的平台概念。为了将该菜单栏与 Frame 对象关联,可以调用该框架的 setMenuBar 方法(注意:这里不是add方法)。

Frame类的方法:

 voidsetMenuBar(MenuBar mb)
          将此窗体的菜单栏设置为指定的菜单栏。

 

构造方法摘要
MenuBar()
          创建新的菜单栏。

 

方法摘要
 Menuadd(Menu m)
          将指定的菜单添加到菜单栏。

 

java.awt
类 Menu

java.lang.Object 

          |--java.awt.MenuComponent     

                      |--java.awt.MenuItem         

                                   |--java.awt.Menu

Menu 对象是从菜单栏部署的下拉式菜单组件。

菜单可以是任意分离式 菜单。可以打开分离式菜单,并从其父菜单栏或菜单中拖开。释放鼠标按钮之后,它仍然在屏幕上。分离菜单的机制与平台有关,因为分离式菜单的外观由其同位体确定。对于不支持分离式菜单的平台,分离属性会被忽略。

菜单中的每一项都必须属于 MenuItem 类。它可以是 MenuItem 的一个实例、子菜单(Menu 的一个实例)、或复选框(CheckboxMenuItem 的一个实例)。

构造方法摘要
Menu()
          构造具有空标签的新菜单。
Menu(String label)
          构造具有指定标签的新菜单。
Menu(String label, boolean tearOff)
          构造具有指定标签的新菜单,指示该菜单是否可以分离。

 

方法摘要
 MenuItemadd(MenuItem mi)
          将指定的菜单项添加到此菜单。

 

因为子菜单是条目的子类

因为菜单可以添加条目

所以菜单也可以添加子菜单

也就是说菜单又可以添加它的父类又可以添加它自己。

 

但是条目没有添加菜单的功能。

import java.awt.*;
import java.awt.event.*;
import java.io.*;

class MyMenuDemo 
{
	private Frame f;
	private MenuBar mb;
	private Menu m,subMenu;
	private MenuItem closeItem,subItem;

	MyMenuDemo()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my frame");
		f.setBounds(300,100,500,600);
		f.setLayout(new FlowLayout());

		mb = new MenuBar();
		m = new Menu("文件");
		subMenu = new Menu("子菜单");
		subItem = new MenuItem("子条目");
		closeItem = new MenuItem("退出");

		f.setMenuBar(mb);//窗体添加菜单栏
		mb.add(m);//菜单栏添加菜单
		m.add(subMenu);//菜单添加子菜单
		subMenu.add(subItem);//子菜单添加子条目
		m.add(closeItem);//菜单添加条目
	
		myEvent();

		f.setVisible(true);
	}

	private void myEvent()
	{
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});

		//点击“退出”按钮退出程序。
		closeItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});
	}

	public static void main(String[] args) 
	{
		new MyMenuDemo();
	}
}


 打开文件

先找打开弹出的文件对话框:

java.awt
类 FileDialog

java.lang.Object 

         |--java.awt.Component     

                     |--java.awt.Container         

                                 |--java.awt.Window             

                                            |--java.awt.Dialog                    

                                                       |--java.awt.FileDialog

public class FileDialog

extends Dialog FileDialog 类显示一个对话框窗口,用户可以从中选择文件。 由于它是一个模式对话框,当应用程序调用其 show 方法来显示对话框时,它将阻塞其余应用程序,直到用户选择一个文件。
构造方法摘要
FileDialog(Dialog parent)
          创建一个文件对话框,用于加载文件。
FileDialog(Dialog parent,String title)
          创建一个具有指定标题的文件对话框,用于加载文件。
FileDialog(Dialog parent,String title, int mode)
          创建一个具有指定标题的文件对话框窗口,用于加载或保存文件。
FileDialog(Frame parent)
          创建一个文件对话框,用于加载文件。
FileDialog(Frame parent,String title)
          创建一个具有指定标题的文件对话框窗口,用于加载文件。
FileDialog(Frame parent,String title, int mode) 
          创建一个具有指定标题的文件对话框窗口,用于加载或保存文件。

mode - 对话框的模式,可以是 FileDialog.LOADFileDialog.SAVE

字段摘要
static intLOAD
          此常量值指示文件对话框窗口的作用是查找要读取的文件。“打开
static intSAVE
          此常量值指示文件对话框窗口的作用是查找要写入的文件。“保存

 

import java.awt.*;
import java.awt.event.*;
import java.io.*;

class MyMenuDemo 
{
	private Frame f;
	private MenuBar bar;
	private Menu fileMenu;
	private MenuItem openItem,saveItem,closeItem;
	private FileDialog openDia,saveDia;
	private TextArea ta;

	MyMenuDemo()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my frame");
		f.setBounds(300,100,650,600);

		bar = new MenuBar();
		fileMenu = new Menu("文件");
		openItem = new MenuItem("打开");
		saveItem = new MenuItem("保存");
		closeItem = new MenuItem("退出");

		f.setMenuBar(bar);//窗体添加菜单Bar
		bar.add(fileMenu);//菜单Bar添加文件菜单
		fileMenu.add(openItem);//文件菜单添加打开
		fileMenu.add(saveItem);//文件菜单添加保存
		fileMenu.add(closeItem);//文件菜单添加退出

		openDia = new FileDialog(f,"我要打开",FileDialog.LOAD);
		saveDia = new FileDialog(f,"我要保存",FileDialog.SAVE);

		ta = new TextArea();
		f.add(ta);
	
		myEvent();

		f.setVisible(true);
	}

	private void myEvent()
	{
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});

		//点击“退出”按钮退出程序。
		closeItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});

		//点击“打开”弹出打开文件对话框
		openItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				openDia.setVisible(true);
				String dirPath = openDia.getDirectory();
				String fileName = openDia.getFile();
				//System.out.println(dirPath);
				//System.out.println(fileName);
				File file = null;
				BufferedReader br = null;
				try
				{
					file = new File(dirPath,fileName);
					br = new BufferedReader(new FileReader(file));
					String line = null;
					ta.setText(null);
					while((line = br.readLine())!=null)
					{
						ta.append(line+"\r\n");
					}
				}
				catch (IOException e1)
				{
					throw new RuntimeException("文件读写失败");
				}
				finally
				{
					try
					{
						if(br!=null)
							br.close();
					}
					catch (IOException e2)
					{
						throw new RuntimeException("读取流关闭失败");
					}
				}				
			}
		});

		//点击“保存”弹出保存文件对话框
		saveItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				saveDia.setVisible(true);
			}
		});
	}

	public static void main(String[] args) 
	{
		new MyMenuDemo();
	}
}


保存文件

要搞清楚什么时候点保存才会弹出保存对话框,

如果这个文件已经在硬盘存在的话,就不会再创建文件,只是将改动的内容储存在这个文件中,

点击另存为的话才会在任何时候弹出保存对话框。

import java.awt.*;
import java.awt.event.*;
import java.io.*;

class MyMenuDemo 
{
	private Frame f;
	private MenuBar bar;
	private Menu fileMenu;
	private MenuItem newItem,openItem,saveItem,saveAsItem,closeItem;
	private FileDialog openDia,saveAsDia;
	private TextArea ta;
	private File file;

	MyMenuDemo()
	{
		init();
	}

	private void init()
	{
		f = new Frame("my frame");
		f.setBounds(300,100,650,600);

		bar = new MenuBar();
		fileMenu = new Menu("文件");
		newItem = new MenuItem("新建");
		openItem = new MenuItem("打开");
		saveItem = new MenuItem("保存");
		saveAsItem = new MenuItem("另存为");
		closeItem = new MenuItem("退出");

		f.setMenuBar(bar);//窗体添加菜单Bar
		bar.add(fileMenu);//菜单Bar添加文件菜单
		fileMenu.add(newItem);//文件菜单添加新建
		fileMenu.add(openItem);//文件菜单添加打开
		fileMenu.add(saveItem);//文件菜单添加保存
		fileMenu.add(saveAsItem);//文件菜单添加另存为
		fileMenu.add(closeItem);//文件菜单添加退出

		openDia = new FileDialog(f,"打开",FileDialog.LOAD);
		saveAsDia = new FileDialog(f,"另存为",FileDialog.SAVE);

		ta = new TextArea();
		f.add(ta);
	
		myEvent();

		f.setVisible(true);
	}

	private void myEvent()
	{
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});

		//点击“退出”按钮退出程序。
		closeItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				System.exit(0);
			}
		});

		//点击“新建”菜单项,新建一个文本文件
		newItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				file = null;
				ta.setText(null);
			}
		});

		//点击“打开”弹出打开文件对话框
		openItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				openDia.setVisible(true);
				String dirPath = openDia.getDirectory();
				String fileName = openDia.getFile();
				//System.out.println(dirPath);
				//System.out.println(fileName);
				if(dirPath==null ||fileName==null)
				{
					return;
				}
				file = new File(dirPath,fileName);
				readText();			
			}
		});

		//点击“保存”菜单项,什么时候会弹出保存对话框?
		saveItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if(file==null)
				{
					popupDia();
				}
				saveText();
			}
		});

		//点击“另存为”弹出保存文件对话框
		saveAsItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				popupDia();	
				saveText();
			}
		});
	}

	private void popupDia()
	{
		saveAsDia.setVisible(true);
		String dirPath = saveAsDia.getDirectory();
		String fileName = saveAsDia.getFile();
		if(dirPath==null ||fileName==null)
		{
			return;
		}
		file = new File(dirPath,fileName);
	}

	private void saveText()
	{
		BufferedWriter bw = null;
		try
		{
			bw = new BufferedWriter(new FileWriter(file));
			String fileText = ta.getText();
			bw.write(fileText);
			bw.flush();
		}
		catch (IOException e1)
		{
			throw new RuntimeException("保存失败");
		}
		finally
		{
			try
			{
				if(bw!=null)
					bw.close();
			}
			catch (IOException e2)
			{
				throw new RuntimeException("写入流关闭失败");
			}
		}
	}

	private void readText()
	{
		BufferedReader br = null;
		try
		{
			br = new BufferedReader(new FileReader(file));
			String line = null;
			ta.setText(null);
			while((line = br.readLine())!=null)
			{
				ta.append(line+"\r\n");
			}
		}
		catch (IOException e1)
		{
			throw new RuntimeException("打开失败");
		}
		finally
		{
			try
			{
				if(br!=null)
					br.close();
			}
			catch (IOException e2)
			{
				throw new RuntimeException("读取流关闭失败");
			}
		}	
	}

	public static void main(String[] args) 
	{
		new MyMenuDemo();
	}
}


jar包双击执行

windows键+R  回车:

C:\Users\Think>e:

E:\>cd java1201

E:\java1201>javac -d c:\myclass MyMenuDemo.java

E:\java1201>c:

C:\Users\Think>cd\

C:\>cd myclass

C:\myclass>jar -cvf notepad.jar myNotepad

已添加清单
正在添加: myNotepad/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: myNotepad/MyMenuDemo$1.class(输入 = 549) (输出 = 360)(压缩了
 34%)
正在添加: myNotepad/MyMenuDemo$2.class(输入 = 576) (输出 = 371)(压缩了
 35%)
正在添加: myNotepad/MyMenuDemo$3.class(输入 = 764) (输出 = 452)(压缩了
 40%)
正在添加: myNotepad/MyMenuDemo$4.class(输入 = 1037) (输出 = 600)(压缩
了 42%)
正在添加: myNotepad/MyMenuDemo$5.class(输入 = 693) (输出 = 434)(压缩了
 37%)
正在添加: myNotepad/MyMenuDemo$6.class(输入 = 590) (输出 = 384)(压缩了
 34%)
正在添加: myNotepad/MyMenuDemo.class(输入 = 4623) (输出 = 2302)(压缩了
 50%)

这时候双击jar包是不能运行的,因为它里面那么多class文件,该运行哪一个它不清楚,

这时候我需要新建一个txt文件将需要运行的class文件告诉它:文件信息如下

Main-Class: myNotepad.MyMenuDemo

写完以后别忘了加回车

 

注意

1.冒号后面加空格。忘加会报IOException。

2.末尾敲回车。不敲回车加不到配置文件中去。

 

写完以后保存

 

接下来怎么办呢:

C:\myclass>jar
用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C
 dir] files ...
选项包括:
    -c  创建新的归档文件
    -t  列出归档目录
    -x  从档案中提取指定的 (或所有) 文件
    -u  更新现有的归档文件
    -v  在标准输出中生成详细输出
    -f  指定归档文件名
    -m  包含指定清单文件中的清单信息
    -e  为捆绑到可执行 jar 文件的独立应用程序
        指定应用程序入口点
    -0  仅存储; 不使用情况任何 ZIP 压缩
    -M  不创建条目的清单文件
    -i  为指定的 jar 文件生成索引信息
    -C  更改为指定的目录并包含其中的文件
如果有任何目录文件, 则对其进行递归处理。
清单文件名, 归档文件名和入口点名称的指定顺序
与 'm', 'f' 和 'e' 标记的指定顺序相同。

示例 1: 将两个类文件归档到一个名为 classes.jar 的归档文件中:
       jar cvf classes.jar Foo.class Bar.class
示例 2: 使用现有的清单文件 'mymanifest' 并
           将 foo/ 目录中的所有文件归档到 'classes.jar' 中:
       jar cvfm classes.jar mymanifest -C foo/


C:\myclass>jar -cvfm notepad.jar 1.txt myNotepad
已添加清单
正在添加: myNotepad/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: myNotepad/MyMenuDemo$1.class(输入 = 549) (输出 = 360)(压缩了
 34%)
正在添加: myNotepad/MyMenuDemo$2.class(输入 = 576) (输出 = 371)(压缩了
 35%)
正在添加: myNotepad/MyMenuDemo$3.class(输入 = 764) (输出 = 452)(压缩了
 40%)
正在添加: myNotepad/MyMenuDemo$4.class(输入 = 1037) (输出 = 600)(压缩
了 42%)
正在添加: myNotepad/MyMenuDemo$5.class(输入 = 693) (输出 = 434)(压缩了
 37%)
正在添加: myNotepad/MyMenuDemo$6.class(输入 = 590) (输出 = 384)(压缩了
 34%)
正在添加: myNotepad/MyMenuDemo.class(输入 = 4623) (输出 = 2302)(压缩了
 50%)

这时已生成jar包:

打开里面看到配置信息里多了你刚才写的那行:

 

这个jar文件必须要在你本地注册过才能用

windows xp下:

点击工具 - 文件夹选项 - 文件类型 - jar文件类型 - 高级 - open - 编辑 - 如果没有open的话 - 新建 - 操作填open - 浏览 - d:\jdk\bin\javaw.exe - 打开 - 后面添一个参数“ -jar” - 确定 - 确定 - 关闭 -  

win8下注册

1.打开注册表(开始->运行或WIN+R,输入regedit,确定);
2.找到HKEY_CLASSES_ROOT\Applications\javaw.exe,一开始没有的话,就在资源管理器中找到javaw.exe文件,如我的电脑中为D:\Program Files\Java\jre\bin\javaw.exe,运行下,或找个Jar文件,选择打开方式,输入D:\Program Files\Java\jre\bin\javaw.exe,再选择打开就行了;
3.进入HKEY_CLASSES_ROOT\Applications\javaw.exe\shell\open\command,修改默认的键值为 "D:\Program Files\Java\jre\bin\javaw.exe" -jar "%1" 。
java环境安装在其它地方也类似。

顺便提下,删除没用的打开方式的方法:在HKEY_CLASSES_ROOT\Applications\中找到该程序文件的项就可以了。

这时双击jar包就能打开了。

  

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值