Java图形开发--GUI

Java图形开发--GUI

1、图形用户界面(gui)介绍

图形用户界面(Graphics User Interface,GUI)是用户与程序交互的窗口,比命令行的界面更加直观并且更好操作。

awt,swing,swt,Jface是什么?

Sun已经提供了一个跨平台GUI开发工具包AWT抽象窗口工具箱(Abstract Window Toolkit).

Sun又创建了一个新的GUI框架swing.解决了AWT存在的Icd问题.

IBM认为swing比较消耗内存,创建了一个新的GUI库,这就是SWT

IBM为了方便开发SWT程序,在SWT基础上又创建了一个更易用,功能强大的图开包"JFace"

 

2、eclipse开发工具介绍

eclipse是什么东西,我们用三句话来说明:

1、eclipse最早是IBM附属公司oti开发的,一共投入了4000万美金,后来捐献给开源社区

2、eclipse是一个开源的、可扩展的集成开发环境,已经成为目前最流行的java开发工具

3、eclipse安装后就可以开发java se的项目了,但不能开发java ee项目,需要安装web开发插件(lomboz或是myeclipse..)

ide(集成开发环境,比如jcreator、vs、myeclipse这些开发工具都是ide)

 

3、swing组件介绍

1、JFrame是Frame的子类

2、属于容器类组件,顶层容器

3、JFrame有一些常用的方法,通过示例与java的帮助文档即可了解。




在图形用户界面编程中,我们在窗体中会经常使用到按钮,我们在进行选择的时候,常常需要确认,所以按钮很重要。

 

只需要在窗体中添加按钮组件(JButton)即可完成。


按钮组件--深入讨论

1、JButton是AbstractButton的子类

2、属于窗口类组件,可以加入别的组件

3、Swing包的按钮组件不只有JButton,还有单选按钮(JRadioButton)、箭头按钮(BasicArrowButton)、触发器按钮(JToggleButton)


/**
 * 功能:GUI开发
 */
package com.gui;

import javax.swing.*;
import java.awt.*;

//JFrame是一个顶层容器类(可以添加其他swing组件的类)
public class Gui1 extends JFrame {
	//需要的swing组件,定义到这里
	JButton jb1 = null;
	// 构造函数
	public Gui1() {
		
		// 创建了一个Button按钮
		jb1 = new JButton("按钮");
		
		// 添加组件
		add(jb1);
		
		// 给窗体设置标题
		setTitle("hello,world!");

		// 设置大小,按像素计算
		setSize(200, 200);
		// 设置初始位置
		setLocation(100, 200);
		// 设置当窗口关闭时,保证JVM也退出
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// 显示
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui1 gui1 = new Gui1();
	}
}

4、三大常用布局管理器

布局管理器--介绍

1、概念

    组件在容器(比如JFrame)中的位置和大小是由布局管理器来决定的。所有的容器都会

使用一个布局管理器,通过它来自动进行组件的布局管理。

2、种类

    java共提供了五种布局管理器流式布局管理器(FlowLayout)边界布局管理器(BorderLayout)网格布局管理器(GridLayout)卡片布局管理器(CardLayout)网格包布局管理器(GridBagLayout)。其中前三种是最常见的布局管理器。

 

边界布局BorderLayout--介绍

    边界布局(BorderLayout)将容器简单的划分为东南西北5个区域,中间区域最大。

    JFrame窗体,JDialog对话框组件默认布局方法

 

/**
 * 边界布局
 */
package com.gui;
import java.awt.*;
import javax.swing.*;

//1.继承JFrame
public class Gui2 extends JFrame{
	//2.定义组件
	JButton jb1, jb2, jb3, jb4, jb5;

