Java GUI

一、awt 

1、容器

(1)、window

默认为边框布局

package container;

import java.awt.*;

public class windowDemo {
    public static void main(String[] args) {

        Frame frame = new Frame("window测试");
        frame.setBounds(100,100,800,600);
        frame.setVisible(true);
    }
}

(2)、Panel

默认为流式布局(默认为居中对齐)

package container;

import java.awt.*;

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        Frame frame = new Frame("展示Panel");
        Panel panel = new Panel();
        panel.add(new TextField("测试文本"));
        panel.add(new Button("测试按钮"));
        frame.add(panel);
        frame.setBounds(100,100,500,800);
        frame.setVisible(true);
    }
}

(3)、ScrollPane

默认为边框布局

package container;

import java.awt.*;

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        Frame frame = new Frame("展示ScrollPane");

        //有参数 SCROLLBARS_ALWAYS 时一直有滚动条,没有时只有窗口装不下内容时才有滚动条。
        ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);

        sp.add(new TextField("测试文本"));
        sp.add(new Button("测试按钮"));

        frame.add(sp);

        frame.setBounds(100,100,500,300);
        frame.setVisible(true);
    }
}

(4)、Box(swing中的) 

package container;

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

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        //默认为边框布局
        Frame frame = new Frame("演示BoxLayout");

        Box horizontalBox = Box.createHorizontalBox();
        horizontalBox.add(new Button("水平按钮一"));
        horizontalBox.add(new Button("水平按钮二"));

        Box verticalBox = Box.createVerticalBox();
        verticalBox.add(new Button("垂直按钮一"));
        verticalBox.add(new Button("垂直按钮二"));

        frame.add(horizontalBox);
        frame.add(verticalBox,BorderLayout.SOUTH);


        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}

package container;

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

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        //默认为边框布局
        Frame frame = new Frame("演示BoxLayout");

        Box horizontalBox = Box.createHorizontalBox();
        horizontalBox.add(new Button("水平按钮一"));
        horizontalBox.add(Box.createHorizontalGlue());
        horizontalBox.add(new Button("水平按钮二"));
        horizontalBox.add(Box.createHorizontalStrut(30));
        horizontalBox.add(new Button("水平按钮三"));

        Box verticalBox = Box.createVerticalBox();
        verticalBox.add(new Button("垂直按钮一"));
        verticalBox.add(Box.createVerticalGlue());
        verticalBox.add(new Button("垂直按钮二"));
        verticalBox.add(Box.createVerticalStrut(30));
        verticalBox.add(new Button("垂直按钮三"));

        frame.add(horizontalBox,BorderLayout.NORTH);
        frame.add(verticalBox);
        
        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}

2、LayoutManager(布局管理器)

(1)、FlowLayout(流式布局)

package container;

import java.awt.*;

public class Demo {
    public static void main(String[] args) {

        //所有容器都不能离开window独立存在
        Frame frame = new Frame("展示FlowLayout");

        frame.setLayout(new FlowLayout(FlowLayout.LEFT,20,20));

        for (int i = 1; i <= 100; i++) {
            frame.add(new Button("按钮" + i));
        }
        
        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}

(2)BorderLayout(边框布局)

package container;

import java.awt.*;

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        Frame frame = new Frame("展示BorderLayout");

        frame.setLayout(new BorderLayout(30,10));

        frame.add(new Button("北侧按钮"), BorderLayout.NORTH);
        frame.add(new Button("南侧按钮"), BorderLayout.SOUTH);
        frame.add(new Button("西侧按钮"), BorderLayout.WEST);
        frame.add(new Button("东侧按钮"), BorderLayout.EAST);
        frame.add(new Button("中间按钮"), BorderLayout.CENTER);

        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}
细节:

           当向某个区域放入多个组件时,只会显示 最后一个

           不指定组件放入哪个区域,默认放入中间

           当某个区域没有添加组件时,该区域并不会空闲出来,而是会被其它组件占据

           向一个区域放多个组件,先将组件放入一个Panel中,在将Panel放入该区域

(3)Gridlayout(网格布局)

package container;

import java.awt.*;

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        //默认为边框布局
        Frame frame = new Frame("计算器");

        //默认流式布局
        Panel p1 = new Panel();
        //设置TextField最多容纳对少字符
        p1.add(new TextField(30));
        frame.add(p1,BorderLayout.NORTH);

        Panel p2 = new Panel();
        p2.setLayout(new GridLayout(3,5,4,4));
        for (int i = 0; i < 10; i++) {
            p2.add(new Button(i + ""));
        }
        p2.add(new Button("+"));
        p2.add(new Button("-"));
        p2.add(new Button("*"));
        p2.add(new Button("/"));
        p2.add(new Button("."));

        //默认放到中间
        frame.add(p2);
        
        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}

(4)、GridBaglayout(网格包布局)

(5)、CardLayout(卡片布局)

package container;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        //默认为边框布局
        Frame frame = new Frame("演示CardLayout");

        Panel p1 = new Panel();
        CardLayout cardLayout = new CardLayout();
        p1.setLayout(cardLayout);
        String[] names = {"第一张","第二张","第三张","第四张","第五张"};
        for (int i = 0; i < names.length; i++) {
            p1.add(names[i],new Button(names[i]));
        }

        frame.add(p1);

        Panel p2 = new Panel();

        Button b1 = new Button("上一张");
        Button b2 = new Button("下一张");
        Button b3 = new Button("第一张");
        Button b4 = new Button("最后一张");
        Button b5 = new Button("第三张");

        ActionListener listener = new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();//获得的字符串就是按钮上的文字

                switch (actionCommand){
                    case "上一张":
                        cardLayout.previous(p1);
                        break;
                    case "下一张":
                        cardLayout.next(p1);
                        break;
                    case "第一张":
                        cardLayout.first(p1);
                        break;
                    case "最后一张":
                        cardLayout.last(p1);
                        break;
                    case "第三张":
                        cardLayout.show(p1,"第三张");
                        break;
                }
            }
        };

        b1.addActionListener(listener);
        b2.addActionListener(listener);
        b3.addActionListener(listener);
        b4.addActionListener(listener);
        b5.addActionListener(listener);

        p2.add(b1);
        p2.add(b2);
        p2.add(b3);
        p2.add(b4);
        p2.add(b5);

        frame.add(p2,BorderLayout.SOUTH);
        
        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}

(6)、BoxLayout(盒子布局)

package container;

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

public class Demo {
    public static void main(String[] args) {

        //panel等所有容器都不能离开window独立存在
        //默认为边框布局
        Frame frame = new Frame("演示BoxLayout");

        BoxLayout boxLayout = new BoxLayout(frame, BoxLayout.Y_AXIS);

        frame.setLayout(boxLayout);

        frame.add(new Button("按钮一"));
        frame.add(new Button("按钮二"));

        //设置最佳大小
        frame.pack();

        frame.setVisible(true);
    }
}

3、AWT中常用组件

演示:写出以下画面

package container;

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

public class Demo {

    Frame frame = new Frame("测试基本组件");

    TextArea ta = new TextArea(5,20);

    Choice choiceColor = new Choice();

    //把两个male、female放入一个分组
    CheckboxGroup cbg = new CheckboxGroup();
    //默认选中
    Checkbox male = new Checkbox("男",cbg,true);
    Checkbox female = new Checkbox("女",cbg,false);

    Checkbox isMarray = new Checkbox("是否已婚?");

    TextField tf = new TextField(50);
    Button ok = new Button("确认");

    //一共几行,能否多选
    List colorList = new List(6,true);

    //用来组装界面
    public Demo(){

        //最下面
        Box hbox = Box.createHorizontalBox();
        hbox.add(tf);
        hbox.add(ok);

        frame.add(hbox,BorderLayout.SOUTH);

        //左上
        choiceColor.add("红色");
        choiceColor.add("绿色");
        choiceColor.add("蓝色");
        Box hbox2 = Box.createHorizontalBox();
        hbox2.add(choiceColor);
        hbox2.add(male);
        hbox2.add(female);
        hbox2.add(isMarray);

        Box vbox = Box.createVerticalBox();
        vbox.add(ta);
        vbox.add(hbox2);

        //左上+右上
        colorList.add("红色");
        colorList.add("绿色");
        colorList.add("蓝色");
        Box hbox3 = Box.createHorizontalBox();
        hbox3.add(vbox);
        hbox3.add(colorList);

        frame.add(hbox3);

        frame.pack();
        frame.setVisible(true);

    }

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

4、Dialog(对话框)

注意: 

模式对话框:在对话框关闭之前无法操作父窗口 

非模式对话框:在对话框关闭之前也可以操作父窗口 

向对话框中加入组件与Frame中相同

package container;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    public static void main(String[] args) {
        Frame frame = new Frame("测试Dialog");

        Dialog d1 = new Dialog(frame,"模式对话框",true);
        Dialog d2 = new Dialog(frame,"非模式对话框",false);

        d1.setBounds(20,20,300,200);
        d2.setBounds(20,20,300,200);

        Button b1 = new Button("打开模式对话框");
        Button b2 = new Button("打非开模式对话框");

        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                d1.setVisible(true);
            }
        });

        b2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                d2.setVisible(true);
            }
        });

        frame.add(b1,BorderLayout.NORTH);
        frame.add(b2);

        frame.pack();
        frame.setVisible(true);
    }
}

5、FileDialog(文件对话框)

6、AWT事件监听机制

(1)、内部类

package container;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    Frame frame = new Frame("测试事件处理");

    TextField textField = new TextField(30);
    Button button = new Button("确定");

    private class MyListener implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent e) {
            textField.setText("Hello world!");
        }
    }

    public Demo() {

        MyListener myListener = new MyListener();

        button.addActionListener(myListener);

        frame.add(textField);
        frame.add(button,BorderLayout.SOUTH);

        frame.setVisible(true);

    }

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

(2)、匿名类

package container;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    Frame frame = new Frame("测试事件处理");
    TextField textField = new TextField(30);
    Button button = new Button("确定");

    public Demo() {

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textField.setText("Hello world!");
            }
        });

        frame.add(textField);
        frame.add(button,BorderLayout.SOUTH);
        frame.setVisible(true);
    }

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

 (3)、事件

(4)、事件监听器

package container;

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

public class Demo {

    Frame frame = new Frame("测试事件处理");
    TextField textField = new TextField(30);
    Choice choice = new Choice();

    public Demo() {

        choice.add("红色");
        choice.add("绿色");
        choice.add("蓝色");

        textField.addTextListener(new TextListener() {
            @Override
            public void textValueChanged(TextEvent e) {
                System.out.println(textField.getText());
            }
        });

        choice.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                System.out.println("当前的选择:" + e.getItem());
            }
        });

        frame.addContainerListener(new ContainerListener() {
            @Override
            public void componentAdded(ContainerEvent e) {
                Component child = e.getChild();
                System.out.println("frame中添加了:" + child);
            }

            @Override
            public void componentRemoved(ContainerEvent e) {

            }
        });

        frame.add(textField,BorderLayout.NORTH);
        frame.add(choice);


        frame.pack();
        frame.setBounds(100,100,500,300);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Demo();
    }
}
关闭窗口
package container;

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

public class Demo {
    
    public static void main(String[] args) {
        Frame frame = new Frame("测试关闭窗口");

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

        frame.pack();
        frame.setVisible(true);
    }
}

7、菜单组件

