Swing GUI简单模板

  • 以下面简单案列为例:

由5部分组成:

Main: 输入基本的初始化参数;

AlgoFrame: 视图层,初始化画布,读取数据,绘制图像等。

AlgoVisualizer: 控制层,

AlgoVisHelper: 工具类,辅助视图层和控制层,完成基本的图形绘制和延时等逻辑。

Circle: 数据类,待绘制图形的数据信息。
在这里插入图片描述

一、视图层 AlgoFrame

向render()函数中添加数据,然后重绘画布repaint(), repaint()函数调用画布类中的重载函数paintComponent()进行重绘。

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

public class AlgoFrame extends JFrame {

    private int canvasWidth;
    private int canvasHeight;


    public AlgoFrame(String title, int canvasWidth, int canvasHeight){
        super(title);

        this.canvasWidth = canvasWidth;
        this.canvasHeight = canvasHeight;

        Algocanvas canvas = new Algocanvas(); // 画布
        setContentPane(canvas);
        pack();

        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public int getCanvasWidth() {
        return canvasWidth;
    }

    public int getCanvasHeight() {
        return canvasHeight;
    }

    // TODO: 设置自己的数据
    private Circle[] circles;
    public void render(Circle[] circles){
        this.circles = circles;
        repaint();
    }

    // 内部类自定义画布
    private class Algocanvas extends JPanel{

        public Algocanvas() {
            // 双缓存
            super(true);  // 默认为true
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D)g;

            // 抗锯齿
            RenderingHints hints = new RenderingHints(
                                            RenderingHints.KEY_ANTIALIASING,
                                            RenderingHints.VALUE_ANTIALIAS_ON );
            g2d.addRenderingHints(hints);

            // 具体绘制
            // TODO: 绘制自己的数据data
            AlgoVisHelper.setStrokeWidth(g2d, 1);
            AlgoVisHelper.setColor(g2d, Color.RED);
            for(Circle circle : circles)
                if(!circle.isFilled)
                    AlgoVisHelper.strokeCircle(g2d, circle.x, circle.y, circle.getR());

                else
                    AlgoVisHelper.fillCircle(g2d, circle.x, circle.y, circle.getR());
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(canvasWidth, canvasHeight);
        }
    }
}

二、控制层

初始化数据初始化视图组成。

在初始化视图中完成需要的事件监听和动画逻辑(新线程)。

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class AlgoVisualizer {

    private Circle[] circles;
    private AlgoFrame frame;
    private boolean isAnimate = true;  // 动画是否执行

    public AlgoVisualizer(int sceneWidth, int sceneHeight, int N){

        // 初始化数据
        circles = new Circle[N];
        int R = 50;
        for (int i = 0; i < N; i++) {
            int x = (int)(Math.random()*(sceneWidth-2*R)) + R;
            int y = (int)(Math.random()*(sceneHeight-2*R)) + R;
            int vx = (int)(Math.random()*11) - 5;
            int vy = (int)(Math.random()*11) - 5;
            circles[i] = new Circle(x, y, R, vx, vy);
        }

        // 初始化视图
        EventQueue.invokeLater(() -> {
            frame = new AlgoFrame("Welcome", sceneWidth, sceneHeight);
            frame.addKeyListener(new AlgoKeyListener());
            frame.addMouseListener(new AlgoMouseListener());

            new Thread( () -> {
                run();
            }).start();
        });
    }

    // 动画逻辑
    private void run(){
        while(true){
            // 绘制数据
            frame.render(circles);
            AlgoVisHelper.pasue(20);

            // 更新数据
            if(isAnimate)
                for(Circle circle : circles)
                    circle.move(0, 0, frame.getCanvasWidth(), frame.getCanvasHeight());
        }
    }

    // 键盘监听内部类
    private class AlgoKeyListener extends KeyAdapter {

        @Override
        public void keyReleased(KeyEvent event) {
            if (event.getKeyChar() == ' ')
                isAnimate = !isAnimate;
        }
    }

    // 鼠标事件监听内部类
    private class AlgoMouseListener extends MouseAdapter{

        @Override
        public void mousePressed(MouseEvent event) {

            // 减去菜单栏对坐标的影响,使坐标原点位于画布左上角
            event.translatePoint(0,
                    -(frame.getBounds().height - frame.getCanvasHeight()));

            //System.out.println(event.getPoint());  // 打印鼠标点的位置
            for(Circle circle : circles)
                if(circle.contain(event.getPoint()))
                    circle.isFilled = !circle.isFilled;
        }
    }
}