	public Gui2(){
		//3.创建组件
		jb1 = new JButton("中部");
		jb2 = new JButton("北部");
		jb3 = new JButton("东部");
		jb4 = new JButton("南部");
		jb5 = new JButton("西部");
		
		//4.添加各个组件
		add(jb1, BorderLayout.CENTER);
		add(jb2, BorderLayout.NORTH);
		add(jb3, BorderLayout.EAST);
		add(jb4, BorderLayout.SOUTH);
		add(jb5, BorderLayout.WEST);
		
		//5.设置窗体属性
		setTitle("边界布局");
		setSize(300, 200);
		setLocation(200, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//6.显示窗体
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui2 gui1 = new Gui2();
	}
}

边界布局BorderLayout--注意事项

1、不是五个部分都必需添加;

2、中部组件会自动调节大小;

3、JFrame,JDialog默认布局管理器就是BorderLayout


流式布局FlowLayout--介绍

FlowLayout布局,按照组件的添加次序将按钮组件(当然也可以是别的组件)从左到右放置在容器中。当到达容器的边界时,组件将放置到下一行中。FlowLayout可以以左对齐、居中对齐、以右对齐的方式排列组件。

 

/**
 * 流式布局
 */
package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui3 extends JFrame{
	//定义组件
	JButton jb1, jb2, jb3, jb4, jb5, jb6;
	//构造函数
	public Gui3(){
		//创建组件
		jb1 = new JButton("Button1");
		jb2 = new JButton("Button2");
		jb3 = new JButton("Button3");
		jb4 = new JButton("Button4");
		jb5 = new JButton("Button5");
		jb6 = new JButton("Button6");
		//添加组件
		add(jb1);
		add(jb2);
		add(jb3);
		add(jb4);
		add(jb5);
		add(jb6);
		//设置流式布局
		setLayout(new FlowLayout(FlowLayout.RIGHT));
		//设置窗体属性
		setTitle("流式布局");
		setSize(300, 200);
		setLocation(200, 200);
		//禁止用户改变窗体大小
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui3 gui1 = new Gui3();
	}
}

流式布局FlowLayout--注意事项

1、不限制他所管理的组件大小,允许他们有最佳大小

2、当容器缩放扩大时,组件的位置可能变化,但组件的大小不变。

3、默认组件是居中对齐,可以通过FlowLayout(int align)函数来指定对齐方式。


网格布局GridLayout--介绍

GridLayout布局,听其名而知其意,它将容器分割成多行多列,组件被填充到每个网格中,添加到容器中的组件首先放置在左上角的网格中,然后从左到右放置其它的组件,当占满该行的所有网格后,接着继续在下一行从左到右放置组件。

/**
 * 网格布局
 */
package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui4 extends JFrame{
	int size = 9;
	//定义组件;
	JButton[] jbs = new JButton[9];
	public Gui4(){
		//创建组件
		for(int i = 0; i < size; i++){
			jbs[i] = new JButton("" + i);
		}
		//设置网格布局
		setLayout(new GridLayout(3, 3, 5, 5));
		//添加组件
		for(int i = 0; i < size; i++){
			add(jbs[i]);
		}
		
		//设置窗体属性
		setTitle("网格布局");
		setSize(300, 300);
		setLocation(200,200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui4 gui1 = new Gui4();
	}
}

网格布局GridLayout--注意事项

1、组件的相对位置不随容器的缩放而变化,但大小会变化;

2、所有组件的大小相同;

3、可以通过GridLayout(int rows,int cols,int hgap,int vgap)来指定网格的行/列,水平间隙/垂直间隙。

参数说明:rows:行数/cols:列数/hgap:垂直间隙/vgap:水平间隙


3、开发GUI程序步骤

1、继承JFrame(类继承)

2、定义需要的组件(成员变量)

3、创建组件(构造函数中)

4、添加组件(构造方法中)

5、设置布局管理器(构造方法中)

6、显示窗体(构造函数中)


5、Swing组件--面板组件

面板组件(JPanel)--介绍

在图形用户界面编程中,如果只是普通的组件布局,我们用前面讲的三种布局管理器就可以解决,但在比较复杂的布局要求时,就需要使用布局管理器的组合使用。

 

JPanel:面板组件,非顶层容器,一个界面只可以有一个JFrame窗体组件,但可以有多个JPanel面板组件JPanel上也可以使用FlowLayout、BorderLayout、GirdLayout等各种布局管理器,这样可以组合使用达到较为复杂的布局效果。


/**
 * 多种布局管理器的使用
 */
package com.gui;
import java.awt.*;
import javax.swing.*;

public class Gui5 extends JFrame{
	//定义组件
	JPanel jp1, jp2;
	JButton jb1, jb2, jb3, jb4, jb5, jb6;
	//构造方法
	public Gui5(){
		//创建组件
		//JPanel布局默认是FlowLayout
		jp1 = new JPanel();
		jp2 = new JPanel();
		
		jb1 = new JButton("Button1");
		jb2 = new JButton("Button2");
		jb3 = new JButton("Button3");
		jb4 = new JButton("Button4");
		jb5 = new JButton("Button5");
		jb6 = new JButton("Button6");
		
		//添加JPanel
		jp1.add(jb1);
		jp1.add(jb2);
		jp2.add(jb3);
		jp2.add(jb4);
		jp2.add(jb5);
		
		//把JPanel加入JFrame
		add(jp1, BorderLayout.NORTH);
		add(jb6, BorderLayout.CENTER);
		add(jp2, BorderLayout.SOUTH);
		
		//设置窗体
		setTitle("多种布局管理器的使用");
		setSize(300, 300);
		setLocation(200, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String args[]){
		Gui5 gui1 = new Gui5();
	}
}

面板(JPanel)组件--注意事项

1、JPanel是JComponent的子类;

2、属于容器类组件,可以加入别的组件;

3、默认布局管理器是流式布局(FlowLayout)


Swing组件--文本框/密码框/标签组件

在图形用户界面编程中,我们常常会提供用户登录界面,比如登录到会员管理系统,登录到工资管理系统、仓库管理系统等。这时候我们就会用到:

1、文本框(JTextField)

2、密码框(JPasswordField)

3、标签(JLable)

package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui6 extends JFrame{
	//定义组件
	JPanel jp1, jp2, jp3;
	JLabel jlb1, jlb2;
	JButton jb1, jb2;
	JTextField jtf;
	JPasswordField jpf;
	//构造方法
	public Gui6(){
		//创建组件
		jp1 = new JPanel();
		jp2 = new JPanel();
		jp3 = new JPanel();
		
		jlb1 = new JLabel("用户名:");
		jlb2 = new JLabel("密   码:");
		
		jb1 = new JButton("登录");
		jb2 = new JButton("取消");
		
		jtf = new JTextField(10);
		jpf = new JPasswordField(10);
		
		//设置布局管理器
		setLayout(new GridLayout(3, 1));
		
		//加入组件
		jp1.add(jlb1);
		jp1.add(jtf);
		jp2.add(jlb2);
		jp2.add(jpf);
		jp3.add(jb1);
		jp3.add(jb2);
		
		//加入到JFrame
		add(jp1);
		add(jp2);
		add(jp3);
		
		//设置窗体
		setTitle("登录界面");
		setSize(300, 150);
		setLocation(500,500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		Gui6 gui1 = new Gui6();

	}
}

Swing组件--复选框/单选框组件

在图形用户界面编程中,我们常常会提供用户注册界面,这时候我们就会用到:

1、复选框组件(JCheckBox)

2、单选框组件(JRadioBuutton)

特别说明:

    同一组单选按钮必需先创建ButtonGroup,然后把单选框组件放入到ButtonGroup中

package com.gui;
import java.awt.*;

import javax.swing.*;
public class Gui7 extends JFrame{
	//定义组件
	JPanel jp1, jp2, jp3;
	JLabel jl1, jl2;
	JButton jb1, jb2;
	JCheckBox jcb1, jcb2, jcb3;
	JRadioButton jrb1, jrb2;
	ButtonGroup bg;
	//构造函数
	public Gui7(){
		//创建组件
		jp1 = new JPanel();
		jp2 = new JPanel();
		jp3 = new JPanel();
		jl1 = new JLabel("你喜欢的运动:");
		jl2 = new JLabel("你喜欢的运动:");
		jb1 = new JButton("注册用户");
		jb2 = new JButton("取消注册");
		
		jcb1 = new JCheckBox("足球");
		jcb2 = new JCheckBox("篮球");
		jcb3 = new JCheckBox("网球");
		
		jrb1 = new JRadioButton("男");
		jrb2 = new JRadioButton("女");
		//单选组件一定要放入到一个ButtonGroup
		//不放入的话,可以多选
		bg = new ButtonGroup();
		bg.add(jrb1);
		bg.add(jrb2);
		
		//设置布局管理器
		setLayout(new GridLayout(3, 1));
		
		//添加组件
		jp1.add(jl1);
		jp1.add(jcb1);
		jp1.add(jcb2);
		jp1.add(jcb3);
		
		jp2.add(jl2);
		jp2.add(jrb1);
		jp2.add(jrb2);
		
		jp3.add(jb1);
		jp3.add(jb2);
		
		add(jp1);
		add(jp2);
		add(jp3);
		
		//设置窗体
		setTitle("调查报告");
		setSize(300, 300);
		setLocation(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui7 gui1 = new Gui7();
	}
}

Swing组件--下拉框/列表框/流动空格组件

在图形用户界面编程中,常常会提供用户调查界面,这个时候会用到:

1、下拉框组件(JComboBox)

2、列表框组件(JList)

3、滚动窗格组件(JScrollPane)

特别说明:

    一般来说,列表框组件+滚动窗格组件是结合使用的。目的是让列表框中的选项可以有滚动条支持。

package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui8 extends JFrame{
	//定义组件
	JPanel jp1, jp2;
	JLabel jl1, jl2;
	JComboBox jcb;
	JList jlist;
	JScrollPane jsp;
	//构造方法
	public Gui8(){
		//创建组件
		jp1 = new JPanel();
		jp2 = new JPanel();
		
		jl1 = new JLabel("你的籍贯:");
		jl2 = new JLabel("旅游地点:");
		
		String[] jg = {"北京", "上海", "天津", "火星"};
		jcb = new JComboBox(jg);
		
		String[] dd = {"九寨沟", "故宫", "长城", "天安门"};
		jlist = new JList(dd);
		//设置显示选项个数
		jlist.setVisibleRowCount(2);
		jsp = new JScrollPane(jlist);
		
		
		//设置布局
		setLayout(new GridLayout(3, 1));
		
		//添加组件
		jp1.add(jl1);
		jp1.add(jcb);
		jp2.add(jl2);
		jp2.add(jsp);
		
		add(jp1);
		add(jp2);
		
		//设置窗体
		setTitle("旅游");
		setSize(300, 300);
		setLocation(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		Gui8 gui1 = new Gui8();
	}
}

Swing组件--总结

总结:

1、Swing的常用组件(JFrame(框架)、Jpanel(面板)、JButton(按钮)、JLable(标签)、JTextField(文本框)、JPasswordField(密码框)、JCheckBox(复选框)、JRadioButton(单选框)、JComboBox(下拉框)、JScrollPane(滚动窗格)、JList(列表框))

2、三大布局管理器(BorderLayout(边界布局)、FlowLayout(流布局)、GridLayout(网格布局)),要灵活使用,从而满足设计需求。


6、GUI编程实践

1、拆分窗格(JSplitPane)属于容器类组件

package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui9 extends JFrame{
	//定义组件
	JSplitPane jsp;
	JList jlist;
	JLabel jl;
	//构造方法
	public Gui9(){
		//创建组件
		String[] words = {"boy", "girl", "bird"};
		jlist = new JList(words);
		jl = new JLabel(new ImageIcon("images/image01.jpg"));
		//拆分窗格
		jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jlist, jl);
		//可以变化
		jsp.setOneTouchExpandable(true);
		
		//添加组件
		add(jsp);
		
		//设置窗体
		setTitle("分割");
		setSize(400, 300);
		setLocation(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		Gui9 gui1 = new Gui9();
	}
}

2、多行文本框(JTextArea)组件

package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui10 extends JFrame{
	//定义组件
	JTextArea jta = null;
	JPanel jp1 = null;
	JComboBox jcb = null;
	JTextField jtf = null;
	JButton jb = null;
	JScrollPane jsp = null;
	
	//构造方法
	public Gui10(){
		jta = new JTextArea();
		jsp = new JScrollPane(jta);
		jp1 = new JPanel();
		String[] chatter = {"张三","李四"};
		jcb = new JComboBox(chatter);
		jtf = new JTextField(10);
		jb = new JButton("发送");
		
		
		//添加组件
		jp1.add(jcb);
		jp1.add(jtf);
		jp1.add(jb);
		
		//加入JFrame
		add(jsp);
		add(jp1, BorderLayout.SOUTH);
		
		//设置窗体
		setIconImage((new ImageIcon("images/image01.jpg")).getImage());
		setTitle("聊天");
		setSize(400, 300);
		setLocation(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui10 gui1 = new Gui10();
	}
}

3、页签组件(JTabbedPane)选项卡窗格

package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui11 extends JFrame{
	//定义组件
	JPanel jp1, jp2, jp3, jp4;
	JLabel jl1, jl2, jl3, jl4, jl5;
	JTextField jtf1;
	JPasswordField jpf1;
	JCheckBox jcb1, jcb2;
	JButton jb1, jb2, jb3, jb4;
	JTabbedPane jtp;
	//构造函数
	public Gui11(){
		//创建组件
		jp1 = new JPanel();
		jp2 = new JPanel();
		jp3 = new JPanel();
		jp4 = new JPanel();
		
		jl1 = new JLabel(new ImageIcon("images/image01.jpg"));
		jl2 = new JLabel("账号");
		jl3 = new JLabel("密码");
		jl4 = new JLabel("忘记密码");
		jl4.setForeground(Color.BLUE);
		jl5 = new JLabel("<html><a href='http://blog.csdn.net/q547550831'>访问</a>");
		jl5.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		
		jtf1 = new JTextField(10);
		jpf1 = new JPasswordField(10);
		
		jcb1 = new JCheckBox("隐身登录");
		jcb2 = new JCheckBox("记住密码");
		
		jb1 = new JButton("清除号码");
		jb2 = new JButton("登录");
		jb3 = new JButton("注销");
		jb4 = new JButton("注册");
		
		jtp = new JTabbedPane();
		
		//设置布局
		jp1.setLayout(new GridLayout(3, 3));
		jp1.add(jl2);
		jp1.add(jtf1);
		jp1.add(jb1);
		jp1.add(jl3);
		jp1.add(jpf1);
		jp1.add(jl4);
		jp1.add(jcb1);
		jp1.add(jcb2);
		jp1.add(jl5);
		jp2.setBackground(Color.RED);
		jp3.setBackground(Color.BLUE);
		jtp.add("账号", jp1);
		jtp.add("手机号码", jp2);
		jtp.add("电子邮件", jp3);
		
		jp4.add(jb2);
		jp4.add(jb3);
		jp4.add(jb4);
		
		//加入到JFrame
		add(jl1, BorderLayout.NORTH);
		add(jtp);
		add(jp4, BorderLayout.SOUTH);
		
		//设置窗体
		setTitle("登录界面");
		setIconImage((new ImageIcon("images/image02.jpg")).getImage());
		setSize(400, 300);
		setLocation(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
	}
	public static void main(String[] args) {
		Gui11 gui1 = new Gui11();
	}
}

4、菜单组件JMenuBarJMenuJMenuItem工具条组件(JToolBar

package com.gui;
/**
 * 1、菜单组件
    	JMenuBar	菜单条组件	树干
    	JMenu		菜单组件	树枝
    	JMenuItem	菜单项组件	树叶
	2、二级菜单制作
    	JMenu里面可以嵌套JMenu
	3、工具条组件
    	JToolBar	容器类组件
 */
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Gui12 extends JFrame{
	//文件组定义组件
	JMenuBar jmb;//菜单条组件
	JMenu menu1,menu2,menu3,menu4,menu5;//主菜单:文件、编辑、格式、查看、帮助
	JMenuItem item2,item3,item4,item5,item6,item7;//子菜单:新建、打开、保存、另存为、页面设置、打印、退出
	JMenu xinjian;//二级菜单
	JMenuItem file,project;
	//编辑组定义组件
	//编辑:撤消、剪切、复制、粘贴、删除、查找、查找下一个、替换、转到、全选、时间/日期
	JMenuItem eitem1,eitem2,eitem3,eitem4,eitem5,eitem6,eitem7,eitem8,eitem9,eitem10,eitem11;
	
	//格式组定义组件
	JMenuItem oitem1,oitem2;//格式:自动换行、字体
	
	//查看组定义组件
	JMenuItem vitem1;//查看:状态栏
	
	//帮助组定义组件
	JMenuItem hitem1,hitem2;//帮助:查看帮助、关于记事本
	
	JTextArea jta;
	//工具条
	JToolBar jtb;
	JButton jb1,jb2,jb3,jb4,jb5,jb6,jb7,jb8;
	
	public static void main(String[] args) {
		Gui12 win=new Gui12();
	}
	//构造函数
	public Gui12(){
		//构建组件
		//工具条
		jtb=new JToolBar();
		jb1=new JButton(new ImageIcon("images/new.jpg"));
		jb1.setToolTipText("新建");//设置提示信息
		jb2=new JButton(new ImageIcon("images/open.jpg"));
		jb2.setToolTipText("打开");
		jb3=new JButton(new ImageIcon("images/save.jpg"));
		jb3.setToolTipText("保存");
		jb4=new JButton(new ImageIcon("images/copy.jpg"));
		jb4.setToolTipText("复制");
		jb5=new JButton(new ImageIcon("images/delete.jpg"));
		jb5.setToolTipText("删除");
		jb6=new JButton(new ImageIcon("images/modify.jpg"));
		jb6.setToolTipText("编辑");
		jb7=new JButton(new ImageIcon("images/print.jpg"));
		jb7.setToolTipText("打印");
		jb8=new JButton(new ImageIcon("images/close.jpg"));
		jb8.setToolTipText("关闭");
		
		jmb=new JMenuBar();
		//主菜单
		menu1=new JMenu("文件(F)");
		menu1.setMnemonic('F');//设置助记符
		menu2=new JMenu("编辑(E)");
		menu2.setMnemonic('E');
		menu3=new JMenu("格式(O)");
		menu3.setMnemonic('O');
		menu4=new JMenu("查看(V)");
		menu4.setMnemonic('V');
		menu5=new JMenu("帮助(H)");
		menu5.setMnemonic('H');
		
		//文件--新建--子目录
		xinjian=new JMenu("新建");
		file=new JMenuItem("文件");
		project=new JMenuItem("工程");
		
		item2=new JMenuItem("打开(O)");
		item2.setMnemonic('O');
		item2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,InputEvent.CTRL_MASK));//设置ctrl快捷组合键
		item3=new JMenuItem("保存(S)");
		item3.setMnemonic('S');
		item3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));
		item4=new JMenuItem("另存为(A)");
		item4.setMnemonic('A');
		item5=new JMenuItem("页面设置(U)");
		item5.setMnemonic('U');
		item6=new JMenuItem("打印(P)");
		item6.setMnemonic('P');
		item6.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,InputEvent.CTRL_MASK));
		item7=new JMenuItem("退出(X)");
		item7.setMnemonic('X');
		
		eitem1=new JMenuItem("撤消(U)");
		eitem1.setMnemonic('U');
		eitem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U,InputEvent.CTRL_MASK));
		eitem2=new JMenuItem("剪切(T)");
		eitem2.setMnemonic('T');
		eitem2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T,InputEvent.CTRL_MASK));
		eitem3=new JMenuItem("复制(C)");
		eitem3.setMnemonic('C');
		eitem3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_MASK));
		eitem4=new JMenuItem("粘贴(P)");
		eitem4.setMnemonic('P');
		eitem4.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,InputEvent.CTRL_MASK));
		eitem5=new JMenuItem("删除(L)");
		eitem5.setMnemonic('L');
		eitem5.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0));
		eitem6=new JMenuItem("查找(F)");
		eitem6.setMnemonic('F');
		eitem6.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,InputEvent.CTRL_MASK));
		eitem7=new JMenuItem("查找下一个(N)");
		eitem7.setMnemonic('N');
		eitem7.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3,0));
		eitem8=new JMenuItem("替换(R)");
		eitem8.setMnemonic('R');
		eitem8.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,InputEvent.CTRL_MASK));
		eitem9=new JMenuItem("转到(G)");
		eitem9.setMnemonic('G');
		eitem9.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,InputEvent.CTRL_MASK));
		eitem10=new JMenuItem("全选(A)");
		eitem10.setMnemonic('A');
		eitem10.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,InputEvent.CTRL_MASK));
		eitem11=new JMenuItem("时间/日期(D)");
		eitem11.setMnemonic('D');
		eitem11.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5,0));
		
		oitem1=new JMenuItem("自动换行(W)");
		oitem1.setMnemonic('W');
		oitem2=new JMenuItem("字体(F)");
		oitem2.setMnemonic('F');
		
		vitem1=new JMenuItem("状态栏(S)");
		vitem1.setMnemonic('S');
		
		hitem1=new JMenuItem("查看帮助(H)");
		hitem1.setMnemonic('H');
		hitem2=new JMenuItem("关于记事本(A)");
		hitem2.setMnemonic('A');
		
		jta=new JTextArea();
		
		//设定布局管理器
		
		//加入组件
		//将按钮添加到工具条上
		jtb.add(jb1);
		jtb.add(jb2);
		jtb.add(jb3);
		jtb.add(jb4);
		jtb.add(jb5);
		jtb.add(jb6);
		jtb.add(jb7);
		jtb.add(jb8);
		
		//将菜单项添加到菜单上
		xinjian.add(file);
		xinjian.add(project);
		
		menu1.add(xinjian);
		menu1.add(item2);
		menu1.add(item3);
		menu1.add(item4);
		menu1.addSeparator();//添加分割线
		menu1.add(item5);
		menu1.add(item6);
		menu1.addSeparator();
		menu1.add(item7);
		
		menu2.add(eitem1);
		menu2.addSeparator();
		menu2.add(eitem2);
		menu2.add(eitem3);
		menu2.add(eitem4);
		menu2.add(eitem5);
		menu2.addSeparator();
		menu2.add(eitem6);
		menu2.add(eitem7);
		menu2.add(eitem8);
		menu2.add(eitem9);
		menu2.addSeparator();
		menu2.add(eitem10);
		menu2.add(eitem11);
		
		menu3.add(oitem1);
		menu3.add(oitem2);
		
		menu4.add(vitem1);
		
		menu5.add(hitem1);
		menu5.addSeparator();
		menu5.add(hitem2);
		
		//将菜单添加到菜单条上
		jmb.add(menu1);
		jmb.add(menu2);
		jmb.add(menu3);
		jmb.add(menu4);
		jmb.add(menu5);
		
		//将菜单条添加到窗体上
		this.setJMenuBar(jmb);
		
		//将工具条添加到窗体上
		this.add(jtb,BorderLayout.NORTH);
		
		JScrollPane jsp=new JScrollPane(jta);
		jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		this.add(jsp);
		
		//窗体设置
		this.setTitle("Java记事本");
		this.setSize(500, 400);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);		
	}
}