(1)、MenuBar、Menu、MenuItem 

写出以下界面:

package container;

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

public class Demo {

    Frame frame = new Frame("测试菜单相关组件");

    MenuBar menuBar = new MenuBar();

    Menu fileMenu = new Menu("文件");
    Menu editMenu = new Menu("编辑");
    Menu formatMenu = new Menu("格式");

    MenuItem auto = new MenuItem("自动换行");
    MenuItem copy = new MenuItem("复制");
    MenuItem paste = new MenuItem("粘贴");

    //设置快捷键,默认有ctrl,true表示还要加上shift
    MenuItem comment = new MenuItem("注释",new MenuShortcut(KeyEvent.VK_Q,true));
    MenuItem cancelComment = new MenuItem("取消注释");

    TextArea ta = new TextArea(6,40);

    public Demo(){

        //添加监听器
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        formatMenu.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //追加写入
                ta.append("您点击了组件:" + e.getActionCommand() + "\n");
            }
        });

        //组装格式菜单
        formatMenu.add(comment);
        formatMenu.add(cancelComment);

        //组装编辑菜单
        editMenu.add(auto);
        editMenu.add(copy);
        editMenu.add(paste);
        editMenu.add(new MenuItem("-"));
        editMenu.add(formatMenu);

        //组装菜单条
        menuBar.add(fileMenu);
        menuBar.add(editMenu);

        //组装窗口
        frame.setMenuBar(menuBar);
        frame.add(ta);

        frame.pack();
        frame.setVisible(true);
    }

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

(2)、PopupMenu(鼠标右击弹出菜单)

写出以下界面

package container;

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

public class Demo {

    Frame frame = new Frame("测试PopupMenu");

    PopupMenu popupMenu = new PopupMenu();
    MenuItem comment = new MenuItem("注释");
    MenuItem cancelComment = new MenuItem("取消注释");
    MenuItem copy = new MenuItem("复制");
    MenuItem save = new MenuItem("保存");
    TextArea ta = new TextArea("爱我中华!!!\n",6,40);
    Panel panel = new Panel();

    public Demo(){

        //添加监听器
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        ActionListener actionListener = new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();
                ta.append("您点击的菜单项为: " + actionCommand + "\n");
            }
        };

        comment.addActionListener(actionListener);
        cancelComment.addActionListener(actionListener);
        copy.addActionListener(actionListener);
        save.addActionListener(actionListener);

        popupMenu.add(comment);
        popupMenu.add(cancelComment);
        popupMenu.add(copy);
        popupMenu.add(save);

        panel.add(popupMenu);
        //设置尺寸
        panel.setPreferredSize(new Dimension(200,100));

        panel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                //true 为右键,false 为左键
                boolean popupTrigger = e.isPopupTrigger();
                if (popupTrigger){
                    popupMenu.show(panel,e.getX(),e.getY());
                }
            }
        });

        frame.add(ta);
        frame.add(panel,BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
    }

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

8、AWT绘图

(1)、演示 

画出以下图形:

package container;

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

public class Demo {
    private final String RECT = "rect";
    private final String OVAL = "oval";

    private String shape = "";

    Frame frame = new Frame("测试绘图");

    Button rectButton = new Button("绘制矩形");
    Button ovalButton = new Button("绘制椭圆");

    Panel p = new Panel();

    //自定义类继承Canvas,重写paint(Graphics g)方法,实现画图的方法
    private class MyCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
            if (shape.equals(RECT)){
                g.setColor(Color.black);
                g.drawRect(100,100,150,100);
            } else if (shape.equals(OVAL)) {
                g.setColor(Color.RED);
                g.drawOval(100,100,150,100);
            }
        }
    }

    //创建对象
    private MyCanvas myCanvas = new MyCanvas();

    public Demo(){
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        rectButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                shape = RECT;
                myCanvas.repaint();
            }
        });

        ovalButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                shape = OVAL;
                myCanvas.repaint();
            }
        });

        p.add(rectButton);
        p.add(ovalButton);

        frame.add(p,BorderLayout.SOUTH);

        myCanvas.setPreferredSize(new Dimension(300,300));
        frame.add(myCanvas);

        frame.pack();;
        frame.setVisible(true);

    }

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

(2)、弹球小游戏

 

package tanqui;

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

public class Game {

    private Frame frame = new Frame("弹球游戏");

    //桌面宽度
    private final int TABLE_WIDTH = 300;
    //桌面高度
    private final int TABLE_HEIGHT = 400;

    //球拍宽度
    private final int RACKET_WIDTH = 60;
    //球拍高度
    private final int RACKET_HEIGHT = 20;

    //小球大小
    private final int BALL_SIZE = 16;

    //记录小球的坐标
    private int ballX = 120;
    private int ballY = 20;

    //记录小球在x、y方向的速度
    private int speedY = 10;
    private int speedX = 5;
    
    //球拍的坐标
    private int recketX = 120;
    private final int recketY = 340;
    
    //游戏是否结束
    private boolean isOver = false;
    //声明一个定时器
    private Timer timer;
    //自定义一个类,充当画布
    private class MyCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
            //游戏结束
            if (isOver){
                g.setColor(Color.blue);
                g.setFont(new Font("Times",Font.BOLD,20));
                g.drawString("游戏结束!",50,200);
            } else {
                //绘制小球
                g.setColor(Color.red);
                g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);
                //绘制球拍
                g.setColor(Color.pink);
                g.fillRect(recketX,recketY,RACKET_WIDTH,RACKET_HEIGHT);
            }
        }
    }

    //创建绘画区
    private MyCanvas drawArea = new MyCanvas();

    //组装界面
    public Game(){
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        //球拍坐标变化
        KeyAdapter keyAdapter = new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                if (keyCode == KeyEvent.VK_LEFT){
                    if (recketX > 0){
                        recketX -= 10;
                    }
                }
                if (keyCode == KeyEvent.VK_RIGHT){
                    if (recketX < (TABLE_WIDTH - RACKET_WIDTH)){
                        recketX += 10;
                    }
                }
            }
        };

        //为了保证事件被监听,给frame和drawArea都注册监听器
        frame.addKeyListener(keyAdapter);
        drawArea.addKeyListener(keyAdapter);

        //小球坐标变化
        ActionListener task = new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                //修正速度
                if (ballX <= 0 || ballX >= (TABLE_WIDTH-BALL_SIZE)){
                    speedX = -speedX;
                }
                if (ballY <= 0 || (ballY >= recketY - BALL_SIZE && ballX >= recketX && ballX <= recketX + RACKET_WIDTH)){
                    speedY = -speedY;
                }
                if (ballY > recketY - BALL_SIZE && (ballX < recketX || ballX > recketX + RACKET_WIDTH)){
                    timer.stop();
                    isOver = true;
                    drawArea.repaint();
                }
                //更新小球坐标,重绘界面
                ballX += speedX;
                ballY += speedY;
                drawArea.repaint();
            }
        };

        timer = new Timer(100,task);
        timer.start();

        drawArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));

        frame.add(drawArea);


        frame.pack();
        frame.setVisible(true);
    }

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

 (3)、处理位图

演示 

画出以下界面

package container;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class Demo {
    private Frame frame = new Frame("测试绘图");
    //定义画图区域的宽高
    private final int AREA_WIDTH = 500;
    private final int AREA_HIGHT = 400;

    private PopupMenu colorMenu = new PopupMenu();
    private MenuItem redMenu = new MenuItem("红色");
    private MenuItem greenMenu = new MenuItem("绿色");
    private MenuItem blueMenu = new MenuItem("蓝色");

    //记录当前颜色
    private Color forceColor = Color.RED;

    //创建一个 BufferedImage 位图对象
    BufferedImage image = new BufferedImage(AREA_WIDTH,AREA_HIGHT,BufferedImage.TYPE_INT_BGR);

    //通过位图,获取关联的Graphics对象
    Graphics g  = image.getGraphics();

    //自定义类继承Canvas,重写paint(Graphics g)方法,实现画图的方法
    private class MyCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
            g.drawImage(image,0,0,null);
        }
    }

    //创建对象
    private MyCanvas drawArea = new MyCanvas();

    //记录鼠标拖动时的上一次坐标
    private int preX = -1;
    private int preY = -1;

    public Demo(){
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        ActionListener listener = new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();
                switch (actionCommand){
                    case "红色":
                        forceColor = Color.RED;
                        break;
                    case "绿色":
                        forceColor = Color.GREEN;
                        break;
                    case "蓝色":
                        forceColor = Color.BLUE;
                        break;
                }
            }
        };

        redMenu.addActionListener(listener);
        greenMenu.addActionListener(listener);
        blueMenu.addActionListener(listener);

        colorMenu.add(redMenu);
        colorMenu.add(greenMenu);
        colorMenu.add(blueMenu);

        drawArea.add(colorMenu);

        drawArea.addMouseListener(new MouseAdapter() {
            //鼠标抬起时触发
            @Override
            public void mouseReleased(MouseEvent e) {
                boolean popupTrigger = e.isPopupTrigger();
                if (popupTrigger){
                    colorMenu.show(drawArea,e.getX(),e.getY());
                }

                //当鼠标画第二条线时,第一条线的末端会与第二条线的开头连起来,
                //所以要监听鼠标抬起,把preX,preY重新置成-1.
                preX = -1;
                preY = -1;
            }
        });

        //设置位图的背景为白色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,AREA_WIDTH,AREA_HIGHT);

        //监听鼠标的移动,完成绘图
        drawArea.addMouseMotionListener(new MouseMotionAdapter() {
            //当鼠标 左键按下 并拖 动时触发
            @Override
            public void mouseDragged(MouseEvent e) {
                if (preX >= 0 && preY >= 0){
                    g.setColor(forceColor);
                    g.drawLine(preX,preY,e.getX(),e.getY());
                }

                //第一次画时。只需要修正preX,preY的值
                //画完之后也要更新坐标
                preX = e.getX();
                preY = e.getY();

                //当鼠标画第二条线时,第一条线的末端会与第二条线的开头连起来,
                //所以要监听鼠标抬起,把preX,preY重新置成-1.

                //重绘组件
                drawArea.repaint();
            }
        });

        drawArea.setPreferredSize(new Dimension(AREA_WIDTH,AREA_HIGHT));
        frame.add(drawArea);

        frame.pack();;
        frame.setVisible(true);
    }

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

做一个图片查看器

package container;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Demo {
    private Frame frame = new Frame("图片查看器");

    MenuBar menuBar = new MenuBar();

    Menu fileMenu = new Menu("文件");

    MenuItem openItem = new MenuItem("打开");
    MenuItem saveItem = new MenuItem("另存为");

    private BufferedImage image;

    private class MyCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
            g.drawImage(image,0,0,null);
        }
    }

    private MyCanvas drawArea = new MyCanvas();

    public Demo(){
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        openItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FileDialog fileDialog = new FileDialog(frame, "打开图片", FileDialog.LOAD);
                fileDialog.setVisible(true);

                String directory = fileDialog.getDirectory();
                String fileName = fileDialog.getFile();

                try {
                    image = ImageIO.read(new File(directory,fileName));
                    drawArea.repaint();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });

        saveItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FileDialog fileDialog = new FileDialog(frame, "保存图片", FileDialog.SAVE);
                fileDialog.setVisible(true);

                String directory = fileDialog.getDirectory();
                String fileName = fileDialog.getFile();

                try {
                    ImageIO.write(image,"JPEG",new File(directory,fileName));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        });


        fileMenu.add(openItem);
        fileMenu.add(saveItem);

        menuBar.add(fileMenu);

        //drawArea.setPreferredSize(new Dimension(800,800));
        frame.setMenuBar(menuBar);
        frame.add(drawArea);

        frame.setBounds(0,0,800,800);

        frame.setVisible(true);
    }

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