三、工具层 AlgoVisHelper

简化基本的图形的绘制以及延时等常用操作。

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;

public class AlgoVisHelper {

    private AlgoVisHelper(){}

    public static final Color Red = new Color(0xF44336);
    public static final Color Pink = new Color(0xE91E63);
    public static final Color Blue = new Color(0x2196F3);
    public static final Color Green = new Color(0x4CAF50);
    public static final Color Yellow = new Color(0xFFEB3B);
    public static final Color Orange = new Color(0xFF9800);
    public static final Color Blank = new Color(0x000000);
    public static final Color White = new Color(0xFFFFFF);
    public static final Color Grey = new Color(0x9E9E9E);

    // 设置画笔宽度及样式
    public static void setStrokeWidth(Graphics2D g2d, int w) {
        int strokeWidth = w;
        g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
    }

    // 设置画笔颜色
    public static void setColor(Graphics2D g2d, Color color) {
        g2d.setColor(color);
    }

    // 绘制空心圆
    public static void strokeCircle(Graphics2D g2d, int x, int y, int r){
        Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r);
        g2d.draw(circle);
    }

    // 绘制实心圆
    public static void fillCircle(Graphics2D g2d, int x, int y, int r){
        Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r);
        g2d.fill(circle);
    }

    // 绘制空心矩形
    public static void strokeRectangle(Graphics2D g2d, int x, int y, int w, int h){
        Rectangle2D rectangle = new Rectangle2D.Double(x, y, w, h);
        g2d.draw(rectangle);
    }

    // 绘制实心矩形
    public static void fillRectangle(Graphics2D g2d, int x, int y, int w, int h){
        Rectangle2D rectangle = new Rectangle2D.Double(x, y, w, h);
        g2d.fill(rectangle);
    }

    // 读取图像到画布
    public static void putImage(Graphics2D g, int x, int y, String imageURL) {
        ImageIcon icon = new ImageIcon(imageURL);
        Image image = icon.getImage();

        g.drawImage(image, x, y, null);
    }

    // 打印文字到画布
    public static void drawText(Graphics2D g, String text, int centerx, int centery){
        if (text == null)
            throw new IllegalArgumentException("Text is null in drawText.");

        FontMetrics metrics = g.getFontMetrics();
        int w = metrics.stringWidth(text);
        int h = metrics.getDescent();
        g.drawString(text, centerx - w/2, centery + h);
    }

    // 延时函数
    public static void pasue(int t){
        try{
            Thread.sleep(t);
        }
        catch (InterruptedException e) {
            System.out.println("Error in Sleeping.");
        }
    }
}

四、数据层

绘制图形和逻辑有的数据类。

import java.awt.*;

public class Circle {

    public int x, y;
    private int r;
    public int vx, vy;
    public boolean isFilled = false;

    public Circle(int x, int y, int r, int vx, int vy){
        this.x = x;
        this.y = y;
        this.r = r;
        this.vx = vx;
        this.vy = vy;
    }

    public int getR(){return r;}

    public void move(int minx, int miny, int maxx, int maxy){
        x += vx;
        y += vy;

        checkCollision(minx, miny, maxx, maxy);
    }

    private void checkCollision(int minx, int miny, int maxx, int maxy){
        if(x - r < minx) { x = r;        vx = -vx; }
        if(x + r >= maxx){ x = maxx - r; vx = -vx; }
        if(y - r < miny) { y = r;        vy = -vy; }
        if(y + r >= maxy){ y = maxy - r; vy = -vy; }
    }

    public boolean contain(Point p){
        return (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y) <= r * r;
    }
}

五、测试

输入初始数据,即可开始测试。

public class Main {

    public static void main(String[] args) {

        int sceneWidth = 800;
        int sceneHeight = 600;
        int N = 20;

        AlgoVisualizer visualizer = new AlgoVisualizer(sceneWidth, sceneHeight, N);
    }
}

注: 该文为慕课网课程整理的笔记,若侵权请告知,立删。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值