7、java绘图坐标体系

绘图坐标本系--介绍

坐标原点位于左上角,以像素为单位。像素是计算机屏幕上最小的显示单位。在java的坐标系中,第一个是X坐标,表示当前位置为水平方向,距离坐标原点X个像素;第二个是Y坐标,表示当前位置为垂直方向,距离坐标原点Y个像素。



坐标体系--像素

     计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的。例如,计算机显示器的分辨率是800×600,表示计算机屏幕上的每一行由800个点组成,共有600行,整个计算机屏幕共有480000个像素。现在的计算机可以支持更高的分辨率,也就是说,屏幕上可以显示更多的像素。因此,像素是一个密度单位,而厘米是长度单位,两者无法比较


绘图原理(1)

Component类提供了两个和绘图相关最重要的方法:

1、paint(Graphics g)绘制组件的外观

2、repaint()刷新组件的外观

当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件

 

绘图原理(2)

在以下情况paint()将会被调用:

1、窗口最小化,再最大化

2、窗口的大小发生变化

3、repaint函数被调用


java绘图技术--Graphics

Graphics类

Graphics类你可以理解就是画笔,为我们提供了各种绘制图形的方法:

1、画直线 drawLine(int x1,int y1,int x2,int y2);

2、画矩形边框 drawRect(int x,int y,int width,int height);