9、五子棋游戏

用Frame和Canvas会有画面闪烁,改为Swing中的JFrame和JPanel后不会闪烁

链接:https://pan.baidu.com/s/1eXK1-SCzHqgOe9C0WI7ACg?pwd=vy60 
提取码:vy60

二、Swing

1、概述

2、基本组件使用,风格改变,组件加入图标

package swing;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    JFrame jFrame = new JFrame("测试Swing基本组件");

    //声明菜单组件
    JMenuBar jMenuBar = new JMenuBar();

    JMenu fileMenu = new JMenu("文件");
    JMenu editMenu = new JMenu("编辑");

    JMenuItem auto = new JMenuItem("自动换行");
    //设置按钮时加入图标
    JMenuItem copy = new JMenuItem("复制",new ImageIcon("image\\swing\\copy.png"));
    JMenuItem paste = new JMenuItem("粘贴",new ImageIcon("image\\swing\\paste.png"));

    JMenu formatMenu = new JMenu("格式");
    JMenuItem comment = new JMenuItem("注释");
    JMenuItem cancelComment = new JMenuItem("取消注释");

    //声明文本域
    JTextArea ta = new JTextArea(6,20);

    //声明列表框
    String[] colors = {"红色","绿色","蓝色"};
    JList<String> colorList = new JList<>(colors);

    //声明下拉选择框
    JComboBox<String> colorSelect = new JComboBox<>();

    //声明其他选择相关组件
    ButtonGroup bg = new ButtonGroup();
    JRadioButton male = new JRadioButton("男",false);
    JRadioButton female = new JRadioButton("女",true);

    JCheckBox isMarry = new JCheckBox("是否已婚?",true);

    //声明底部
    JTextField tf = new JTextField(40);
    JButton ok = new JButton("确定",new ImageIcon("image\\swing\\ok.png"));

    //声明右键菜单
    JPopupMenu jPopupMenu = new JPopupMenu();

    ButtonGroup poupButtonBg = new ButtonGroup();

    JRadioButtonMenuItem metalItem = new JRadioButtonMenuItem("Metal 风格");
    JRadioButtonMenuItem nimbusItem = new JRadioButtonMenuItem("Nimbus 风格");
    JRadioButtonMenuItem windowsItem = new JRadioButtonMenuItem("Windows 风格",true);
    JRadioButtonMenuItem windowsClassicItem = new JRadioButtonMenuItem("Windows 经典风格");
    JRadioButtonMenuItem motifItem = new JRadioButtonMenuItem("Motif 风格");

    public Demo(){
        //组装视图

        //底部
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(tf);
        bottomPanel.add(ok);
        jFrame.add(bottomPanel, BorderLayout.SOUTH);

        //组装选择相关组件
        JPanel selsctPanel = new JPanel();

        colorSelect.addItem("红色");
        colorSelect.addItem("绿色");
        colorSelect.addItem("蓝色");
        selsctPanel.add(colorSelect);
        bg.add(male);
        bg.add(female);
        selsctPanel.add(male);
        selsctPanel.add(female);
        selsctPanel.add(isMarry);

        //组装文本域和选择相关
        Box topLeft = Box.createVerticalBox();
        topLeft.add(ta);
        topLeft.add(selsctPanel);

        //组装顶部
        Box top = Box.createHorizontalBox();
        top.add(topLeft);
        top.add(colorList);

        jFrame.add(top);

        //组装顶部菜单
        formatMenu.add(comment);
        formatMenu.add(cancelComment);

        editMenu.add(auto);
        //添加横杠
        editMenu.addSeparator();
        editMenu.add(copy);
        editMenu.add(paste);
        editMenu.addSeparator();
        editMenu.add(formatMenu);

        jMenuBar.add(fileMenu);
        jMenuBar.add(editMenu);

        jFrame.setJMenuBar(jMenuBar);

        //组装右键菜单
        poupButtonBg.add(metalItem);
        poupButtonBg.add(nimbusItem);
        poupButtonBg.add(windowsItem);
        poupButtonBg.add(windowsClassicItem);
        poupButtonBg.add(motifItem);

        ActionListener listener = new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();
                try {
                    changeFlavor(actionCommand);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        metalItem.addActionListener(listener);
        nimbusItem.addActionListener(listener);
        windowsItem.addActionListener(listener);
        windowsClassicItem.addActionListener(listener);
        motifItem.addActionListener(listener);

        jPopupMenu.add(metalItem);
        jPopupMenu.add(nimbusItem);
        jPopupMenu.add(windowsItem);
        jPopupMenu.add(windowsClassicItem);
        jPopupMenu.add(motifItem);

        //不需要再监听鼠标事件了,有封装好的API
        ta.setComponentPopupMenu(jPopupMenu);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

    //修改外观
    private void changeFlavor(String command) throws Exception {
        switch (command) {
            case "Metal 风格":
                UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
                break;
            case "Nimbus 风格":
                UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
                break;
            case "Windows 风格":
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                break;
            case "Windows 经典风格":
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");
                break;
            case "Motif 风格":
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
                break;
        }

        //刷新组件外观
        //刷新jFrame中的所有容器
        SwingUtilities.updateComponentTreeUI(jFrame.getContentPane());
        SwingUtilities.updateComponentTreeUI(jMenuBar);
        SwingUtilities.updateComponentTreeUI(jPopupMenu);
    }
}

3、为组件设置边框

package swing;

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

public class BorderTest {

    JFrame jf  = new JFrame("测试边框");

    public BorderTest(){
        //设置Jframe为网格布局
        jf.setLayout(new GridLayout(2,4));

        //创建凸起的斜边框,分别设置四条边的颜色
        Border bb = BorderFactory.createBevelBorder(BevelBorder.RAISED,Color.RED,Color.GREEN,Color.BLUE,Color.GRAY);
        jf.add(getPanelWithBorder(bb,"BevelBorder"));


        //创建LineBorder  参数:颜色,线宽
        Border lb = BorderFactory.createLineBorder(Color.ORANGE, 10);
        jf.add(getPanelWithBorder(lb,"LineBorder"));

        //创建EmptyBorder,会在组件的四周留白
        Border eb = BorderFactory.createEmptyBorder(20, 5, 10, 30);
        jf.add(getPanelWithBorder(eb,"EmptyBorder"));

        //创建EtchedBorder  参数:突起,高亮处颜色,阴影处颜色
        Border etb = BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.RED, Color.GREEN);
        jf.add(getPanelWithBorder(etb,"EtchedBorder"));

        //创建TitledBorder,为原有的Border添加标题   参数:与其组合的边框,标题内容,标题在左边,标题在下边,字体,标题颜色
        TitledBorder tb = new TitledBorder(lb,"测试标题",TitledBorder.LEFT,TitledBorder.BOTTOM,new Font("StSong",Font.BOLD,18),Color.BLUE);
        jf.add(getPanelWithBorder(tb,"TitledBorder"));

        //直接创建MatteBorder,它是EmptyBorder的子类,EmptyBorder是留白,而MatteBorder可以给留空的区域填充颜色
        MatteBorder mb = new MatteBorder(20,5,10,30,Color.GREEN);
        jf.add(getPanelWithBorder(mb,"MatteBorder"));

        //直接创创建CompoundBorder,将两个边框组合成新边框  参数:先外边框,再内边框
        CompoundBorder cb = new CompoundBorder(new LineBorder(Color.RED,8),tb);
        jf.add(getPanelWithBorder(cb,"CompoundBorder"));

        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);

    }
    public JPanel getPanelWithBorder(Border border,String borderName){
        JPanel jPanel = new JPanel();

        jPanel.add(new JLabel(borderName));

        //为panel设置边框
        jPanel.setBorder(border);

        return jPanel;
    }
    public static void main(String[] args) {
        new BorderTest();
    }
}

 4、JToolBar

package swing;

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

public class Demo {

    JFrame jFrame = new JFrame("测试工具条");
    JTextArea jta = new JTextArea(6,40);

    //名字,设置为横向
    JToolBar jToolBar = new JToolBar("播放工具条",SwingConstants.HORIZONTAL);

    //创建3个Action对象
    Action pre = new AbstractAction("上一曲",new ImageIcon("image\\jtoolbar\\pre.png")) {
        @Override
        public void actionPerformed(ActionEvent e) {
            jta.append("上一曲\n");
        }
    };

    Action pause = new AbstractAction("暂停",new ImageIcon("image\\jtoolbar\\pause.png")) {
        @Override
        public void actionPerformed(ActionEvent e) {
            jta.append("暂停\n");
        }
    };
    Action next = new AbstractAction("下一曲",new ImageIcon("image\\jtoolbar\\next.png")) {
        @Override
        public void actionPerformed(ActionEvent e) {
            jta.append("下一曲\n");
        }
    };

