图形界面编程
组件:
---------------
JButton:按钮
JTextField:单行文本域
JTextArea:多行文本区
JComboBox:下拉选择框
JList:列表
JRadioButton:单选按钮
JCheckBox:多选按钮 复选框
Border:边框
JEditorPane:显示格式化文本
JMenuBar JMenu JMenuItem 菜单
JPopupMenu:弹出式菜单
JToolBar:工具栏
JPasswordField:单行密码框
JTabbedPane:分层面板
JSplitPane:分隔面板
JTree:树
JTable:表格
JFileChooser:文件选择器
JSlider:滑动条
JProgressBar:进度条
JColorChooser:颜色选择器
代码:
--------------------------------------------------------------------------------
1.Frame
-----------
import javax.swing.*;
import java.awt.*;
public class TestFrame {
public static void main(String[] args) {
JFrame frame=new JFrame("HelloTarena");
frame.setLayout(null);
JPanel panel=new JPanel();
panel.setSize(300,200);
panel.setBackground(Color.red);
frame.add(panel);
frame.setSize(600,400);
frame.setVisible(true);
}
}
2. TextField/TextArea 组件应用
-----------------
import javax.swing.*;
import java.awt.*;
public class TestTextComponent {
public static void main(String[] args) {
JFrame frame=new JFrame("Hello");
frame.setSize(600,400);
JTextField jtf=new JTextField();
JTextArea jta=new JTextArea();
JScrollPane jsp=new JScrollPane(jta);
frame.add(jtf,"North");
frame.add(jsp);
frame.setVisible(true);
}
}
3. FlowLayout 布局
-----------------
import javax.swing.*;
import java.awt.*;
public class TestLayout {
public static void main(String[] args) {
JFrame frame=new JFrame("Hello");
frame.setSize(500,300);
LayoutManager lm=new FlowLayout();
frame.setLayout(lm);
JButton b1=new JButton("BUTTON1");
frame.add(b1);
JButton b2=new JButton("BUTTON2");
frame.add(b2);
frame.setVisible(true);
}
}
4. BorderLayout 布局
--------------------
import javax.swing.*;
import java.awt.*;
public class TestBorderLayout {
public static void main(String[] args) {
JFrame frame=new JFrame("Hello");
frame.setSize(600,400);
//frame.setLayout(new BorderLayout());
JButton b1=new JButton("b1");
JButton b2=new JButton("b2");
JButton b3=new JButton("b3");
JButton b4=new JButton("b4");
JButton b5=new JButton("b5");
frame.add(b1);
frame.add(b2,"North");
frame.add(b3,"South");
frame.add(b4,"East");
frame.add(b5,"West");
frame.setVisible(true);
}
}
5. GridLayout 布局
-------------------
import javax.swing.*;
import java.awt.*;
public class TestGridLayout {
public static void main(String[] args) {
JFrame frame=new JFrame("Hello");
frame.setSize(600,400);
frame.setLayout(new GridLayout(3,2));
JButton b1=new JButton("b1");
JButton b2=new JButton("b2");
JButton b3=new JButton("b3");
JButton b4=new JButton("b4");
JButton b5=new JButton("b5");
frame.add(b1);
frame.add(b2);
frame.add(b3);
frame.add(b4);
frame.add(b5);
frame.setVisible(true);
}
}
6. CardLayout 布局
---------------------
import java.awt.*;
import java.awt.event.*;
public class MyCard {
public static void main(String args[]) {
new MyCard().go();
}
public void go() {
final Frame f = new Frame("CardLayout Example");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent evt) {
f.setVisible(false);
f.dispose();
System.exit(0);
}
});
f.setSize(300, 100);
f.setLayout(new CardLayout(20,20));
final Frame f1 = f; // why set f1 final??
for(int i = 1; i <= 5; ++i) {
Button b = new Button("Button " + i);
b.setSize(100, 25);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
CardLayout cl = (CardLayout)f1.getLayout();
cl.next(f1);
}
} );
f.add(b, "button" + i);
}
f.setVisible(true);
}
}
7. GridBagLayout 布局
-------------------
import java.awt.*;
import java.util.*;
import java.awt.event.*;
public class MyGridBag extends Panel {
protected void makebutton(String name,GridBagLayout gridbag,GridBagConstraints c) {
Button button = new Button(name);
gridbag.setConstraints(button, c);
add(button);
}
public void go() {
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setFont(new Font("Helvetica", Font.PLAIN, 14));
setLayout(gridbag);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
makebutton("Button1", gridbag, c);
makebutton("Button2", gridbag, c);
makebutton("Button3", gridbag, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
makebutton("Button4", gridbag, c);
// c.weightx = 0.0; //reset to the default
makebutton("Button5", gridbag, c); //another row
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row
makebutton("Button6", gridbag, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
makebutton("Button7", gridbag, c);
c.gridwidth = 1; //reset to the default
c.gridheight = 2;
c.weighty = 1.0;
makebutton("Button8", gridbag, c);
// c.weighty = 0.0; //reset to the default
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.gridheight = 1; //reset to the default
makebutton("Button9", gridbag, c);
makebutton("Button10", gridbag, c);
setSize(300, 100);
}
public static void main(String args[]) {
final Frame f = new Frame("GridBag Layout Example");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent evt) {
f.setVisible(false);
f.dispose();
System.exit(0);
}
});
MyGridBag gb = new MyGridBag();
gb.go();
f.add("Center", gb);
f.pack();
f.setVisible(true);
}
}
java中的图形界面
GUI,图形化的用户接口,为了人机交互使用的。
构造图形界面的步骤
1,选择一个容器
2,设置容器的布局管理器
3,向容器添加组件
4,事件的监听
容器(Container)用于管理其他的组件的对象。组件必须放到容器里。
JFrame,这是一个最顶层的窗体容器,所有其他的组件必须放在顶层容器里。
JDialog 对话框容器,他要依附于其父组件,他不是一个顶层容器。
JPanel,他不是顶层容器,必须放在顶层容器中,任何一个容器都有add()方法,Panel面板
是透明的(默认)。他也是一个组件。
布局管理:对于任何一个容器类中都有setLayout()方法,用容器对象调用这个方法,来设
置容器的布局管理器(LayoutManager这是一个接口,所有布局管理器都实现了这个接口)
。
可用的布局管理器:
FlowLayout,流式布局管。Panel的默认布局管理就是FlowLayout。
BorderLayout,按方位进行布局管理,(North,South,East,West,Middle)不明确指定,就会默认加载在中间(Middle),
add(Component comp,String place)这个方法是在指定的位置添加组件。
GridLayout,网格布局,通过行列,间距,来用网格分割,把组件放入如网格中,先行后列摆放组件。
CardLayout,卡片布局,面板重叠放置。
GridBogLayout,组件可以跨行跨列的网格布局。
JButton :按钮
JTextField:单行文本域
JTextArea:多行文本区
JScrollPane:滚动窗体
JComboBox:下拉选择框
JRadioButton:单选按钮
JCheckBox:多选按钮
JList:多行列表
JLabel:标签
JPasswordField:密码输入框
JEditorPane:显示结构化文档
Border:边框
JMenuBar:菜单条
JMenu:菜单
JMenuItem:菜单项
JPopupMenu:弹出式菜单
JSlider:滑动条
JProgressBar:进度条
JTabbedPane:分层面板
JSplitPane:分隔面板
JToolBar:工具条
JFileChooser:文件选择器
JColorChooser:颜色选择器
显示对话框
JoptionPane 里面有很多静态方法可以弹出对话框
注意:具体的方法可以去参看Java2 SE的API文档。
awt事件模型(观察者模式)(重点)
事件模型中,包括事件源对象,事件处理者(事件监听者对象),事件对象。
事件源和事件处理者之间建立了授权关系,也就是在事件源类中有一个事件处理者的对象作为属性,也可能是一个事件处理者的集合。
事件对象
事件源————————〉事件处理者
这就是事件模型的机制,也就是由事件源对象发送一个消息(事件对象),然后事件处理者调用相应的方法处理事件。
首先了解一下什么是发消息:A,B,C三个类,分别作为事件源,事件处理者,事件对象。在A类中有一个B类的属性或者是一个内容为B类对
象的集合,也就是事件源和事件处理者之间的建立了授权关系,在B类需要实现一个自定义的接口,这个自定义的接口继承了EventListener
,EventListener接口中没有定义任何方法,这只是一个标记接口。实现在自定义接口中定义好的用于事件处理的方法,C类要继承EventObject类。这些方法是以事件对象为参数的b(C c),而后在A类a(C c)方法中使用B类的对象调用B类中的b(C c)方法,并把事件对象作为参数,并在main方法中用A类的对象调用了a(c)方法,这也就叫做A类对象给B类发送了消息。
例子如下:
import java.util.*;
class A{
private String test;
private List li=new ArrayList();
public A(String test){
this.test=test;
}
public String getTest(){return this.test;}
public void addB(B b){
this.li.add(b);
}
public void removeB(B b){
this.li.remove(b);
}
public void fire(C c){
Iterator it=li.iterator();
while(it.hasNext()){
B b=(B)it.next();
b.b(c);
}
}
}
interface Blistener extends EventListener{
void b(C c);
}
class B implements Blistener{
public void b(C c){
A a=(A)c.getSource();
System.out.println(a.getTest()+" "+c.getMessage());
}
}
class C extends EventObject{
private String message;
public C(Object src){
super(src);
}
public void setMessage(String message){
this.message=message;
}
public String getMessage(){return this.message;}
}
public class Test{
public static void main(String[] args){
A a1=new A("Event");
B b1=new B();
C c1=new C(a1);
c1.setMessage("Test");
a1.add(b1);
a1.fire(c1);
}
}
以上代码只是事例,在引入包之后可以运行。
事件对象继承自EventObject类,并可以通过getSource()方法获得事件源对象,当然需要在构造事件对象时将事件源对象传入。
day 10
============
代码:
--------------------------------------------------------------------------------
1.分数池
---------------------
import java.util.*;
class FenShu{
//key:Double value:FenShu
static Map pool=new HashMap();
public static FenShu getFenShu(double fenzi,int fenmu){
Double d=new Double(fenzi/fenmu);
if (pool.containsKey(d)){
return (FenShu)pool.get(d);
}
else{
FenShu fs=new FenShu((int)fenzi,fenmu);
pool.put(d,fs);
return fs;
}
}
public static void main(String[] args){
FenShu fs1=new FenShu(1,2);
FenShu fs2=new FenShu(1,3);
System.out.println(fs1.add(fs2));
System.out.println(fs1.substract(fs2));
System.out.println(fs1.multiply(fs2));
System.out.println(fs1.divide(fs2));
}
private int fenzi;
private int fenmu;
public FenShu(int fenzi,int fenmu){
this.fenzi=fenzi;
this.fenmu=fenmu;
yueFen();
}
private void yueFen(){
int r;
if (fenzi<fenmu) r=fenzi;
else r=fenmu;
for(int i=r;i>=1;i--){
if (fenzi%i==0 && fenmu%i==0){
fenzi/=i;
fenmu/=i;
break;
}
}
}
public int getFenZi(){
return this.fenzi;
}
public int getFenMu(){
return this.fenmu;
}
public FenShu add(FenShu fs){
int newFenMu=this.fenmu*fs.getFenMu();
int newFenZi=this.fenmu*fs.getFenZi()+this.fenzi*fs.getFenMu();
return getFenShu(newFenZi,newFenMu);
}
public FenShu substract(FenShu fs){
int newFenMu=this.fenmu*fs.getFenMu();
int newFenZi=this.fenzi*fs.getFenMu()-this.fenmu*fs.getFenZi();
return getFenShu(newFenZi,newFenMu);
}
public FenShu multiply(FenShu fs){
int newFenMu=this.fenmu*fs.getFenMu();
int newFenZi=this.fenzi*fs.getFenZi();
return getFenShu(newFenZi,newFenMu);
}
public FenShu divide(FenShu fs){
int newFenMu=this.fenmu*fs.getFenZi();
int newFenZi=this.fenzi*fs.getFenMu();
return getFenShu(newFenZi,newFenMu);
}
public String toString(){
return fenzi+"/"+fenmu;
}
}
2. 计算器界面
-----------------
import javax.swing.*;
import java.awt.*;
public class MyCalculator {
JFrame frame;
JTextField jtf;
JButton[] jbs=new JButton[15];
public MyCalculator(){
init();
}
public void init(){
frame=new JFrame("MyCalculator");
frame.setSize(400,300);
jtf=new JTextField();
jtf.setEditable(false);
frame.add(jtf,"North");
JPanel panel=new JPanel();
for(int i=0;i<10;i++){
jbs[i]=new JButton(i+"");
}
jbs[10]=new JButton("+");
jbs[11]=new JButton("-");
jbs[12]=new JButton("*");
jbs[13]=new JButton("/");
jbs[14]=new JButton("=");
panel.setLayout(new GridLayout(5,3));
for(int i=0;i<5;i++){
panel.add(jbs[i*2]);
panel.add(jbs[i*2+1]);
panel.add(jbs[i+10]);
}
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
new MyCalculator();
}
}
-------------------
事件模型
三种角色: 事件源 事件对象 事件监听器
事件源 和 事件监听器 事先建立授权关系
当事件条件满足的时候,事件源会给事件监听器发送一个事件对象,由事件监听器去处理
事件源和事件监听器是完全弱耦合的
事件源可以是多种事件的事件源
事件源可以注册多个监听器
监听器可以注册在多个事件源当中
事件对象中会封装事件源对象
事件对象继承java.util.EventObject
监听接口继承java.util.EventListener 每一个方法都会以相应的事件对象作为参数
事件源以事件对象作为参数,调用监听器的相应的方法
事件源 提供addXXXListener removeXXXListener
代码:
--------------------------------------------------------------------------------
3. 事件模型工作原理示例程序
--------------------------
import java.util.*;
public class TestGirl {
public static void main(String[] args) {
Girl g1 = new Girl("ZhangLF");
EmotionListener b1 = new Boy1("Huxz");
EmotionListener b2 = new Boy2("Liucy");
g1.addEmotionListener(b1);
g1.addEmotionListener(b2);
// g1.addEmotionListener(b1);
g1.fire();
g1.removeEmotionListener(b2);
System.out.println();
g1.fire();
}
}
class EmotionEvent extends EventObject {
public EmotionEvent(Object src) {
super(src);
}
}
// 定义标准
interface EmotionListener extends EventListener {
void whatCanIdoWhenGirlHappy(EmotionEvent e);
void whatCanIdoWhenGirlSad(EmotionEvent e);
}
// 使用标准
class Girl {
private String name;
// element:EmotionListener
private Set bfs = new HashSet();
public Girl(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void addEmotionListener(EmotionListener listener) {
bfs.add(listener);
// System.out.println(name+" said:我终于嫁出去了");
}
public void removeEmotionListener(EmotionListener listener) {
bfs.remove(listener);
}
public void fire() {
EmotionEvent e = new EmotionEvent(this);
for (int day = 1; day <= 10; day++) {
Iterator it = bfs.iterator();
while (it.hasNext()) {
EmotionListener bf=(EmotionListener)(it.next());
if (day % 2 == 0) {
bf.whatCanIdoWhenGirlHappy(e);
} else {
bf.whatCanIdoWhenGirlSad(e);
}
}
}
}
}
// 实现标准
class Boy1 implements EmotionListener {
String name;
public Boy1(String name) {
this.name = name;
}
public void whatCanIdoWhenGirlHappy(EmotionEvent e) {
Object src = e.getSource();
Girl g = (Girl) src;
System.out.println(name + " said:" + g.getName()
+ ",You Happy,I Happy!");
}
public void whatCanIdoWhenGirlSad(EmotionEvent e) {
Object src = e.getSource();
Girl g = (Girl) src;
System.out.println(name + " said:" + g.getName() + ",You Sad,I Sad!");
}
}
class Boy2 implements EmotionListener {
String name;
public Boy2(String name) {
this.name = name;
}
public void whatCanIdoWhenGirlHappy(EmotionEvent e) {
Object src = e.getSource();
Girl g = (Girl) src;
System.out.println(name + " said:" + g.getName()
+ ",You Happy,I can make you Sad!");
}
public void whatCanIdoWhenGirlSad(EmotionEvent e) {
Object src = e.getSource();
Girl g = (Girl) src;
System.out.println(name + " said:" + g.getName()
+ ",You Sad,I am very happy!");
}
}
代码:
--------------------------------------------------------------------------------
4. MouseAdapter / WindowAdapter类的使用,可以使监听器选择地实现类中的方法.
------------------
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestFrame {
public static void main(String[] args) {
JFrame frame=new JFrame("HeHe");
frame.setSize(600,400);
/*
class MyMouseListener extends MouseAdapter{
public void mouseClicked(MouseEvent arg0) {
System.out.println("鼠标点击");
}
}
MouseListener l=new MyMouseListener();
*/
frame.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent arg0) {
System.out.println("鼠标点击");
}
});
/*
class MyWindowListener extends WindowAdapter{
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
}
frame.addWindowListener(new MyWindowListener());
*/
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
5. ActionEvent/ActionListener (适用组件: JButton/JTextField/JList/JMenuItem)
setActionCommand()/getActionCommand()方法的使用
------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestActionListener {
public static void main(String[] args) {
JFrame frame=new JFrame("hehe");
frame.setSize(400,300);
frame.setLayout(new FlowLayout());
class MyListener implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println(e.getActionCommand());
}
}
ActionListener al=new MyListener();
JButton b1=new JButton("OK");
JButton b2=new JButton("OK");
JTextField jtf=new JTextField(15);
b1.setActionCommand("OK1");
b2.setActionCommand("OK2");
jtf.setActionCommand("TextField");
b1.addActionListener(al);
b2.addActionListener(al);
jtf.addActionListener(al);
frame.add(b1);
frame.add(b2);
frame.add(jtf);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
事件模型知识点概要:
--------------------
awt事件模型(观察者模式)(重点)
事件模型中,包括事件源对象,事件处理者(事件监听者对象),事件对象。
事件源和事件处理者之间建立了授权关系,也就是在事件源类中有一个事件处理者的对象作
为属性,也可能是一个事件处理者的集合。
事件对象
事件源————————〉事件处理者
这就是事件模型的机制,也就是由事件源对象发送一个消息(事件对象),然后事件处理者
调用相应的方法处理事件。
在事件监听器接口中定义的方法,都要以事件对象为参数。
一个事件源可以注册多个同类型的监听器,也可以注册多种多个事件监听器,一个事件监听
器也可以为多个事件源服务。
首先了解一下什么是发消息:A,B,C三个类,分别作为事件源,事件处理者,事件对象。
在A类中有一个B类的属性或者是一个内容为B类对象的集合,也就是事件源和事件处理者之
间的建立了授权关系,在B类需要实现一个自定义的接口,这个自定义的接口继承了EventLi
stener,EventListener接口中没有定义任何方法,这只是一个标记接口。实现在自定义接口中定义好的用于事件处理的方法,C类要继承EventObject
类。这些方法是以事件对象为参数的b(C c),而后在A类a(C c)方法中使用B类的对象调用B类中的b(C c)方法,并把事件对象作为参数,并在main方法
中用A类的对象调用了a(c)方法,这也就叫做A类对象给B类发送了消息。
也就是说事件源对象间接调用了事件监听器的方法,并以事件对象为实参传到事件监听器的方法中,要就叫事件源给事件监听器的方法发了一个消息(事件对象)。
例子如下:
import java.util.*;
//事件源类
class A{
private String test;
private List li=new ArrayList();
public A(String test){
this.test=test;
}
public String getTest(){return this.test;}
public void addB(B b){
this.li.add(b);
}
public void removeB(B b){
this.li.remove(b);
}
public void fire(){
C c=new C(this);
Iterator it=li.iterator();
while(it.hasNext()){
B b=(B)it.next();
b.b(c);
}
}
}
//事件监听器的接口,要继承EventListener标记接口
interface Blistener extends EventListener{
void b(C c);
}
//事件监听器,实现接口
class B implements Blistener{
public void b(C c){
A a=(A)c.getSource();
System.out.println(a.getTest()+" "+c.getMessage());
}
}
//事件对象类
class C extends EventObject{
private String message;
public C(Object src){
super(src);
}
public void setMessage(String message){
this.message=message;
}
public String getMessage(){return this.message;}
}
public class Test{
public static void main(String[] args){
A a1=new A("Event");
B b1=new B();
c1.setMessage("Test");
a1.addB(b1);//注册监听器
a1.fire();//发送事件
}
}
以上代码只是事例,在引入包之后可以运行。
事件对象继承自EventObject类,并可以通过getSource()方法获得事件源对象,当然需要在构造事件对象时将事件源对象传入,来区分是哪个事件源发
出的事件,所以要用事件对象作为参数。
事件源,事件对象,监听接口,在java.awt包中提供了很多已经定义好的,只需要实现监听接口就好了。
在Java的图形编程中,所有动作(事件)都已经提供了相应的事件对象和事件监听接口,例如:实现窗口的关闭按钮,点击关闭按钮会发出相应的事件对象,相应的调用监听器中实现好的方法。相应的方法清参阅Java2 SE API帮助文档。
缺省适配模式,通过一个抽象类实现接口,抽象类中的接口方法实现,都是一个无意义的空实现,可以继承这个抽象类,只覆盖向覆盖的方法就可以了。
在java.awt.event包中,会有一些适配类,也就是把相应的XXXListener,换成XXXAdapter就是适配类。
在java.awt.event包中的ActionEvent类,在以下操作中会发送这个事件,
1,JButton组件,按钮被点击
2,JTextField组件,在单行文本域中按Enter键。
3,JCheckBox组件,选中了复选框。
4,JRadioButton组件,选中了单选按钮。
5,JMenu组件,选中菜单项。
===================
代码:
--------------------------------------------------------------------------------
1. 计算器的分析与设计:
-------------------
append:判断添加模式还是改写模式
result:存放第一操作数
operator:存放运算符
tf:显示 存放第二操作数
12+34=
1:tf:1 append=true
2: tf:12 append=true
+: tf:12 append=false result=12 operator='+'
3: tf:3 append=true
4: tf:34 append=true
=: 运算 tf:46 append=false
12+34*2=
1:tf:1 append=true
2: tf:12 append=true
+: tf:12 append=false result=12 operator='+'
3: tf:3 append=true
4: tf:34 append=true
*: 运算 tf:46 result=46 operator='*' append=false
2: tf:2 append=true
=:运算 tf:92
-----------------
实现:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyCalculator {
JFrame frame;
JTextField jtf;
JButton[] jbs=new JButton[15];
boolean append=false;
double result;
char operator='=';
class NumberListener implements ActionListener{
public void actionPerformed(ActionEvent e){
String text=e.getActionCommand();
if (append){
String s=jtf.getText();
jtf.setText(s+text);
}
else{
jtf.setText(text);
}
append=true;
}
}
class OperatorListener implements ActionListener{
public void actionPerformed(ActionEvent e){
String s=e.getActionCommand();
char o=s.charAt(0);
if (!append && o!='='){
operator=o;
return;
}
append=false;
double tf=Double.parseDouble(jtf.getText());
switch(operator){
case '+':result+=tf;break;
case '-':result-=tf;break;
case '*':result*=tf;break;
case '/':result/=tf;break;
case '=':result=tf;
}
jtf.setText(result+"");
operator=o;
}
}
public MyCalculator(){
init();
}
public void init(){
frame=new JFrame("MyCalculator");
frame.setSize(400,300);
jtf=new JTextField();
jtf.setEditable(false);
jtf.setText("0");
frame.add(jtf,"North");
ActionListener number=new NumberListener();
ActionListener oper=new OperatorListener();
JPanel panel=new JPanel();
for(int i=0;i<10;i++){
jbs[i]=new JButton(i+"");
jbs[i].addActionListener(number);
}
jbs[10]=new JButton("+");
jbs[11]=new JButton("-");
jbs[12]=new JButton("*");
jbs[13]=new JButton("/");
jbs[14]=new JButton("=");
for(int i=10;i<15;i++){
jbs[i].addActionListener(oper);
}
panel.setLayout(new GridLayout(5,3));
for(int i=0;i<5;i++){
panel.add(jbs[i*2]);
panel.add(jbs[i*2+1]);
panel.add(jbs[i+10]);
}
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
new MyCalculator();
}
}
----------------------------
day 11
===================
Java多线程编程
这里要先回忆一下进程,即运行中的程序,多任务操作系统中并发的一个任务(CPU是分时间片执行多个进程的),线程,其本质是进程中顺序的执行流程,进程有独立的进程空间进程中的数据存放空间(对空间和栈空间)是独立的。线程没有独立的存放数据的空间,他们的数据存储空间(堆空间)是共享的,线程间的栈空间是独立的,线程消耗的资源也比进程小。
线程,是进程(运行中的程序)中顺序的执行流程,进程可以划分出多个线程。(一个进程运行过程中的多个程序)
JVM(java虚拟机)本身就是一个进程,java只能够申请创建线程。
操作系统决定线程是否有优先级,独占式的操作系统中系统会有优先级的概念,共享式的操作系统则不会优先级的。
Java中的线程也是对象,线程类是Thread类,线程是操作系统创建并进行维护的资源,线程对象只能表示一个线程,他本身不是线程。只能通过线程对象来申请创建,中止线程,访问底层的线程资源。
线程包含了三部分,cpu资源,代码,数据存储空间。
线程对象调用start()方法,线程对象就会向操作系统申请线程启动,除了申请的线程,还有main方法的线程,也就是主线程。
注意:只有运行状态的线程才有机会执行代码,主线程的中止不会影响其他的正在运行中的线程,朱线程中止也就是main()方法退出了。只有进程中的所有线程都中止时,进程(JVM进程)才会退出,只要有线程没有中止,进程就不会退出。
线程编程的两种方法
1,写一个类,继承Thread类,覆盖Thread类中继承来的run()方法,这样就写好了自定义的线程类。
2,写一个类,实现Runable接口,实现其中的run()方法。这种方法写好的类的对象需要作为线程类创建对象时构造方法的参数。
1,
Thread t=new a();
class a extends Thread{
public void run(){
...
}
}
2,
Runable r=new b();//目标对象
Thread t=new Thread(r);//用目标对象构造线程对象
class b implements Runable{
public void run(){
...
}
}
Thread的方法
public static void sleep(long millis)
throws InterruptedException
括号中以毫秒为单位, 使线程停止一段时间,间隔期满后,线程不一定立即恢复执行。
当main()运行完毕,即使在结束时时间片还没有用完,CPU也放弃此时间片,继续运行其他程序。
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace(e);
}
public final void join() throws InterruptedException
表示其他运行线程放弃执行权,进入阻塞状态,直到调用线程结束。
实际上是把并发的线程变为串行运行。
线程的优先级:1-10,越大优先级越高,优先级越高被OS选中的可能性就越大。(不建议使用,因为不同操作系统的优先级并不相同,使得程序不具备跨平台性,这种优先级只是粗略地划分)。
注:程序的跨平台性:除了能够运行,还必须保证运行的结果。
Public static void field()
使当前线程马上交出执行权,回到可运行状态,等待OS的再次调用。
Public final Boolean isActive()
验证当前线程是否是活动的,不管它是否正在运行。
线程的生命周期
下面为线程中的7中非常重要的状态:(有的书上也只有认为前五种状态:而将“锁池”和“等待池”都看成是“阻塞”状态的特殊情况:这种认识也
是正确的,但是将“锁池”和“等待池”单独分离出来有利于对程序的理解)
1,初始状态,线程创建,线程对象调用start()方法。
2,可运行状态,也就是等待Cpu资源,等待运行的状态。
3,运行状态,获得了cpu资源,正在运行状态。
4,阻塞状态,也就是让出cpu资源,进入一种等待状态,而且不是可运行状态,有三种情况会进入阻塞状态。
1)如等待输入(输入设备进行处理,而CUP不处理),则放入阻塞,直到输入完毕,阻塞结束后会进入可运行状态。
2)线程休眠,线程对象调用sleep()方法,阻塞结束后会进入可运行状态。
3)线程对象2调用线程对象1的join()方法,那么线程对象2进入阻塞状态,直到线程对象1中止。
5,中止状态,也就是执行结束。
6,锁池状态
7,等待队列
共享数据的并发处理
两个线程同时访问的资源叫做临界资源。两个线程同时访问对象并要求操作相同资源时打断了原子操作就会出现问题。(原子操作,不可再分的操作)
两个线程修改共享资源时会出现数据的不一致,为避免这种现象采用对访问的线程做限制的方法。
互斥锁机制,利用每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个琐是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程。
1.Synchronized修饰代码块(同步代码块),
public void push(char c){
synchronized(this)//只有持有当前对象的锁标记才能访问这个代码块
{
...
}
}
对括号内的对象加锁,只有拿到锁标记的对象才能执行该代码块
2.Synchronized修饰方法
public synchronized void push(char c) {
...
}
对当前对象的加锁,只有拿到锁标记的对象才能执行该方法。
注意:构造方法不能Synchronized修饰,静态方法可以用Synchronized修饰(是对类对象加锁,类对象会在反射时讲到)。抽象方法不能用Synchronized修饰,不影响子类覆盖,子类在覆盖这个方法是可以加Synchronized,也可以不加Synchronized,所以根据Java不允许写废代码的特点是不能写在一起。
注意:对当前对象加锁,一个代码块或者方法是同步的(Synchronized),当前对象的锁标记没有分配出去时,有一个线程来访问这个代码块时,就会的到这个对象的锁标记,直到这个线程结束才会释放着个锁标记,其他想访问这个代码块或者是方法线程就会进入这个对象锁池,如果没有得到当前对象的锁标记,就不能访问这个代码块或者是方法。
注:方法的Synchronized特性本身不会被继承,只能覆盖。
线程因为未拿到锁标记而发生阻塞进入锁池(lock pool)。每个对象都有自己的一个锁池的空间,用于放置等待运行的线程。由系统决定哪个线程拿到锁标记并运行。
使用互斥锁的注意事项
举例:男孩和女孩例子,每个女孩是一个对象,每个男孩是个线程。每个女孩都有自己的锁池。每个男孩可能在锁池里等待。
Class Girl{
Public void hand(){
}
Public syncronized void kiss(){
}
}
Class Boy extends Thread{
Public void run(){
}
}
互相持有对方线程想要获得的锁标记,就会造成死锁。
没有获得加锁对象的锁标记的线程,不能访问只有获得该对象所标记才能访问的同步方法,但可以访问这个对象的非同步的方法。
死锁的两种处理方法
统一排列锁顺序(解决不同方法中对多个共享资源的访问)
对象1的方法
synchronized(a)
synchronized(b)
对象2的方法
synchronized(a)
synchronized(b)
注意:只读不用加同步,只写也不用加同步,只有读写操作兼而有之时才加同步。
注:在java.io包中Vector 和 HashTable 之所以是线程安全的,是因为每个方法都有synchronized修饰。Static 方法可以加 synchronized , 锁的是类对象。但是Vector 是 jdk 1.0 的 ArrayList 是 jdk1.2 所以实际应用还是使用ArrayList。
------------------
1. 线程类的两种实现方法:
-----------
public class TestThread {
public static void main(String[] args) {
Thread t1=new ThreadA();
Thread t2=new ThreadB();
Runnable target=new Target();
Thread t3=new Thread(target);
t1.start();
t2.start();
t3.start();
}
}
// 继承Thread 类
class ThreadA extends Thread{
public void run(){
for(int i=1;i<=1000;i++){
System.out.println(i+" $$$");
}
}
}
class ThreadB extends Thread{
public void run(){
for(int i=1;i<=1000;i++){
System.out.println(i+" ###");
}
}
}
//创建目标类,实现Runnable 接口
class Target implements Runnable{
public void run(){
for(int i=1;i<=1000;i++){
System.out.println(i+" %%%");
}
}
}
2. Thread 类中,sleep(),john()方法的使用
--------------------
public class TestPrintThread {
public static void main(String[] args) {
Thread t1=new NThread();
Thread t2=new CThread(t1);
//t1.setPriority(Thread.MAX_PRIORITY);
//t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
}
}
class NThread extends Thread{
public void run(){
for(int i=1;i<=26;i++){
System.out.println(i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class CThread extends Thread{
Thread t;
public CThread(Thread t) {
this.t = t;
}
public void run(){
for(char c='A';c<='Z';c++){
System.out.println(c);
try {
Thread.sleep(200);
if (c=='M') t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3. Synthonsizned 修饰符的使用 (利用对象锁机制实现线程的同步)
---------------------
public class TestSynchronized {
public static void main(String[] args) {
MyStack ms=new MyStack();
ms.push('A');
ms.push('B');
Thread t1=new PushThread(ms);
Thread t2=new PopThread(ms);
t1.start();
t2.start();
}
}
class MyStack{
private char data[]=new char[6];
private int index=0;
public synchronized void push(char c){
System.out.println(c+" pushed!");
data[index]=c;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
index++;
print();
}
public synchronized void pop(){
index--;
System.out.println(data[index]+" poped!");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
data[index]=' ';
print();
}
public void print(){
for(int i=0;i<data.length;i++){
System.out.print(data[i]+"/t");
}
System.out.println();
}
}
class PushThread extends Thread{
MyStack ms;
public PushThread(MyStack ms) {
this.ms = ms;
}
public void run(){
// synchronized(ms){
ms.push('C');
// }
}
}
class PopThread extends Thread{
MyStack ms;
public PopThread(MyStack ms) {
this.ms = ms;
}
public void run(){
// synchronized(ms){
ms.pop();
// }
}
}
/*
synchronized(o){
}
public synchronized void m(){
}
public void m(){
synchronized(this){
}
}