3、画椭圆边框 drawOval(int x,int y,int width,int height);

4、填充矩形 fillRect(int x,int y,int width,int height);

5、填充椭圆 fillOval(int x,int y,int width,int height);

6、画图片 drawImage(Image img.int x,int y,..);

7、画字符串 drawString(String str,int x,int y);

8、设置画笔的字体 setFont(Font font);

9、设置画笔的颜色 setColor(Color c);


package com.gui;
import java.awt.*;
import javax.swing.*;
public class Gui13 extends JFrame{
	
	MyPanel mp = null;
	public Gui13(){
		mp = new MyPanel();
		
		add(mp);
		
		setSize(400, 300);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		Gui13 gui1 = new Gui13();

	}

}

//定义一个MyPanel,用于绘图和显示绘图的区域
class MyPanel extends JPanel{
	//覆盖JPanel的paint方法
	//Graphics是绘图的重要类,等价于画笔
	public void paint(Graphics g){
		//1.调用父类方法,完成初始化
		super.paint(g);
		//空心圆
		//g.drawOval(10, 10, 30, 30);
		//直线
		//g.drawLine(10, 10, 40, 40);
		//空心矩形
		//g.drawRect(10, 10, 40, 60);
		//填充矩形
//		g.setColor(Color.BLUE);
//		g.fillRect(10, 10, 40, 60);
//		g.setColor(Color.RED);
//		g.fillRect(70, 70, 40, 60);
		
		//在面板上画出图片
//		Image im = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/images/image01.jpg"));
//		g.drawImage(im, 10, 10, 200, 150, this);
		
		//字符
//		g.setColor(Color.red);
//		g.setFont(new Font(("隶书"), Font.BOLD, 30));
//		g.drawString("String 字符串", 100, 100);
		//圆的轮廓
		g.drawArc(100, 100, 100, 100, 20, 300);
	}
}