    public Demo(){

        //通过监听器注册JButton
        JButton preBtn = new JButton(pre);
        JButton pauseBtn = new JButton(pause);
        JButton nextBtn = new JButton(next);

        jToolBar.add(preBtn);
        jToolBar.addSeparator();
        jToolBar.add(pauseBtn);
        jToolBar.addSeparator();
        jToolBar.add(nextBtn);

        //让工具条可以拖动
        jToolBar.setFloatable(true);

        //文本框默认不支持滚动条
        //将文本框放入JScrollPane中
        JScrollPane jScrollPane = new JScrollPane(jta);

        jFrame.add(jToolBar,BorderLayout.NORTH);
        jFrame.add(jScrollPane);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

5、JColorChooser和JFileChoose

JColorChooser

package swing;

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

public class Demo {

    JFrame jFrame = new JFrame("测试颜色选择框");
    JTextArea jta = new JTextArea(6,40);

    JButton btn = new JButton(new AbstractAction("改变文本框颜色") {
        @Override
        public void actionPerformed(ActionEvent e) {
            Color color = JColorChooser.showDialog(jFrame, "颜色选择器", Color.WHITE);
            jta.setBackground(color);
        }
    });

    public Demo(){

        jFrame.add(jta);
        jFrame.add(btn,BorderLayout.SOUTH);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

JFileChoose 

package swing;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Demo {

    JFrame jFrame = new JFrame("测试JFileChoose");
    JMenuBar jMenuBar = new JMenuBar();
    JMenu jMenu = new JMenu("文件");
    JMenuItem open = new JMenuItem(new AbstractAction("打开") {
        @Override
        public void actionPerformed(ActionEvent e) {
            JFileChooser jFileChooser = new JFileChooser(".");
            jFileChooser.showOpenDialog(jFrame);
            File selectedFile = jFileChooser.getSelectedFile();
            try {
                image = ImageIO.read(selectedFile);
                drawArea.repaint();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    });

    JMenuItem save = new JMenuItem(new AbstractAction("保存") {
        @Override
        public void actionPerformed(ActionEvent e) {
            JFileChooser jFileChooser = new JFileChooser(".");
            jFileChooser.showSaveDialog(jFrame);
            File selectedFile = jFileChooser.getSelectedFile();

            try {
                ImageIO.write(image,"jpeg",selectedFile);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    });

    BufferedImage image;

    private class MyCanvas extends JPanel{
        @Override
        public void paint(Graphics g) {
            g.drawImage(image,0,0,null);
        }
    }

    MyCanvas drawArea = new MyCanvas();

    public Demo(){

        jMenu.add(open);
        jMenu.add(save);

        jMenuBar.add(jMenu);

        jFrame.setJMenuBar(jMenuBar);

        drawArea.setPreferredSize(new Dimension(800,800));
        jFrame.add(drawArea);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

6、JOptionPane

showXxxDialog(Component parentComponent,
		Object message, 
		String title, 
		int optionType, 
		int messageType,
        	Icon icon,
		Object[] options, 
		Object initialValue)
--参数解释:
parentComponent:当前对话框的父组件
message:对话框上显示的信息,信息可以是字符串、组件、图片等
title:当前对话框的标题
optionType:当前对话框上显示的按钮类型:DEFAULT_OPTION、YES_NO_OPTION、YES_NO_CANCEL_OPTION、OK_CANCEL_OPTION
messageType:当前对话框的类型:ERROR_MESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE、PLAIN_MESSAGE
icon:当前对话框左上角的图标
options:自定义下拉列表的选项
initialValue:自定义选项中的默认选中项

(1)、showMessageDialog(消息对话框)

package swing;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Demo {

    JFrame jFrame = new JFrame("测试消息对话框");
    JTextArea jta = new JTextArea(6,30);

    JButton jButton = new JButton(new AbstractAction("弹出消息对话框") {
        @Override
        public void actionPerformed(ActionEvent e) {
            String text = jta.getText();
            //错误对话框
            //JOptionPane.showMessageDialog(jFrame,text,"消息对话框",JOptionPane.ERROR_MESSAGE);
            //基本信息对话框
            //JOptionPane.showMessageDialog(jFrame,text,"消息对话框",JOptionPane.INFORMATION_MESSAGE);
            //警告信息
            //JOptionPane.showMessageDialog(jFrame,text,"消息对话框",JOptionPane.WARNING_MESSAGE);
            //解释对话框
            //JOptionPane.showMessageDialog(jFrame,text,"消息对话框",JOptionPane.QUESTION_MESSAGE);
            //基本对话框
            //JOptionPane.showMessageDialog(jFrame,text,"消息对话框",JOptionPane.PLAIN_MESSAGE);
            //自定义图标
            JOptionPane.showMessageDialog(jFrame,text,"消息对话框",JOptionPane.PLAIN_MESSAGE,new ImageIcon("image\\male.png"));
        }
    });

    public Demo(){

        jFrame.add(jta);
        jFrame.add(jButton,BorderLayout.SOUTH);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

(2)、showConfirmDialog(确认对话框)

package swing;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Demo {

    JFrame jFrame = new JFrame("测试确认对话框");
    JTextArea jta = new JTextArea(6,30);

    JButton jButton = new JButton(new AbstractAction("弹出确认对话框") {
        @Override
        public void actionPerformed(ActionEvent e) {
            String text = jta.getText();
            //默认按钮(只有确定)
            //int result = JOptionPane.showConfirmDialog(jFrame, text, "确认对话框", JOptionPane.DEFAULT_OPTION);
            //是、否
            //int result = JOptionPane.showConfirmDialog(jFrame, text, "确认对话框", JOptionPane.YES_NO_OPTION);
            //是、否、取消
            //int result = JOptionPane.showConfirmDialog(jFrame, text, "确认对话框", JOptionPane.YES_NO_CANCEL_OPTION);
            //确认、取消
            int result = JOptionPane.showConfirmDialog(jFrame, text, "确认对话框", JOptionPane.OK_CANCEL_OPTION);
            if (result == JOptionPane.YES_OPTION){
                jta.append("用户点击了 是 按钮\n");
            }
            if (result == JOptionPane.NO_OPTION) {
                jta.append("用户点击了 否 按钮\n");
            }
//            if (result == JOptionPane.OK_OPTION) {
//                jta.append("用户点击了 确认 按钮\n");
//            }
            if (result == JOptionPane.CANCEL_OPTION) {
                jta.append("用户点击了 取消 按钮\n");
            }

        }
    });

    public Demo(){

        jFrame.add(jta);
        jFrame.add(jButton,BorderLayout.SOUTH);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

(3)、showInputDialog(输入对话框)

package swing;

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

public class Demo {

    JFrame jFrame = new JFrame("测试输入对话框");
    JTextArea jta = new JTextArea(6,30);

    JButton jButton = new JButton(new AbstractAction("弹出输入对话框") {
        @Override
        public void actionPerformed(ActionEvent e) {
            String result = JOptionPane.showInputDialog(jFrame, "请填写您的银行卡账号", "输入对话框", JOptionPane.INFORMATION_MESSAGE);
            jta.append(result + "\n");
        }
    });

    public Demo(){

        jFrame.add(jta);
        jFrame.add(jButton,BorderLayout.SOUTH);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

(4)、showOptionDialog(选项对话框)

package swing;

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

public class Demo {

    JFrame jFrame = new JFrame("测试选项对话框");
    JTextArea jta = new JTextArea(6,30);

    JButton jButton = new JButton(new AbstractAction("弹出选项对话框") {
        @Override
        public void actionPerformed(ActionEvent e) {
            //参数: 依附的组件,提示信息,左上角标题,按钮类型(一般为默认),对话框类型,自定义图标,按钮上的信息,默认选中
            int result = JOptionPane.showOptionDialog(jFrame, "请选择衣服号码大小", "选项对话框",
                    JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
                    new String[]{"大号", "中号", "小号"}, "中号");

            switch (result){
                case 0:
                    jta.setText("用户选择了大号");
                    break;
                case 1:
                    jta.setText("用户选择了中号");
                    break;
                case 2:
                    jta.setText("用户选择了小号");
                    break;
            }

        }
    });

    public Demo(){

        jFrame.add(jta);
        jFrame.add(jButton,BorderLayout.SOUTH);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

    }

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

7、JSplitPane

package container2;

import javax.swing.*;

public class Book {
    private String name;
    private Icon icon;
    private String desc;

    public Book(String name, Icon icon, String desc) {
        this.name = name;
        this.icon = icon;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Icon getIcon() {
        return icon;
    }

    public void setIcon(Icon icon) {
        this.icon = icon;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    @Override
    public String toString() {
        return name;
    }
}
package container2;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;

public class SplitPaneTest {

    Book[] books = {new Book("java自学宝典",new ImageIcon("image\\container\\java.png"),"Java编程书籍"),
            new Book("javaEE",new ImageIcon("image\\container\\ee.png"),"JavaEE编程书籍"),
            new Book("android教程",new ImageIcon("image\\container\\android.png"),"android移动开发教程")};

    JFrame jFrame = new JFrame("测试JSplitPane");
    //显示的是Book的 toString 方法
    JList<Book> bookJList = new JList<>(books);
    JLabel bookCover = new JLabel();
    JTextArea bookDesc = new JTextArea();

    public SplitPaneTest(){

        //设定组件大小
        bookJList.setPreferredSize(new Dimension(150,400));
        bookCover.setPreferredSize(new Dimension(220,270));
        bookDesc.setPreferredSize(new Dimension(220,130));

        //为bookJList设置条目选中事件监听器
        bookJList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                Book selectedValue = bookJList.getSelectedValue();
                bookCover.setIcon(selectedValue.getIcon());
                bookDesc.setText(selectedValue.getDesc());
            }
        });

        //组装左边区域
        JSplitPane left = new JSplitPane(JSplitPane.VERTICAL_SPLIT,bookCover,new JScrollPane(bookDesc));

        //
        left.setOneTouchExpandable(true);

        JSplitPane hole = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,left,bookJList);

        //支持连续布局
        hole.setContinuousLayout(true);
        hole.setDividerLocation(10);

        jFrame.add(hole);



        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

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

}

 8、JTabbedPane(放置多个标签页)

JTabbedPane可以很方便地在窗口上放置多个标签页,每个标签页相当于获得了一个与外部容器具有相同大小的组件摆放区域。通过这种方式, 就可以在一个容器里放置更多的组件 , 例如右击桌面上的" 我的电脑 "图标,在弹出的快捷菜单里单击"属性 " 菜单工页 , 就可以看 到 一个"系统属性 " 对话框 ,这个对话框里包含了 若干个标签页。

创建JTabbedPane对象

 JTabbedPane(int tabPlacement, int tabLayoutPolicy):
	tabPlacement:
		指定标签标题的放置位置,可以选择 SwingConstants中的四个常量:TOP、LEFT、BOTTOM、RIGHT
	tabLaoutPolicy:
		指定当窗口不能容纳标签页标题时的布局策略,可以选择JTabbedPane.WRAP_TAB_LAYOUT和JTabbedPane.SCROLL_TAB_LAYOUT
  1. 通过JTabbedPane对象堆标签进行增删改查
addTab(String title, Icon icon, Component component, String tip):添加标签
	title:标签的名称
	icon:标签的图标
	component:标签对应的组件
	tip:光标放到标签上的提示
	
insertTab(String title, Icon icon, Component component, String tip, int index):插入标签页
	title:标签的名称
	icon:标签的图标
	component:标签对应的组件
	tip:光标放到标签上的提示
	index:在哪个索引处插入标签页
setComponentAt(int index, Component component):修改标签页对应的组件
	index:修改哪个索引处的标签
	component:标签对应的组件
removeTabAt(int index):
	index:删除哪个索引处的标签
  1. 设置当前显示的标签页
setSelectedIndex(int index):设置哪个索引处的标签被选中
  1. 设置JTabbedPane的其他属性
setDisabledIconAt(int index, Icon disabledIcon): 将指定位置的禁用图标设置为 icon,该图标也可以是null表示不使用禁用图标。
setEnabledAt(int index, boolean enabled): 设置指定位置的标签页是否启用。
setTitleAt(int index, String title): 设置指定位置标签页的标题为 title,该title可以是null,这表明设置该标签页的标题为空。
setToolTipTextAt(int index, String toolTipText): 设置指定位置标签页的提示文本 。
  1. 为JTabbedPane设置监听器
addChangeListener(ChangeListener l)

package container;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class Demo {

    JFrame jFrame = new JFrame("测试");

    JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.LEFT,JTabbedPane.SCROLL_TAB_LAYOUT);

    public Demo(){

        //添加标签
        tabbedPane.addTab("用户管理",new ImageIcon("image/jtoolbar/open.gif"),new JList<String>(new String[]{"用户一","用户二","用户三"}));
        tabbedPane.addTab("商品管理",new JList<String>(new String[]{"商品一","商品二","商品三"}));
        tabbedPane.addTab("订单管理",new ImageIcon("image/jtoolbar/open.gif"),new JList<String>(new String[]{"订单一","订单二","订单三"}));

        //完成设置
        //禁用
        tabbedPane.setEnabledAt(0,false);
        //默认选中
        tabbedPane.setSelectedIndex(1);

        //监听标签面板的选中情况
        tabbedPane.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                int selectedIndex = tabbedPane.getSelectedIndex();
                JOptionPane.showMessageDialog(jFrame,"当前选中了第"+(selectedIndex + 1)+"个标签");

            }
        });

        jFrame.add(tabbedPane);

        jFrame.setBounds(0,0,400,400);

        //固定窗口大小
        jFrame.setResizable(false);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);

    }

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

9、进度条(JProcessBar、ProcessMonitor、BoundedRangeModel)

(1)、JProcessBar

package container;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    JFrame jFrame = new JFrame("测试进度条");

    JCheckBox indeterminate = new JCheckBox("不确定进度条");
    JCheckBox noBoder = new JCheckBox("不会指边框");

    //进度条
    JProgressBar jProgressBar = new JProgressBar(JProgressBar.HORIZONTAL,0,100);

    public Demo(){

        indeterminate.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = indeterminate.isSelected();

                //设置是否为不确定进度条
                jProgressBar.setIndeterminate(selected);
                //设置是否显示百分比
                jProgressBar.setStringPainted(!selected);
            }
        });

        noBoder.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = noBoder.isSelected();

                jProgressBar.setBorderPainted(!selected);
            }
        });

        Box vbox = Box.createVerticalBox();
        vbox.add(indeterminate);
        vbox.add(noBoder);

        //设置进度条属性
        jProgressBar.setStringPainted(true);
        jProgressBar.setBorderPainted(true);

        jFrame.setLayout(new FlowLayout());
        jFrame.add(vbox);
        jFrame.add(jProgressBar);
        
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

        //修改进度
        for (int i = 0; i <= 100; i++) {

            jProgressBar.setValue(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }

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

把耗时操作放进子线程中,防止耗时操作过长,是主线程无法操作

package container;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    JFrame jFrame = new JFrame("测试进度条");

    JCheckBox indeterminate = new JCheckBox("不确定进度条");
    JCheckBox noBoder = new JCheckBox("不会指边框");

    //进度条
    JProgressBar jProgressBar = new JProgressBar(JProgressBar.HORIZONTAL,0,100);

    public Demo(){

        indeterminate.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = indeterminate.isSelected();

                //设置是否为不确定进度条
                jProgressBar.setIndeterminate(selected);
                //设置是否显示百分比
                jProgressBar.setStringPainted(!selected);
            }
        });

        noBoder.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = noBoder.isSelected();

                jProgressBar.setBorderPainted(!selected);
            }
        });

        Box vbox = Box.createVerticalBox();
        vbox.add(indeterminate);
        vbox.add(noBoder);

        //设置进度条属性
        jProgressBar.setStringPainted(true);
        jProgressBar.setBorderPainted(true);

        jFrame.setLayout(new FlowLayout());
        jFrame.add(vbox);
        jFrame.add(jProgressBar);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

        SimulaterActivite simulaterActivite = new SimulaterActivite(jProgressBar.getMaximum());
        new Thread(simulaterActivite).start();

        Timer timer = new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int current = simulaterActivite.current;
                jProgressBar.setValue(current);
            }
        });
        timer.start();

        jProgressBar.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                int value = jProgressBar.getValue();
                if (value == simulaterActivite.getAmount()){
                    timer.stop();
                }
            }
        });

    }

    private class SimulaterActivite implements Runnable{
        private int amount;
        //设置内存可见
        private volatile int current;

        public SimulaterActivite(int amount) {
            this.amount = amount;
        }

        public int getAmount() {
            return amount;
        }

        public void setAmount(int amount) {
            this.amount = amount;
        }

        public int getCurrent() {
            return current;
        }

        public void setCurrent(int current) {
            this.current = current;
        }

        @Override
        public void run() {
            while (current<amount){
                try {
                    Thread.currentThread().sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                current++;
            }
        }
    }

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

(2)、BoundedRangeModel

package container;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    JFrame jFrame = new JFrame("测试进度条");

    JCheckBox indeterminate = new JCheckBox("不确定进度条");
    JCheckBox noBoder = new JCheckBox("不会指边框");

    //进度条
    JProgressBar jProgressBar = new JProgressBar(JProgressBar.HORIZONTAL,0,100);

    public Demo(){
        BoundedRangeModel model = jProgressBar.getModel();

        indeterminate.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = indeterminate.isSelected();

                //设置是否为不确定进度条
                jProgressBar.setIndeterminate(selected);
                //设置是否显示百分比
                jProgressBar.setStringPainted(!selected);
            }
        });

        noBoder.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = noBoder.isSelected();

                jProgressBar.setBorderPainted(!selected);
            }
        });

        Box vbox = Box.createVerticalBox();
        vbox.add(indeterminate);
        vbox.add(noBoder);

        //设置进度条属性
        jProgressBar.setStringPainted(true);
        jProgressBar.setBorderPainted(true);

        jFrame.setLayout(new FlowLayout());
        jFrame.add(vbox);
        jFrame.add(jProgressBar);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);

        SimulaterActivite simulaterActivite = new SimulaterActivite(jProgressBar.getMaximum());
        new Thread(simulaterActivite).start();

        Timer timer = new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int current = simulaterActivite.current;
                model.setValue(current);
            }
        });
        timer.start();

        model.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                int value = model.getValue();
                if (value == simulaterActivite.getAmount()){
                    timer.stop();
                }
            }
        });

    }

    private class SimulaterActivite implements Runnable{
        private int amount;
        //设置内存可见
        private volatile int current;

        public SimulaterActivite(int amount) {
            this.amount = amount;
        }

        public int getAmount() {
            return amount;
        }

        public void setAmount(int amount) {
            this.amount = amount;
        }

        public int getCurrent() {
            return current;
        }

        public void setCurrent(int current) {
            this.current = current;
        }

        @Override
        public void run() {
            while (current<amount){
                try {
                    Thread.currentThread().sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                current++;
            }
        }
    }

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

(3)、ProcessMonitor(进度对话框)

ProgressMonitor的用法与JProgressBa 的用法基本相似,只是ProgressMonitor可以直接创 建一个进度对话框,它提供了下面的构造器完成对话框的创建:

 public ProgressMonitor(Component parentComponent,Object message,String note, int min,int max):
	parentComponent:对话框的父组件 (可以为null,可以单独存在)
	message:对话框的描述信息
	note:对话框的提示信息
	min:进度条的最小值
	max:进度条的最大值

使用 ProgressMonitor 创建的对话框里包含的进度条是非常固定的,程序甚至不能设置该进度条是否包含边框(总是包含边框) , 不能设置进度不确定,不能改变进度条的方向(总是水平方向) 。

package container;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    Timer timer;
    public Demo(){

        ProgressMonitor progressMonitor = new ProgressMonitor(null, "等待完成任务", "已完成", 0, 100);
        SimulaterActivite simulaterActivite = new SimulaterActivite(100);
        new Thread(simulaterActivite).start();

        timer = new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int current = simulaterActivite.current;
                progressMonitor.setProgress(current);

                if (progressMonitor.isCanceled()){
                    timer.stop();
                    progressMonitor.close();
                    System.exit(0);
                }
            }
        });
        timer.start();


    }

    private class SimulaterActivite implements Runnable{
        private int amount;
        //设置内存可见
        private volatile int current;

        public SimulaterActivite(int amount) {
            this.amount = amount;
        }

        public int getAmount() {
            return amount;
        }

        public void setAmount(int amount) {
            this.amount = amount;
        }

        public int getCurrent() {
            return current;
        }

        public void setCurrent(int current) {
            this.current = current;
        }

        @Override
        public void run() {
            while (current<amount){
                try {
                    Thread.currentThread().sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                current++;
            }
        }
    }

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

10、列表框(JList、JComboBox)

(1)、简单演示 

3.设置监听器,监听列表项的变化,JList通过addListSelectionListener完成,JComboBox通过addItemListener完成

package container;

import javax.swing.*;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;
import java.util.Vector;

public class Demo {

    JFrame jFrame = new JFrame("测试列表框");
    String[] books = {"图书一","图书二","图书三","图书四","图书五"};

    //定义布局按钮所在面板
    JPanel layoutPanel = new JPanel();
    ButtonGroup layoutGroup = new ButtonGroup();

    //定义布局按钮所在面板
    JPanel selectModePanel = new JPanel();
    ButtonGroup selectGroup = new ButtonGroup();

    JTextArea favourite = new JTextArea(4,40);

    JList<String> bookList;
    JComboBox<String> bookSelector;

    public Demo(){

        bookList = new JList<>(books);

        addBtnToLayoutPanel("纵向滚动",JList.VERTICAL);
        addBtnToLayoutPanel("纵向换行",JList.VERTICAL_WRAP);
        addBtnToLayoutPanel("横向换行",JList.HORIZONTAL_WRAP);

        addBtnToSelectModePanel("无限制",ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        addBtnToSelectModePanel("单选",ListSelectionModel.SINGLE_SELECTION);
        addBtnToSelectModePanel("单范围",ListSelectionModel.SINGLE_INTERVAL_SELECTION);

        //对JList做设置
        //可以看见3行
        bookList.setVisibleRowCount(3);
        //第三个到第五个默认选中
        bookList.setSelectionInterval(2,4);

        //处理条目选择事件
        bookList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                List<String> selectedValuesList = bookList.getSelectedValuesList();
                favourite.setText("");
                for (String s : selectedValuesList) {
                    favourite.append(s + "\n");
                }
            }
        });

        Box verticalBox = Box.createVerticalBox();
        verticalBox.add(new JScrollPane(bookList));
        verticalBox.add(layoutPanel);
        verticalBox.add(selectModePanel);

        //组装bookSelector
        Vector<String> vector = new Vector<>();
        List<String> list = List.of("图书一","图书二","图书三","图书四","图书五");
        vector.addAll(list);

        bookSelector = new JComboBox<>(vector);

        //可编辑
        bookSelector.setEditable(true);
        //可视最多为4
        bookSelector.setMaximumRowCount(4);

        bookSelector.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object selectedItem = bookSelector.getSelectedItem();
                favourite.setText(selectedItem.toString());
            }
        });

        Box horizontalBox = Box.createHorizontalBox();
        horizontalBox.add(verticalBox);
        JPanel bookPanel = new JPanel();
        bookPanel.add(bookSelector);
        horizontalBox.add(bookPanel);

        //底部
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BorderLayout());

        bottomPanel.add(new Label("您最喜欢的图书:"),BorderLayout.NORTH);
        bottomPanel.add(favourite);

        Box vbox = Box.createVerticalBox();
        vbox.add(horizontalBox);
        vbox.add(bottomPanel);

        jFrame.add(vbox);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

    //封装方法,向layoutPanel中添加按钮
    public void addBtnToLayoutPanel(String name,int layoutType){
        layoutPanel.setBorder(new TitledBorder(new EtchedBorder(),"确定选项布局"));

        JRadioButton button = new JRadioButton(name);
        layoutPanel.add(button);
        if (layoutGroup.getButtonCount() == 0){
            button.setSelected(true);
        }
        layoutGroup.add(button);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                bookList.setLayoutOrientation(layoutType);
            }
        });
    }

    //封装方法,向selectModePanel中添加按钮
    public void addBtnToSelectModePanel(String name,int selectMode){
        selectModePanel.setBorder(new TitledBorder(new EtchedBorder(),"确定选择模式"));

        JRadioButton button = new JRadioButton(name);
        selectModePanel.add(button);
        if (selectGroup.getButtonCount() == 0){
            button.setSelected(true);
        }
        selectGroup.add(button);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                bookList.setSelectionMode(selectMode);
            }
        });
    }

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

