欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  Java

java图形化Swing教程(二)

程序员文章站 2022-04-09 14:20:33
...


与多线程、泛型等不同,Swing主要在于使用。
下面主要放代码和注释,少说话。

(一)共用代码

所有继承JFrame的类都要有一个开始的框架来包含他们,这里直接给出框架,以下几点中不会重复书写。

package Event;import java.awt.*;import javax.swing.*;/**
 * 
 * @author QuinnNorris
 * 共用代码
 */public class BaseFrame {
    /**
     * @param args
     */
    public static void main(String[] args) {        
    // TODO Auto-generated method stub

        // 开启一个线程,所有的Swing组件必须由事件分派线程进行配置,线程将鼠标点击和按键控制转移到用户接口组件。
        EventQueue.invokeLater(new Runnable() {            
        // 匿名内部类,是一个Runnable接口的实例,实现了run方法
            public void run() {

                JFrame frame = new *********();                
                // 将*号的地方换成你实现的JFrame的子类,来实现你的代码

                frame.setExtendedState(Frame.MAXIMIZED_BOTH);                
                // 将窗口最大化

                frame.setTitle("Christmas");                
                // 设置窗口标题

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                
                // 选择当用户关闭框架的时候进行的操作 ,在有些时候需要将窗口隐藏,不能直接退出需要用到这个方法

                frame.setVisible(true);                
                // 将窗口可见化,这样以便用户在第一次看见窗口之前我们能够向其中添加内容
            }

        });
    }

}

输出结果:得到一个基本的公用框架,以后的内容可以在其他类中书写,放入这个框架中。

(二)按钮事件

package Event;import java.awt.*;import javax.swing.*;import java.awt.event.*;/**
 * 
 * @author QuinnNorris 按钮事件
 */public class ButtonFrame extends JFrame {

    private JPanel buttonPanel;    
    private static final int DEFAULT_WIDTH = 300;    
    private static final int DEFAULT_HEIGHT = 200;    
    public ButtonFrame() {
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);        // 设置默认宽度和高度

        buttonPanel = new JPanel();        // 将类的实例域中的JPanel面板对象实例化

        makeButton("yellow",Color.YELLOW);
        makeButton("blue",Color.BLUE);
        makeButton("red",Color.RED);        //调用makeButton方法来创建并添加按钮

        add(buttonPanel);        // 我们将这个添加好按钮的面板添加到原框架中


    }    /**
     * 通过方法来创建按钮,并且完成关联监视器和添加入面板的操作
     * @param name 创建按钮的标识
     * @param backgroundColor 点击按钮后改变的颜色,匿名内部类只能访问final修饰的变量,所以要用final
     */
    public void makeButton(String name,final Color backgroundColor){

        JButton colorButton = new JButton(name);        
        //通过不同的标识名,我们创建按钮

        buttonPanel.add(colorButton);        
        //我们将创建的按钮添加到面板中

        //匿名内部类,创建一个ActionListener的实例
        colorButton.addActionListener(new ActionListener(){            
        /**
             * 当按钮点击的时候,会自动的调用actionPerformed方法
             */
            public void actionPerformed(ActionEvent event) {

                buttonPanel.setBackground(backgroundColor);                
                // 调用setBackground方法,设置背景颜色
            }
        });
    }

}

输出结果:在一个全屏窗口中,上方有三个不同颜色的按钮,按下去后,背景颜色会随之改变。

(三)更改主题