8、java事件处理机制

 

java事件处理机制--初步介绍

java事件处理是采取“委派事件模型”。所谓“委派事件模型”是指当事件发生时,产生事件的对象(即事件源),会把此“信息”传递给“事件的监听者”处理的一种方式,而这里所说的“信息”实际上就是java.awt.event事件类库里某个类所创建的对象,我们暂时把它称为“事件的对象”。


    比如:当按下按钮时,就会在按钮触发一个“事件”,程序就会产生一个“事件对象”来表示这个事件,并把这个“事件对象”传递给“事件的监听者”,“事件的监听者”再根据“事件对象”的类型进行相应处理。

为了让“产生事件的对象”[比如按钮]知道要把事件传递给哪一个“事件监听者”,我们必需先把“事件监听者”在“产生事件的对象”注册,这个操作也就是要告知“产生事件的对象”要把事件传递给它。


/**
 * 功能:事件处理机制
 */
package com.gui;
import java.awt.*;
import javax.swing.*;

import java.awt.event.*;

public class Gui14 extends JFrame implements ActionListener{
	//定义组件
	Panel mp = null;
	JButton jb1, jb2;
	
	public Gui14(){
		mp = new Panel();
		//设置背景颜色
		mp.setBackground(Color.black);
		jb1 = new JButton("黑色");
		jb2 = new JButton("红色");
		
		add(jb1, BorderLayout.NORTH);
		add(mp);
		add(jb2, BorderLayout.SOUTH);
		
		
		//注册监听
		jb1.addActionListener(this);
		jb2.addActionListener(this);
		
		//事件源是jb1,jb2,事件监听者是gui14的对象
		
		//指定action命令
		jb1.setActionCommand("黑色");
		jb2.setActionCommand("红色");
		
		//设置窗体
		setSize(300, 200);
		setLocation(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	public static void main(String[] args) {
		Gui14 gui1 = new Gui14();
	}
	
	//对事件处理的方法
	@Override
	public void actionPerformed(ActionEvent e) {
		//判断是哪个按钮被点击
		if(e.getActionCommand().equals("黑色")){
			//System.out.println("黑色");
			mp.setBackground(Color.black);
			
		} else if(e.getActionCommand().equals("红色")){
			//System.out.println("红色");
			mp.setBackground(Color.red);
			
		} else {
			
		}
		
		
	}

}

class MyPanel2 extends JPanel{
	public void paint(Graphics g){
		
	}
}


/**
 * 1.通过上下左右键来控制一个小球的移动
 */
package com.gui;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Gui15 extends JFrame{
	//定义组件
	MyPanel3 mp =null;
	
	public Gui15(){
		mp = new MyPanel3();
		
		//mp加入JFrame
		add(mp);
		
		//添加监听
		addKeyListener(mp);
		
		//设置窗体
		setTitle("小球");
		setSize(400, 300);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		Gui15 gui1 = new Gui15();
	}

}

//定义自己的面板
class MyPanel3 extends JPanel implements KeyListener{
	private int x = 10;
	private int y = 10;
	
	public void paint(Graphics g){
		super.paint(g);
		//圆
		g.fillOval(x, y, 20, 20);
	}

	//输入的一个具体信息
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		//System.out.println("typed");
	}

	//按压
	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		//System.out.println("press");
		//向下 向上 向左 向右
		if(e.getKeyCode() == KeyEvent.VK_DOWN){
			y += 2;
		} else if(e.getKeyCode() == KeyEvent.VK_UP){
			y -= 2;
		} else if(e.getKeyCode() == KeyEvent.VK_LEFT){
			x -= 2;
		} else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
			x += 2;
		}
		//调用repaint()方法,重绘面板
		repaint();
	}

	//释放
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		//System.out.println("released" + (char)e.getKeyCode());
	}
}