(2)、数据复杂时自定义Model 

 

package model;

import javax.swing.*;
import java.math.BigDecimal;
import java.math.RoundingMode;

public class NumberListModel extends AbstractListModel<BigDecimal> {
    BigDecimal start;
    BigDecimal end;
    BigDecimal step;

    public NumberListModel(BigDecimal start, BigDecimal end, BigDecimal step) {
        this.start = start;
        this.end = end;
        this.step = step;
    }

    @Override
    public int getSize() {
        int floor = (int) Math.floor(end.subtract(start).divide(step, 2, RoundingMode.HALF_DOWN).doubleValue());
        return floor + 1;
    }

    @Override
    public BigDecimal getElementAt(int index) {
        BigDecimal bigDecimal = new BigDecimal(index).multiply(step).add(start).setScale(2, RoundingMode.HALF_DOWN);
        return bigDecimal;
    }
}
package model;

import javax.swing.*;
import java.math.BigDecimal;
import java.math.RoundingMode;

public class NumberComboBoxListModel extends NumberListModel implements ComboBoxModel<BigDecimal> {
    //当前选中条目的索引
    private int selectedId;

    public NumberComboBoxListModel(BigDecimal start, BigDecimal end, BigDecimal step) {
        super(start, end, step);
    }

    //把一个值设置为当前选中条目
    @Override
    public void setSelectedItem(Object anItem) {

        if (anItem instanceof BigDecimal){
            BigDecimal curr = (BigDecimal) anItem;
            selectedId = curr.subtract(super.start).divide(super.step,2, RoundingMode.HALF_DOWN).intValue();
        }
    }