package Event;import java.awt.*;import javax.swing.*;import java.awt.event.*;/**
 * 
 * @author QuinnNorris 更换主题
 */public class MetalFrame extends JFrame {

    private JPanel buttonPanel;    
    private static final int DEFAULT_WIDTH = 300;    
    private static final int DEFAULT_HEIGHT = 200;    
    public MetalFrame() {

    
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);        // 设置默认宽度和高度

        buttonPanel = new JPanel();        // 将类的实例域中的JPanel面板对象实例化

        UIManager.LookAndFeelInfo[] infos = UIManager
                .getInstalledLookAndFeels();        // 调用这个静态方法,我们获得所有主题

        makeButton(infos);        // 调用makeButton方法来将主题实现

        add(buttonPanel);        // 我们将这个添加好按钮的面板添加到原框架中
    }    /**
     * 通过方法来创建所有的主题按钮,并且将他们关联监视器
     * 
     * @param infos
     *            包含有所有类型主题的数组
     */
    private void makeButton(final UIManager.LookAndFeelInfo[] infos) {        
    for (UIManager.LookAndFeelInfo info : infos) {
            JButton button = new JButton(info.getName());            
            // 用for-each循环来遍历所有的主题

            final UIManager.LookAndFeelInfo innerInfo = info;            
            // 将info复制并且定义位final类型,便于内部类的使用

            buttonPanel.add(button);            
            // 我们将创建的按钮添加到面板中

            // 匿名内部类,创建一个ActionListener的实例
            button.addActionListener(new ActionListener() {                
            /**
                 * 当按钮点击的时候,会自动的调用actionPerformed方法
                 */
                public void actionPerformed(ActionEvent ae) {                    
                try {

                        UIManager.setLookAndFeel(innerInfo.getClassName());                       
                        // 调用setLookAndFeel方法,更改主题

                        SwingUtilities.updateComponentTreeUI(buttonPanel);                        
                        // 通过这个静态方法,将更改的主题立即应用

                    } catch (Exception e) {                        
                    // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
        }

    }

}

输出结果:窗口上方有五个主题按钮,分别写着他们各自主题的名字,点击后会立即更改所属主题。

(四)按钮与击键动作

package Event;import javax.swing.*;import java.awt.*;import java.awt.event.*;/**
 * 
 * @author QuinnNorris 按钮与击键动作
 */public class ActionFrame extends JFrame {

    private JPanel buttonPanel;    
    private static final int DEFAULT_WIDTH = 300;    
    private static final int DEFAULT_HEIGHT = 200;    
    public ActionFrame() {

        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);        
        // 设置默认宽度和高度

        buttonPanel = new JPanel();        
        // 将类的实例域中的JPanel面板对象实例化

        Action yellowAction = new ColorAction("Yellow", Color.YELLOW);        
        // 创建一个自己定义的ColorAction对象yellowAction

        buttonPanel.add(new JButton(yellowAction));        
        // 创建一个按钮,其属性从所提供的 Action中获取

        add(buttonPanel);        
        // 我们将这个添加好按钮的面板添加到原框架中

        InputMap imap = buttonPanel
                .getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);        
                // 我们将JPanel对象的InputMap设置为第二种输入映射,并创建该对象

        imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");        
        // 在imap中通过调用击键类KeyStroke的静态方法设置击键输入ctrl+Y的组合
        // 第二个参数是一个标志参数,将这对参数用键值对的形式存入imap

        ActionMap amap = buttonPanel.getActionMap();        
        // 我们不能将InputMap直接和Action做映射,我们需要用ActionMap做过渡
        // 用JPanel中的getACtionMap方法获得amap对象

        amap.put("panel.yellow", yellowAction);        
        // 将imap中标记参数对应的击键组合和相应的Action组合起来
    }    public class ColorAction extends AbstractAction {

        /**
         * ColorAction的构造器,存放键值对
         * @param name 按钮的名称
         * @param c 按钮对应点击后显示的颜色
         */
        public ColorAction(String name, Color c) {
            putValue(Action.NAME, name);
            putValue(Action.SHORT_DESCRIPTION,                    
            "Set panel color to " + name.toLowerCase());
            putValue("color", c);            
            //在构造器中设置一些键值对映射,这些设置的属性将会被JPanel读取
        }        
        /**
         * 当按钮点击或击键的时候,会自动的调用actionPerformed方法
         */
        public void actionPerformed(ActionEvent event) {
            Color c = (Color) getValue("color");
            buttonPanel.setBackground(c);            
            // 调用setBackground方法,设置背景颜色
        }
    }
}

输出结果:窗口上方有yellow按钮,通过点击或者ctrl+Y都可以使背景变黄,鼠标悬停在上面一段时间会显示说明文字。

(五)鼠标操作

package Event;import javax.swing.*;/**
 * 
 * @author QuinnNorris
 * 继承JFrame的子类,将Component对象内容打包
 */public class MouseFrame extends JFrame{

    public MouseFrame(){
        add(new MouseComponent());        
        //向框架中添加一个JComponent的实例
        pack();
    }
}
package Event;import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;/**
 * 
 * @author QuinnNorris 鼠标点击
 */public class MouseComponent extends JComponent {

    private static final int SIDELENGTH = 100;    
    // 定义创造的正方形的边长

    private ArrayList<Rectangle2D> squares;    
    // 声明一个正方形集合

    private Rectangle2D current;    
    // java类库中用来描述矩形的类,它的对象可以看作是一个矩形

    /**
     * 构造器方法,做初始化工作
     */
    public MouseComponent() {

        squares = new ArrayList<>();
        current = null;

        addMouseListener(new MouseHandler());        
        // 添加一个我们实现的类,这个类继承了监测鼠标点击情况的MouseListener

        addMouseMotionListener(new MouseMotionHandler());        
        // 添加另一个实现类,这个类继承了监测鼠标移动情况的MouseMotionListener
    }    /**
     * 我们覆盖了这个以用来打印图形,将会被自动调用
     * 
     * @param g
     *            Graphics是我们要使用的2D的一个父类
     */
    public void paintComponent(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;        
        // 转换为我们需要使用的类型

        for (Rectangle2D r : squares)
            g2.draw(r);        
            // 对数组中的每个正方形,都进行绘制
    }    /**
     * 判断在这个坐标上是否有图形
     * 
     * @param p
     *            一对当前的x,y的坐标值
     * @return 返回存在的图形或者null
     */
    public Rectangle2D find(Point2D p) {        
    for (Rectangle2D r : squares) {            
    if (r.contains(p))                
    //contains方法测定坐标是否在图形的边界内

                return r;
        }        
        // 如果在squares这个数组中有这个位置的坐标,表明这个位置上非空
        // 返回这个位置上的对象

        return null;        
        // 否则如果什么都没有,返回null
    }    
    /**
     * 在这个坐标位置增加一个图形
     * @param p 坐标位置
     */
    public void add(Point2D p) {        
    double x = p.getX();        
    double y = p.getY();        
    //获取x和y的坐标

        current = new Rectangle2D.Double(x - SIDELENGTH / 2,
                y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH);        
                //用获得的坐标和既定的边长构建一个新的正方形,并将其赋值给current

        squares.add(current);        
        //将current添加到squares队列中

        repaint();        
        //重绘图像

    }    /**
     * 将这个位置的图形移除
     * @param s 代表所要移除的矩形对象
     */
    public void remove(Rectangle2D s) {        
    if (s == null)            
    return;        
    //如果要移除的内容为空,直接返回

        if (s == current)
            current = null;        
            //如果要移除的内容和current正指向的内容相同,则将current清空
        //避免发生不必要的错误

        squares.remove(s);        
        //将s从squares的列表中直接删去

        repaint();        
        //重绘图像
    }    
    /**
     * 
     * @author QuinnNorris 继承了MouseAdapter类的鼠标点击控制类
     */
    private class MouseHandler extends MouseAdapter {

        /**
         * 单击鼠标操作
         */
        public void mousePressed(MouseEvent event) {

            current = find(event.getPoint());            
            // 将鼠标单击的这个点的坐标的对象赋给current

            if (current == null)                
            //如果这个点没有对象,当前指向空的位置

                add(event.getPoint());                
                //在这个点绘制正方形
        }        
        /**
         * 鼠标双击操作
         */
        public void mouseClicked(MouseEvent event) {

            current = find(event.getPoint());            
            // 将鼠标单击的这个点的坐标的对象赋给current

            if (current != null && event.getClickCount() >= 2)                
            //如果这个点有对象,而且点击鼠标的次数大于2

                remove(current);                
                //移除current

        }
    }    
    /**
     * 
     * @author QuinnNorris
     * 鼠标移动拖动类
     */
    private class MouseMotionHandler implements MouseMotionListener {

        /**
         * 鼠标光标移动到组件上,但未按下时调用
         */
        public void mouseMoved(MouseEvent event) {            
        if (find(event.getPoint()) == null)                
        //如果鼠标所在位置不是空

                setCursor(Cursor.getDefaultCursor());                
                //则将光标的图像设置为默认的图像
            else
                setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));                
                //如果当前位置有图像,则将光标样式设置为手型
        }        /**
         * 鼠标光标在组件上按下,并拖动时调用
         */
        public void mouseDragged(MouseEvent event) {            
        if (current != null) {                
        //因为在调用这个方法之前肯定会调用点击鼠标的方法
                //所以我们直接判断:如果现在current不为空

                int x = event.getX();                
                int y = event.getY();                
                //获取到坐标

                current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2,
                        SIDELENGTH, SIDELENGTH);                
                        //最后在鼠标放下时进行图形绘制

                repaint();                
                //重绘图像
            }
        }
    }

}

输出结果:在这个窗体中,单击一次鼠标会创建一个100像素为边长的小正方形。在正方形内,双击或更多次点击会删除这个正方形。可以点住正方形并进行拖动,并且在指示正方形区域内时,鼠标指针变为手型指针。

与多线程、泛型等不同,Swing主要在于使用。
下面主要放代码和注释,少说话。

以上就是java图形化Swing教程(二)的内容,更多相关内容请关注PHP中文网(www.php.cn)!