java事件处理机制--深入理解

1、事件源

     事件源是一个产生(或触发)事件的对象,比如前面的JButton的一个对象jb1。当这个事件源对象的某些状态以某种方式发生变化时,就会产生某种类型的事件(一个事件源可能会生成多个不同类型的事件)。如果某个组件(对象)希望得到事件源产生的事件,就需要在这个事件源上注册。

2、事件

事件就是承载事件源状态改变时的信息对象。或者说,事件是事件源事件监听器传输事件源状态信息的载体。在用户与GUI组件进行交互时就会生成事件,比如当鼠标在面板中移动时,就会生成一个鼠标移动事件的对象,而这个对象保存着当前鼠标在面板中位置信息。java.awt.event包和javax.swing.event包中定义了各种事件类型,常见的事件类有:

事件类

说明

ActionEvent

通常在按下按钮,或双击一个列表项或选中某个菜单时发生

AdjustmentEvnet

当操作一个滚动条时发生

ComponentEvent

当一个组件隐藏、移动、改变大小时发送

ContainerEvent

当一个组件从容器中加入或者删除时发生

FocusEvent

当一个组件获得或是失去焦点时发生

ItemEvent

当一个复选框或是列表项被选中时,当一个选择框或选择菜单被选中

KeyEvent

当从键盘的按键被按下,松开时发生