    //获取当前选中的条目
    @Override
    public Object getSelectedItem() {
        BigDecimal item = new BigDecimal(selectedId).multiply(super.step).add(super.start).setScale(1, RoundingMode.HALF_DOWN);
        return item;
    }
}
package model;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.math.BigDecimal;
import java.util.List;
import java.util.Vector;

public class ListModelTest {
    JFrame jFrame = new JFrame("测试ListModel");

    JList<BigDecimal> jList = new JList<>(new NumberListModel(new BigDecimal(1),new BigDecimal(21),new BigDecimal(2)));

    JComboBox<BigDecimal> jComboBox = new JComboBox<>(new NumberComboBoxListModel(new BigDecimal(0.1),new BigDecimal(1.2),new BigDecimal(0.1)));

    JLabel jLabel = new JLabel("您选择的值是:");
    JTextField jTextField = new JTextField(15);
    public ListModelTest(){

        //一次显示几个
        jList.setVisibleRowCount(4);
        //默认选中范围
        jList.setSelectionInterval(2,4);
        //宽
        jList.setFixedCellWidth(90);
        //高
        jList.setFixedCellHeight(30);

        jList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                List<BigDecimal> selectedValuesList = jList.getSelectedValuesList();
                jTextField.setText("");
                for (BigDecimal bigDecimal : selectedValuesList) {
                    jTextField.setText(jTextField.getText()+ "  " + bigDecimal);
                }
            }
        });

        jComboBox.setMaximumRowCount(4);
        jComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object selectedItem = jComboBox.getSelectedItem();
                jTextField.setText(selectedItem.toString());
            }
        });

        Box vbox = Box.createHorizontalBox();
        vbox.add(new JScrollPane(jList));
        JPanel tempPanel = new JPanel();
        tempPanel.add(jComboBox);
        vbox.add(tempPanel);

        jFrame.add(vbox);

        JPanel buttomPanel = new JPanel();
        buttomPanel.add(jLabel);
        buttomPanel.add(jTextField);

        jFrame.add(buttomPanel,BorderLayout.SOUTH);


        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

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

(3)、对组件的选项进行增删改

 

package container;


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Demo {

    JFrame jFrame = new JFrame("测试DefaultListModel");
    JTextField bookName = new JTextField(20);
    JButton removeBtn = new JButton("删除指定图书");
    JButton addBtn = new JButton("添加指定图书");

    JList bookList = new JList();

    DefaultListModel<String> model = new DefaultListModel<>();

    public Demo(){
        model.addElement("书籍一");
        model.addElement("书籍二");
        model.addElement("书籍三");
        model.addElement("书籍四");
        model.addElement("书籍五");
        model.addElement("书籍六");

        //设置JList
        bookList = new JList(model);
        //设置单选(单选)
        bookList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        bookList.setVisibleRowCount(4);
        jFrame.add(new JScrollPane(bookList));

        addBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String name = bookName.getText();
                //去掉前后空格,不为空
                if(!name.trim().equals("")){
                    model.addElement(name);
                }
            }
        });

        removeBtn.addActionListener(e -> {
//            int selectedIndex = bookList.getSelectedIndex();
//            if (selectedIndex>=0){
//                model.remove(selectedIndex);
//            }
            Object selectedValue = bookList.getSelectedValue();
            model.removeElement(selectedValue);
        });

        //底部
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(bookName);
        bottomPanel.add(addBtn);
        bottomPanel.add(removeBtn);

        jFrame.add(bottomPanel, BorderLayout.SOUTH);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }


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

 (4)列表外观修改(ListCellRenderer)

package container;


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

public class Demo {

    JFrame jFrame = new JFrame("好友列表");

    String[] friend = {
            "李清照",
            "苏格拉底",
            "李白",
            "弄玉",
            "虎头"
    };

    JList friendList = new JList(friend);