MouseEvent

当鼠标被拖动、移动、点击、按下..

TextEvent

当文本区和文本域的文本发生改变时发生

WindowEvent

当一个窗口激活、关闭、失效、恢复、最小化...

3、事件监听器接口

     事件源产生一个事件,可以传送给事件监听者处理,那么怎样才能编写一个事件监听者呢?

     事件监听者实际上就是一个类,该类实现了某个事件监听器接口、比如前面我们案例中的MyPanel就是一个类,它实现了ActionListener接口,它就可以作为一个事件监听者,对接受到的事件进行处理。

     事件监听器接口有多种,不同的事件监听器接口可以监听不同的事件,一个类可以实现一个事件监听接口,也可以实现多个监听接口,这些接口在java.awt.event和javax.swing.event包中定义。

package com.gui;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Gui16 extends JFrame{
	//定义组件
	MyPanel4 mp = null;
	
	//构造方法
	public Gui16(){
		mp = new MyPanel4();
		
		//mp加入JFrame
		add(mp);
		//注册监听
		addMouseListener(mp);
		addKeyListener(mp);
		addMouseMotionListener(mp);
		
		//设置窗体
		setSize(400, 300);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public static void main(String[] args) {
		Gui16 gui1 = new Gui16();

	}

}

//1 鼠标按下输出坐标,移出,移入,按下,释放
//2.按键按下对应字符
//3.鼠标移动、拖拽
//4.窗口变化(关闭,最小化,最大化)
//定义自己的面板
class MyPanel4 extends JPanel implements MouseListener, KeyListener, MouseMotionListener, WindowListener{
	public void paint(Graphics g){
		super.paint(g);
	}
	//鼠标
	//鼠标点击
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("鼠标点击了 x = " + e.getX() + " y = " + e.getY());
	}
	//鼠标按下
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("鼠标按下");
	}
	//鼠标松开
	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("鼠标松开");
	}
	//鼠标移动到MyPanel4
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("鼠标移出");
	}
	//鼠标移出MyPanel4
	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("鼠标进入");
	}
	
	//鼠标拖拽
	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
		
	//鼠标移动
	@Override
	public void mouseMoved(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("鼠标当前坐标x = " + e.getX() + " Y = " + e.getY());
	}
	
	
	//键盘
	//输入具体信息
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
	//按下
	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		System.out.println(e.getKeyChar() + "键被按下");
	}
	//释放
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	
	//窗口
	//窗口打开
	@Override
	public void windowOpened(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	//窗口正在关闭
	@Override
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	//窗口关闭
	@Override
	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	//窗口最小化
	@Override
	public void windowIconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	//窗口最小化到显示
	@Override
	public void windowDeiconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	//窗口被激活了
	@Override
	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	//窗口变成非激活窗口
	@Override
	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub
	}
}