    public Demo(){

        friendList.setCellRenderer(new MyRenderer());

        jFrame.add(friendList);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

    private class MyRenderer extends JPanel implements ListCellRenderer{
        private String name;
        private ImageIcon icon;

        //背景色
        private Color bgColor;
        //文字颜色
        private Color forceColor;

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {

            this.name=value.toString();
            this.icon=new ImageIcon("image/list/"+ name +".gif");
            this.bgColor=isSelected ? list.getSelectionBackground() : list.getBackground();
            this.forceColor = isSelected ? list.getSelectionForeground() : list.getForeground();

            return this;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(60,80);
        }

        //绘制列表项的内容
        @Override
        public void paint(Graphics g) {
            int imageWidth = icon.getImage().getWidth(null);
            int imageHight = icon.getImage().getHeight(null);

            //填充背景矩形
            g.setColor(bgColor);
            g.fillRect(0,0,getWidth(),getHeight());

            //绘制头像
            g.drawImage(icon.getImage(),this.getWidth()/2-imageWidth/2,10,null);
            //名称
            g.setColor(forceColor);
            g.setFont(new Font("StSong",Font.BOLD,18));
            g.drawString(this.name,this.getWidth()/2 - this.name.length()*20/2,10+imageHight+25);
        }
    }


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

11、树

JTree常用构造方法:

JTree(TreeModel newModel):使用指定 的数据模型创建 JTree 对象,它默认显示根结点。
JTree(TreeNode root): 使用 root 作为根节 点创建 JTree 对象,它默认显示根结点 。
JTree(TreeNode root, boolean asksAllowsChildren): 使用root作为根结点创建JTree对象,它默认显示根结点。 asksAllowsChildren 参数控制怎样的结点才算叶子结点,如果该参数为 true ,则只有当程序使用 setAllowsChildren(false)显式设置某个结点不允许添加子结点时(以后也不会拥有子结点) ,该结点才会被 JTree 当成叶子结点:如果该参数为 false ,则只要某个结点当时没有子结点(不管以后是否拥有子结点) ,该结点都会被 JTree 当成叶子结点。

TreeNode继承体系及使用:

在构建目录树时,可以先创建很多DefaultMutableTreeNode对象,并调用他们的add方法构建好子父级结构,最后根据根结点构建一个JTree即可。

案例:

(1)、JTree基本演示

package container;


import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;

public class Demo {

    JFrame jFrame = new JFrame("简单树");

    JTree tree;
    DefaultMutableTreeNode root;
    DefaultMutableTreeNode guangdong;
    DefaultMutableTreeNode guangxi;
    DefaultMutableTreeNode foshan;
    DefaultMutableTreeNode shantou;
    DefaultMutableTreeNode guilin;
    DefaultMutableTreeNode nanning;
    public Demo(){
        //依次创建所有结点
        root = new DefaultMutableTreeNode("中国");
        guangdong = new DefaultMutableTreeNode("广东");
        guangxi = new DefaultMutableTreeNode("广西");
        foshan = new DefaultMutableTreeNode("佛山");
        shantou = new DefaultMutableTreeNode("汕头");
        guilin = new DefaultMutableTreeNode("桂林");
        nanning = new DefaultMutableTreeNode("南宁");

        //通过add()方法建立父子层级关系
        guangdong.add(foshan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanning);
        root.add(guangdong);
        root.add(guangxi);

        //依据根结点,创建JTree
        tree = new JTree(root);

        jFrame.add(tree);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }


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

JTree的其他外观设置方法:

tree.putClientProperty( "JTree.lineStyle", "None"):设置结点之间没有连接线
tree.putClientProperty("JTree.lineStyle" , "Horizontal"):设置结点之间只有水平分割线
tree.setShowsRootHandles(true):设置根结点有"展开、折叠"图标
tree.setRootVisible(false):隐藏根结点

DefaultMutableTreeNode其他成员方法:

Enumeration breadthFirstEnumerationO/preorderEnumeration(): 按广度优先的顺序遍历以此结点为根的子树,并返回所有结点组成的枚举对象 。
Enumeration depthFirstEnumerationO/postorderEnumeration(): 按深度优先的顺序遍历以此结点为根的子树,并返回所有结点组成的枚举对象 。
DefaultMutableTreeNode getNextSibling(): 返回此结点的下一个兄弟结点 。
TreeNode getParent(): 返回此结点的父结点 。 如果此结点没有父结点,则返回null 。
TreeNode[] getPath(): 返回从根结点到达此结点的所有结点组成的数组。
DefaultMutableTreeNode getPreviousSibling(): 返回此结点的上一个兄弟结点。
TreeNode getRoot(): 返回包含此结点的树的根结点 。
TreeNode getSharedAncestor(DefaultMutableTreeNode aNode): 返回此结点和aNode最近的共同祖先 。
int getSiblingCount(): 返回此结点的兄弟结点数 。
boolean isLeaf(): 返回该结点是否是叶子结点 。
boolean isNodeAncestor(TreeNode anotherNode): 判断anotherNode是否是当前结点的祖先结点(包括父结点) 。
boolean isNodeChild(TreeNode aNode): 如果aNode是此结点的子结点,则返回true。
boolean isNodeDescendant(DefaultMutableTreeNode anotherNode): 如果 anotherNode 是此结点的后代,包括是此结点本身、此结点的子结点或此结点的子结点的后代,都将返回true 。
boolean isNodeRelated(DefaultMutableTreeNode aNode) : 当aNode和当前结点位于同一棵树中时返回 true 。
boolean isNodeSibling(TreeNode anotherNode): 返回anotherNode是否是当前结点的兄弟结点 。
boolean isRoot(): 返回当前结点是否是根结点 。
Enumeration pathFromAncestorEnumeration(TreeNode ancestor): 返回从指定祖先结点到当前结点的所有结点组成的枚举对象 。

(2)、结点编辑

package container;


import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Demo {

    JFrame jf ;
    JTree tree;

    //JTree关联的数据模型对象
    DefaultTreeModel model;

    //定义几个初始结点
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
    DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
    DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
    DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
    DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
    DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
    DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");

    //定义需要被拖动的TreePath
    TreePath movePath;

    //定义按钮,完成操作
    JButton addSiblingBtn = new JButton("添加兄弟结点");
    JButton addChildBtn = new JButton("添加子结点");
    JButton deleteBtn = new JButton("删除结点");
    JButton editBtn = new JButton("编辑当前结点");

    public Demo(){

        //通过add()方法建立父子层级关系
        guangdong.add(foshan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanning);
        root.add(guangdong);
        root.add(guangxi);

        jf = new JFrame("可编辑结点的树");
        tree = new JTree(root);

        //获取JTree关联的数据模型TreeModel对象
        model = (DefaultTreeModel) tree.getModel();

        //设置JTree可编辑
        tree.setEditable(true);

        //创建鼠标事件监听器
        MouseListener ml = new MouseAdapter() {

            //按下鼠标时,获得被拖动的结点
            @Override
            public void mousePressed(MouseEvent e) {
                //如果需要唯一确定某个结点,则必须通过TreePath来获取
                TreePath tp = tree.getPathForLocation(e.getX(), e.getY());
                if (tp!=null){
                    movePath = tp;
                }
            }

            //松开树表示,确定即将被拖入到的父结点
            @Override
            public void mouseReleased(MouseEvent e) {

                TreePath tp = tree.getPathForLocation(e.getX(), e.getY());
                if (tp!=null && movePath!=null){
                    //阻止向子结点拖动
                    if (movePath.isDescendant(tp) && movePath!=tp){
                        JOptionPane.showMessageDialog(jf,"目标结点是被移动结点的子结点,无法移动!","非法移动",JOptionPane.WARNING_MESSAGE);
                    }
                    //不是向子结点移动,并且鼠标按下和松开也不是同一个结点

                    if (movePath!=tp){
                        //add方法内部,先将该结点从原父结点删除,然后再把该结点添加到新结点中
                        DefaultMutableTreeNode tartParentNode = (DefaultMutableTreeNode) tp.getLastPathComponent();
                        DefaultMutableTreeNode moveNode = (DefaultMutableTreeNode) movePath.getLastPathComponent();
                        tartParentNode.add(moveNode);

                        movePath=null;
                        tree.updateUI();
                    }
                }
            }
        };

        //为JTree添加鼠标监听器
        tree.addMouseListener(ml);

        JPanel panel = new JPanel();

        addSiblingBtn.addActionListener(e -> {
            //获取选中结点
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();

            //如果结点为空,则直接返回
            if (selectedNode==null){
                return;
            }

            //获取该选中结点的父结点
            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();

            //如果父结点为空,则直接返回
            if (parent==null){
                return;
            }

            //创建一个新结点
            DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");

            //获取选中结点的索引
            int selectedIndex = parent.getIndex(selectedNode);

            //在选中位置插入新结点
            model.insertNodeInto(newNode,parent,selectedIndex);

            //----------显示新结点---------------
            //获取从根结点到新结点的所有结点
            TreeNode[] pathToRoot = model.getPathToRoot(newNode);

            //使用指定的结点数组创建TreePath
            TreePath treePath = new TreePath(pathToRoot);

            //显示指定的treePath
            tree.scrollPathToVisible(treePath);


        });

        panel.add(addSiblingBtn);

        addChildBtn.addActionListener(e -> {
            //获取选中结点
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();

            if (selectedNode==null){
                return ;
            }

            //创建新结点
            DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");

            //model.insertNodeInto(newNode,selectedNode,selectedNode.getChildCount());使用TreeModel的方法添加,不需要手动刷新UI
            selectedNode.add(newNode);//使用TreeNode的方法添加,需要手动刷新UI

            //显示新结点

            TreeNode[] pathToRoot = model.getPathToRoot(newNode);
            TreePath treePath = new TreePath(pathToRoot);
            tree.scrollPathToVisible(treePath);

            //手动刷新UI
            tree.updateUI();

        });

        panel.add(addChildBtn);

        deleteBtn.addActionListener(e -> {

            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();

            if (selectedNode!=null && selectedNode.getParent()!=null){
                model.removeNodeFromParent(selectedNode);
            }

        });

        panel.add(deleteBtn);

        //实现编辑结点的监听器
        editBtn.addActionListener(e -> {

            TreePath selectionPath = tree.getSelectionPath();

            if (selectionPath!=null){
                //编辑选中结点
                tree.startEditingAtPath(selectionPath);
            }

        });

        panel.add(editBtn);

        jf.add(new JScrollPane(tree));
        jf.add(panel, BorderLayout.SOUTH);

        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);

    }

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

(3)、监听节点事件

package container;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;

public class Demo {
    JFrame jf = new JFrame("监听树的选择事件");

    JTree tree;

    DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
    DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
    DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
    DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
    DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
    DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
    DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");

    JTextArea eventTxt = new JTextArea(5, 20);

    public void init() {

        //通过add()方法建立父子层级关系
        guangdong.add(foshan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanning);
        root.add(guangdong);
        root.add(guangxi);

        tree = new JTree(root);

        //添加监听器
        tree.addTreeSelectionListener(e -> {
            if (e.getOldLeadSelectionPath()!=null){
                eventTxt.append("原选中结点的路径:"+e.getOldLeadSelectionPath().toString()+"\n");
            }

            eventTxt.append("新选中结点的路径:"+e.getNewLeadSelectionPath().toString()+"\n");
        });

        tree.setShowsRootHandles(true);
        tree.setRootVisible(true);

        Box box = Box.createHorizontalBox();
        box.add(new JScrollPane(tree));
        box.add(new JScrollPane(eventTxt));

        jf.add(box);
        jf.pack();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);
    }

    public static void main(String[] args) {
        new Demo().init();
    }
}

(4)、修改结点外观

JTree默认的外观是比较单一的,它提供了如下几种改变结点外观的方式:

  1. 使用 DefaultTreeCellRenderer 直接改变节点的外观,这种方式可 以 改变整棵树所有节点 的字体、颜色和图标 。
  2. 为 JTree 指定 DefaultTreeCellRenderer 的扩展类对象作为 JTree 的节点绘制器,该绘制器负责为不同节点使用不同的字体、颜色和图标。通常使用这种方式来改变节点的外观 。
  3. 为 JTree 指定一个实现 TreeCellRenderer 接口的节点绘制器,该绘制器可以为不同的节点自由绘制任意内容,这是最复杂但最灵活的节点绘制器 。

第 一种方式最简单 , 但灵活性最差 ,因为它会改变整棵树所有节点的外观 。 在这种情况下 , Jtree的所有节点依然使用相同的图标 ,相当于整体替换了 Jtree 中 节点的所有默认图标 。 用户指定 的节点图标未必就比 JTree 默认的图标美观 。

DefaultTreeCellRenderer 提供了如下几个方法来修改节点的外观:

setBackgroundNonSelectionColor(Color newColor): 设置用于非选定节点的背景颜色 。
setBackgroundSelectionColor(Color newColor): 设置节点在选中状态下的背景颜色 。
setBorderSelectionColor(Color newColor): 设置选中状态下节点的边框颜色 。
setClosedIcon(Icon newIcon): 设置处于折叠状态下非叶子节点的图标 。
setFont(Font font) : 设置节点文本 的 字体。
setLeaflcon(Icon newIcon): 设置叶子节点的图标 。
setOpenlcon(Icon newlcon): 设置处于展开状态下非叶子节 点的图标。
setTextNonSelectionColor(Color newColor): 设置绘制非选中状态下节点文本的颜色 。
setTextSelectionColor(Color newColor): 设置绘制选中状态下节点文本的颜色 。
 使用 DefaultTreeCellRenderer 直接改变节点的外观

import cn.itcast.swing.util.ImagePathUtil;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;

public class ChangeAllCellRender {

    JFrame jf = new JFrame("改变所有结点外观");

    JTree tree;

    DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
    DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
    DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
    DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
    DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
    DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
    DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");

    public void init(){
        //通过add()方法建立父子层级关系
        guangdong.add(foshan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanning);
        root.add(guangdong);
        root.add(guangxi);

        tree = new JTree(root);

        //创建一个DefaultTreeCellRenderer对象
        DefaultTreeCellRenderer cellRenderer = new DefaultTreeCellRenderer();
        //设置非选定结点的背景颜色
        cellRenderer.setBackgroundNonSelectionColor(new Color(220,220,220));
        //设置选中结点的背景色
        cellRenderer.setBackgroundSelectionColor(new Color(140,140,140));
        //设置选中状态下结点的边框颜色
        cellRenderer.setBorderSelectionColor(Color.BLACK);
        //设置处于折叠状态下非叶子结点的图标
        cellRenderer.setClosedIcon(new ImageIcon(ImagePathUtil.getRealPath("10\\close.gif")));
        //设置结点文本的字体
        cellRenderer.setFont(new Font("SansSerif",Font.BOLD,16));
        //设置叶子结点图标
        cellRenderer.setLeafIcon(new ImageIcon(ImagePathUtil.getRealPath("10\\leaf.png")));
        //设置处于展开状态下非叶子结点图标跑
        cellRenderer.setOpenIcon(new ImageIcon(ImagePathUtil.getRealPath("10\\open.gif")));
        //设置绘制非选中状态下结点文本颜色
        cellRenderer.setTextNonSelectionColor(new Color(255,0,0));
        //设置选中状态下结点的文本颜色
        cellRenderer.setTextSelectionColor(new Color(0,0,255));

        tree.setCellRenderer(cellRenderer);

        tree.setShowsRootHandles(true);

        tree.setRootVisible(true);

        jf.add(new JScrollPane(tree));
        jf.pack();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);

    }


    public static void main(String[] args) {
        new ChangeAllCellRender().init();
    }

}
扩展DefaultTreeCellRenderer改变结点外观

DefaultTreeCellRenderer 实现类实现了TreeCellRenderer接口,该接口里只有 一个用于绘制节点内容的方法: getTreeCellRendererComponent() , 该方法负责绘制 JTree 节点 。学习JList的时候,如果要绘制JList的列表项外观的内容,需要实现ListCellRenderer 接口,通过重写getTreeCellRendererComponent()方法返回一个Component 对象 , 该对象就是 JTree 的节点组件 。两者之间非常类似

DefaultTreeCellRende rer 类继承了JLabel,实现 getTreeCellRendererComponent()方法时返回 this ,即返回一个特殊的 JLabel 对象 。 如果需要根据节点内容来改变节点的外观,则可以再次扩展DefaultTreeCellRenderer 类,并再次重写它提供的 getTreeCellRendererComponent()方法。

自定义类继承DefaultTreeCellRenderer,重写getTreeCellRendererComponent()方法 

import cn.itcast.swing.util.ImagePathUtil;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;

public class ExtendsDefaultCellTreeRenderer {

    JFrame jf = new JFrame("根据结点类型定义图标");

    JTree tree;

    //定义几个初始结点
    DefaultMutableTreeNode root = new DefaultMutableTreeNode(new NodeData(DBObjectType.ROOT,"数据库导航"));
    DefaultMutableTreeNode salaryDb = new DefaultMutableTreeNode(new NodeData(DBObjectType.DATABASE,"公司工资数据库"));
    DefaultMutableTreeNode customerDb = new DefaultMutableTreeNode(new NodeData(DBObjectType.DATABASE,"公司客户数据库"));
    DefaultMutableTreeNode employee = new DefaultMutableTreeNode(new NodeData(DBObjectType.TABLE,"员工表"));
    DefaultMutableTreeNode attend = new DefaultMutableTreeNode(new NodeData(DBObjectType.TABLE,"考勤表"));
    DefaultMutableTreeNode concat = new DefaultMutableTreeNode(new NodeData(DBObjectType.TABLE,"联系方式表"));
    DefaultMutableTreeNode id = new DefaultMutableTreeNode(new NodeData(DBObjectType.INDEX,"员工ID"));
    DefaultMutableTreeNode name = new DefaultMutableTreeNode(new NodeData(DBObjectType.COLUMN,"姓名"));
    DefaultMutableTreeNode gender = new DefaultMutableTreeNode(new NodeData(DBObjectType.COLUMN,"性别"));

    public void init(){
        //通过结点的add方法,建立结点的父子关系

        root.add(salaryDb);
        root.add(customerDb);

        salaryDb.add(employee);
        salaryDb.add(attend);

        customerDb.add(concat);

        concat.add(id);
        concat.add(name);
        concat.add(gender);

        tree = new JTree(root);

        tree.setCellRenderer(new MyRenderer());

        tree.setShowsRootHandles(true);
        tree.setRootVisible(true);

        //设置使用windows外观风格
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();
        }

        //更新JTree的UI外观
        SwingUtilities.updateComponentTreeUI(tree);

        jf.add(new JScrollPane(tree));
        jf.pack();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);

    }

    public static void main(String[] args) {
        new ExtendsDefaultCellTreeRenderer().init();
    }

    class MyRenderer extends DefaultTreeCellRenderer{
        //初始化5个图标
        ImageIcon rootIcon = new ImageIcon(ImagePathUtil.getRealPath("10\\root.gif"));
        ImageIcon databaseIcon = new ImageIcon(ImagePathUtil.getRealPath("10\\database.gif"));
        ImageIcon tableIcon = new ImageIcon(ImagePathUtil.getRealPath("10\\table.gif"));
        ImageIcon columnIcon = new ImageIcon(ImagePathUtil.getRealPath("10\\column.gif"));
        ImageIcon indexIcon = new ImageIcon(ImagePathUtil.getRealPath("10\\index.gif"));

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            //执行父类默认的绘制结点操作
            super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus);
            DefaultMutableTreeNode  node = (DefaultMutableTreeNode) value;

            NodeData data = (NodeData) node.getUserObject();
            //根据结点数据中的nodeType决定结点的图标
            ImageIcon icon = null;
            switch (data.nodeType){
                case DBObjectType.ROOT:
                    icon = rootIcon;
                    break;
                case DBObjectType.DATABASE:
                    icon = databaseIcon;
                    break;
                case DBObjectType.TABLE:
                    icon = tableIcon;
                    break;
                case DBObjectType.COLUMN:
                    icon = columnIcon;
                    break;
                case DBObjectType.INDEX:
                    icon = indexIcon;
                    break;
            }

            //改变图标
            this.setIcon(icon);

            return this;
        }
    }


    //定义一个NodeData类,用于封装结点数据
    class NodeData{
        public int nodeType;
        public String nodeData;

        public NodeData(int nodeType, String nodeData) {
            this.nodeType = nodeType;
            this.nodeData = nodeData;
        }

        @Override
        public String toString() {
            return this.nodeData;
        }
    }

    //定义一个接口,该接口里包含数据库对象类型的常量
    interface  DBObjectType{
        int ROOT=0;
        int DATABASE=1;
        int TABLE=2;
        int COLUMN=3;
        int INDEX=4;
    }

}

 实现TreeCellRenderer接口改变结点外观

import cn.itcast.swing.util.ImagePathUtil;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;

public class CustomerTreeNode {

    JFrame jf = new JFrame("定制树的结点");

    JTree tree;

    //定义几个初始结点

    DefaultMutableTreeNode friends = new DefaultMutableTreeNode("我的好友");
    DefaultMutableTreeNode qingzhao = new DefaultMutableTreeNode("李清照");
    DefaultMutableTreeNode suge = new DefaultMutableTreeNode("苏格拉底");
    DefaultMutableTreeNode libai = new DefaultMutableTreeNode("李白");
    DefaultMutableTreeNode nongyu = new DefaultMutableTreeNode("弄玉");
    DefaultMutableTreeNode hutou = new DefaultMutableTreeNode("虎头");

    public void init() {

        friends.add(qingzhao);
        friends.add(suge);
        friends.add(libai);
        friends.add(nongyu);
        friends.add(hutou);

        tree = new JTree(friends);

        tree.setShowsRootHandles(true);
        tree.setRootVisible(true);


        tree.setCellRenderer(new ImageCellRenderer());



        jf.add(new JScrollPane(tree));
        jf.pack();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);

    }

    public static void main(String[] args) {
        new CustomerTreeNode().init();
    }


    class ImageCellRenderer extends JPanel implements TreeCellRenderer {

        private ImageIcon icon;
        private String name;
        //定义绘制单元格时的背景色
        private Color background;
        //定义绘制单元格时的前景色
        private Color foreground;


        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            icon = new ImageIcon(ImagePathUtil.getRealPath("10\\" + value + ".gif"));

            name = value.toString();

            background = hasFocus ? new Color(140, 200, 235) : new Color(255, 255, 255);
            foreground = hasFocus ? new Color(255,255,3) : new Color(0,0,0);
            //返回当前JPanel作为结点
            return this;
        }

        //重写paintComponent改变JPanel的外观

        @Override
        protected void paintComponent(Graphics g) {
            int imageWidth = icon.getImage().getWidth(null);
            int imageHeight = icon.getImage().getHeight(null);
            g.setColor(background);
            g.fillRect(0,0,getWidth(),getHeight());

            g.setColor(foreground);
            //绘制好友图标
            g.drawImage(icon.getImage(),getWidth()/2-imageWidth/2,10,null);

            //绘制好友姓名
            g.setFont(new Font("SansSerif",Font.BOLD,18));

            g.drawString(name,getWidth()/2-name.length()*10,imageHeight+30);

        }


        //设置当前组件结点最佳大小
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(80,80);
        }
    }
}

12、表格

(1)、JTable基本使用

package container;

import javax.swing.*;

public class Demo {

    JFrame jFrame = new JFrame("简单表格");

    //一维数组->标题
    Object[] titles= {"姓名","年龄","性别"};
    //二维数组->数据
    Object[][] data = {
            {"李清照",29,"女"},
            {"苏格拉底",56,"男"},
            {"李白",35,"男"},
            {"弄玉",18,"女"},
            {"虎头",2,"男"},
    };

    public Demo(){

        JTable jTable =new JTable(data,titles);
        jFrame.add(new JScrollPane(jTable));

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

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

(2)、调整表格

package container;

import javax.swing.*;
import javax.swing.table.TableColumn;

public class Demo {

    JFrame jFrame = new JFrame("简单表格");

    //一维数组->标题
    String[] titles= {"姓名","年龄","性别"};
    //二维数组->数据
    Object[][] data = {
            {"李清照",29,"女"},
            {"苏格拉底",56,"男"},
            {"李白",35,"男"},
            {"弄玉",18,"女"},
            {"虎头",2,"男"},
    };

    public Demo(){

        JTable jTable =new JTable(data,titles);
        //设置随意选择
        jTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        TableColumn column_1 = jTable.getColumn(titles[0]);
        //设置最小列宽
        column_1.setMinWidth(40);
        TableColumn column_3 = jTable.getColumn(titles[2]);
        //设置最大列宽
        column_3.setMaxWidth(50);

        jFrame.add(new JScrollPane(jTable));

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

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

(3)、TableModel

package container;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

public class Demo {

    JFrame jFrame = new JFrame("简单表格");

    //一维数组->标题
    Object[] titles= {"姓名","年龄","性别"};
    //二维数组->数据
    Object[][] data = {
            {"李清照",29,"女"},
            {"苏格拉底",56,"男"},
            {"李白",35,"男"},
            {"弄玉",18,"女"},
            {"虎头",2,"男"},
    };

    private Vector titlesV = new Vector();
    private Vector<Vector> dataV = new Vector<>();

    public Demo(){

        for (Object title : titles) {
            titlesV.add(title);
        }

        for (Object[] datum : data) {
            Vector temp = new Vector();
            for (Object o : datum) {
                temp.add(o);
            }
            dataV.add(temp);
        }
        MyTableModel myTableModel = new MyTableModel();
        JTable jTable =new JTable(myTableModel);
        //设置随意选择
        jTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        TableColumn column_1 = jTable.getColumn(titles[0]);
        //设置最小列宽
        column_1.setMinWidth(40);
        TableColumn column_3 = jTable.getColumn(titles[2]);
        //设置最大列宽
        column_3.setMaxWidth(50);

        jFrame.add(new JScrollPane(jTable));

        JButton jButton = new JButton("获取选中行数据");
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selectedColumn = jTable.getSelectedColumn();
                int selectedRow = jTable.getSelectedRow();
                System.out.println("当前选中的行索引:" + selectedColumn);
                System.out.println("当前选中的列索引:" + selectedRow);

                //Object valueAt = myTableModel.getValueAt(selectedRow, selectedColumn);
                Object valueAt = jTable.getValueAt(selectedRow, selectedColumn);
                System.out.println("当前选中单元格的数据是:" + valueAt);
            }
        });

        jFrame.add(jButton, BorderLayout.SOUTH);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

    private class MyTableModel extends AbstractTableModel{
        @Override
        public int getRowCount() {
            return dataV.size();
        }

        @Override
        public int getColumnCount() {
            return titlesV.size();
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return dataV.get(rowIndex).get(columnIndex);
        }

        //饭后列名
        @Override
        public String getColumnName(int column) {
            return (String) titlesV.get(column);
        }

        //当前单元格是否可编辑
        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }
    }

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

(4)、添加删除行列

package container;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

public class Demo {

    JFrame jFrame = new JFrame("简单表格");

    //一维数组->标题
    Object[] titles= {"姓名","年龄","性别"};
    //二维数组->数据
    Object[][] data = {
            {"李清照",29,"女"},
            {"苏格拉底",56,"男"},
            {"李白",35,"男"},
            {"弄玉",18,"女"},
            {"虎头",2,"男"},
    };

    private Vector titlesV = new Vector();
    private Vector<Vector> dataV = new Vector<>();

    public Demo(){

        for (Object title : titles) {
            titlesV.add(title);
        }

        for (Object[] datum : data) {
            Vector temp = new Vector();
            for (Object o : datum) {
                temp.add(o);
            }
            dataV.add(temp);
        }

        DefaultTableModel model = new DefaultTableModel(dataV,titlesV);
        JTable jTable =new JTable(model);

        JButton addRow = new JButton("添加一行");
        JButton addColun = new JButton("添加一列");
        JButton deleteRow = new JButton("删除一行");

        addRow.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.addRow(new Object[]{"柳岩",18,"女"});
            }
        });

        addColun.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.addColumn("职业");
            }
        });

        deleteRow.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selectedRow = jTable.getSelectedRow();
                model.removeRow(selectedRow);
            }
        });

        jFrame.add(new JScrollPane(jTable));
        JPanel jPanel = new JPanel();
        jPanel.add(addRow);
        jPanel.add(addColun);
        jPanel.add(deleteRow);

        jFrame.add(jPanel,BorderLayout.SOUTH);

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }


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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值