java事件处理机制--总结

总结--事件编程步骤:

1、编写事件处理类(事件监听者)

2、根据需求给事件处理类实现监听器接口

3、在事件处理中重写(实现)其事件处理的函数

4、在事件源类中指定该事件的监听器(响应者)是谁

 

注意事项:

1、java采用委托机制处理事件

2、java中的事件是分类的,比如对窗体事件、鼠标事件、按键事件、操作事件[按按钮]

3、java中一个类要监听某个事件,则必需实现相应的事件监听接口

4、事件监听接口有多种,程序员应当针对不同的情况,实现不同的监听接口,比如监听鼠标事件就应当实现MouseListener;要监听键盘事件,就应当实现KeyListener..

5、在实现监听接口的类(事件监听类/者)中,需要重写处理函数,比如实现了ActionListener接口,就应当重写actionPerformed(ActionEvent e),可以参考前面的事件监听器接口表格

6、在事件源中需要注册事件监听类。否则事件监听类接收不到事件源发生的事件。

 

一个类要实现监听的步骤:

a、实现相应的接口[KeyListener/MouseListener/ActionListener/WindowListener]

b、把接口的处理方法根据需要重新编写(Override)

c、在事件源上注册监听

d、事件传递是靠事件(类)对象



----------参考《韩顺平.循序渐进学.java.从入门到精通》

----------参考《JDK_API_1_6_zh_CN

Java学习笔记--导航http://blog.csdn.net/q547550831/article/details/49819641


  • 3
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
javaGUI图形界面 public class login extends JFrame { private JComboBox nameJComboBox; private JPanel userJPanel; private JLabel pictureJLabel; private JButton okJButton,cancelJButton; private JLabel nameJLabel,passwordJLabel,note; private JPasswordField passwordJPasswordField; private String name1; private String password1; private String user; private ImageIcon myImageIcon; public login( ) { createUserInterface(); // 调用创建用户界面方法 } private void createUserInterface() { Container contentPane = getContentPane(); contentPane.setLayout( null ); userJPanel = new JPanel(); userJPanel.setBounds( 35, 120, 300, 96 ); userJPanel.setBorder(BorderFactory.createEtchedBorder() ); //显示一圈边儿 userJPanel.setLayout( null ); contentPane.add( userJPanel ); nameJComboBox = new JComboBox(); nameJComboBox.setBounds( 100, 12, 170, 25 ); nameJComboBox.addItem( "admin" ); nameJComboBox.addItem( "aloie" ); nameJComboBox.setSelectedIndex( 0 ); nameJComboBox.setEditable(true); userJPanel.add( nameJComboBox ); pictureJLabel=new JLabel(); pictureJLabel.setBounds(45,0,380,118); pictureJLabel.setIcon(new ImageIcon("pic.gif")); contentPane.add(pictureJLabel); nameJLabel=new JLabel("姓 名:"); nameJLabel.setBounds(20,12,80,25); userJPanel.add(nameJLabel); passwordJPasswordField=new JPasswordField(); passwordJPasswordField.setBounds(100,60,170,25); userJPanel.add(passwordJPasswordField); passwordJLabel=new JLabel("密 码:"); passwordJLabel.setBounds(20,60,80,25); userJPanel.add(passwordJLabel); note=new JLabel("密码与用户名相同"); note.setBounds(0,295,180,25); add(note); okJButton=new JButton("登 陆"); okJButton.setBounds(60,250,80,25); contentPane.add(okJButton); okJButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { okJButtonActionPerformed(event); } } ); cancelJButton=new JButton("取 消"); cancelJButton.setBounds(210,250,80,25); contentPane.add(cancelJButton); cancelJButton.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { System.exit(0); //退出登陆 } } ); setTitle( "登陆窗口" ); setSize( 380, 350 ); setResizable( false ); //将最大化按钮设置为不可用 } private void okJButtonActionPerformed( ActionEvent event ) { //okJButton响应事件,检查用户名和密码的匹配 name1= nameJComboBox.getSelectedItem().toString(); if (name1.equals("admin") ) { if (passwordJPasswordField.getText().equals("admin")) { showNewWindow(); setVisible( false); } else { JOptionPane.showMessageDialog( this,"密码错误,拒绝登陆", "密码错误 !", JOptionPane.ERROR_MESSAGE ); } } else if (name1.equals("aloie")) { if ( passwordJPasswordField.getText().equals("aloie") ) { showNewWindow(); setVisible(false); } else { JOptionPane.showMessageDialog( this,"密码错误,拒绝登陆", "密码错误 !", JOptionPane.ERROR_MESSAGE ); } } } public void showNewWindow() { JFrame jf=new JFrame("main Frame"); jf.setSize(500,400); jf.setVisible(true); jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } public static void main( String[] args ) { JFrame.setDefaultLookAndFeelDecorated(true); login mylogin = new login( ); mylogin.setVisible( true ); mylogin.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值