Java-Swing实现520表白神器

我们首先看一下实现的效果:
在这里插入图片描述
这是打包后的exe文件执行的效果,但是在编辑器中运行的效果和exe文件运行的效果还是有点出入的。

比如打包以后窗口生成的位置有所变化,字体有些许模糊了,视觉上来看按钮变大了,颜色也不鲜艳了。

案例源码:

package frame;

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

public class MyFrame extends JFrame{
    //面板对象
    private JPanel mainPanel = new JPanel();
    //组件: JLabel标签  JButton按钮   JTextField文本框
    //展示一个图片
    private JLabel pictureLabel = new JLabel();
    //展示一个问题
    private JLabel questionLabel = new JLabel("你是不是喜欢我?");
    //两个按钮
    private JButton yesBtn = new JButton("YES");
    private JButton noBtn = new JButton("NO");

    public MyFrame(String title){
        super(title);
        this.init();
    }

    public void init(){
        this.setFontAndSoOn();
        this.addElements();
        this.addListener();
        this.setFrameSelf();
    }

    //设置字体 位置等
    public void setFontAndSoOn(){
        //宽500 高300
        //先将mainPanel的默认布局清空
        mainPanel.setLayout(null);
        //然后自己去摆放每一个组件的位置
        //布局: 流式、边界式、网格式,都不符合我们的要求,我们使用自定义布局
        //设置图片位置
        pictureLabel.setBounds(40,30,140,200);
        //设置图片边框
        pictureLabel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
        //添加图片,需要一个ImageIcon对象,自定义了一个drawImage方法
        pictureLabel.setIcon(this.drawImage("timg.gif",140,200));
        //设置问题label的位置
        questionLabel.setBounds(220,80,260,40);
        //questionLabel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
        questionLabel.setFont(new Font("黑体",Font.BOLD,22));
        //设置字体居中
        questionLabel.setHorizontalAlignment(SwingConstants.CENTER);
        //设置yes按钮位置
        yesBtn.setBounds(240,160,100,40);
        yesBtn.setFont(new Font("黑体",Font.BOLD,14));
        //设置鼠标点击该按钮时候的光标是一个小手
        yesBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        //设置no按钮位置
        noBtn.setBounds(360,160,100,40);
        noBtn.setFont(new Font("黑体",Font.BOLD,14));
        //设置鼠标点击该按钮时候的光标是一个小手
        noBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    }
    //添加元素
    public void addElements(){
        //将这些组件添加☞刚才的窗体内
        mainPanel.add(pictureLabel);
        mainPanel.add(questionLabel);
        mainPanel.add(yesBtn);
        mainPanel.add(noBtn);
        this.add(mainPanel);
    }
    //设置窗体本身
    public void setFrameSelf(){
        //设置窗口出现的位置和宽高
        this.setBounds(800,300,500,300);
        //窗口的关闭按钮默认是使得窗体隐藏,现在设置让它不关闭
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        //设置窗口大小不能拖拽
        this.setResizable(false);
        //设置窗口显示
        this.setVisible(true);
    }
    //单独设计一个方法,用来画一个图片
    public ImageIcon drawImage(String path, int width, int height){
        //通过一个给定的路径创建一个ImageIcon对象
//        ImageIcon imageIcon = new ImageIcon(path);
        ImageIcon imageIcon = new ImageIcon(MyFrame.class.getResource(path));
        //设置imageIcon对象的信息
        imageIcon.setImage(imageIcon.getImage().getScaledInstance(width,height,Image.SCALE_DEFAULT));
        return imageIcon;
    }
    //添加事件绑定(核心)
    public void addListener(){
        //yes按钮  单击,离开(失去焦点)  MouseAdapter是一个适配器,可以仅仅选择几个方法去实现
        yesBtn.addMouseListener(new MouseAdapter() {
            //单击
            public void mouseClicked(MouseEvent e) {
                //弹出一个小窗口,画一个小心心
                showHeart();
            }
            //离开
            public void mouseExited(MouseEvent e) {
                //让按钮还原
                yesBtn.setFont(new Font("黑体",Font.BOLD,14));
                //颜色变为黑色
                yesBtn.setForeground(Color.BLACK);
            }
        });
        //yes按钮  悬停(得到焦点)
        yesBtn.addMouseMotionListener(new MouseMotionAdapter() {
            //悬停
            public void mouseMoved(MouseEvent e) {
                //字体稍微变大一点
                yesBtn.setFont(new Font("黑体",Font.BOLD,18));
                //颜色变为红色
                yesBtn.setForeground(Color.RED);
            }
        });
        //----------------------------------------------------
        //no按钮  单击,离开(失去焦点)
        noBtn.addMouseListener(new MouseAdapter() {
            //单击
            public void mouseClicked(MouseEvent e) {
                //弹出一个小窗口,画一个小心心,把当前窗口隐藏,把下一个窗口运行出来
                showHeart();
            }
            //离开
            public void mouseExited(MouseEvent e) {
                //文本值变回去
                noBtn.setText("NO");
                //让按钮还原
                noBtn.setFont(new Font("黑体",Font.BOLD,14));
                //颜色变为黑色
                noBtn.setForeground(Color.BLACK);
            }
        });
        //no按钮  悬停(得到焦点)
        noBtn.addMouseMotionListener(new MouseMotionAdapter() {
            //悬停
            public void mouseMoved(MouseEvent e) {
                //文本值变为YES
                noBtn.setText("YES");
                //字体稍微变大一点
                noBtn.setFont(new Font("黑体",Font.BOLD,18));
                //颜色变为红色
                noBtn.setForeground(Color.RED);
            }
        });
        //---------------------------------------
        //窗体关闭按钮的事件绑定
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                int option = JOptionPane.showConfirmDialog(MyFrame.this,"你要把小可爱关掉嘛?嘤嘤嘤");
                //option有三个值,是==0,否==1,取消==2
                //逻辑上来讲,否和取消都是同一回事
                if(option==0)
                    JOptionPane.showMessageDialog(MyFrame.this,"关掉就有用了么???");
                else
                    JOptionPane.showMessageDialog(MyFrame.this,"哈哈哈,我就知道你舍不得我");
            }
        });
    }
    //点击yes按钮以后,弹出的新的窗口
    public void showHeart(){
        MyFrame.this.setVisible(false);//当前窗口隐藏
        //弹出新的窗口
        new HeartFrame();

    }
}

package frame;

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

public class HeartFrame extends JFrame {
    //设置心形图案的宽度和高度
    private static final int WIDTH = 520;
    private static final int HEIGHT = 520;
    //构造方法
    public HeartFrame(){
        super("我也喜欢你,爱心送给你");//窗口标题
        this.setFrameSelf();
    }
    public void setFrameSelf(){
        this.setBackground(Color.BLACK);
        this.setBounds(800,200,WIDTH,HEIGHT);//设置窗体宽高和显示位置
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);//不可拖拽
        this.setVisible(true);
    }
    //设计一个方法,用来画心形图案  规则,算法
    //需要提供一支笔:Graphics,提供O点坐标(x,y),半径r
    public void drawHeart(Graphics pic,int x,int y,int r){
        //求直角边长  已知 根号2 = 1.414
        int offset = (int)(r / 1.414);
        int c1x = x - (r -offset) /2;  //c1的x坐标  O的x 减去 (r - 直角边)/2
        int c1y = y - (r -offset) /2;  //c1的y坐标  O的y 减去 (r - 直角边)/2 -->小三角形两个直角
        int c2x = c1x - offset *2 -1;  //c2的x坐标  c1的x 减去2个直角边 -1 (因为像素点四舍五入)
        int c2y = c1y + offset*2;      //c2的y坐标  c1的y 减去2个直角边
        int c3x = x + (r - offset) / 2;//c3的x坐标  O的x 加上 (r - 直角边)/2
        int c3y = y - (r - offset) / 2;//c3的y坐标  O的y 减去 (r - 直角边)/2
        int c4x = c3x + offset * 2 + 1;//c4的x坐标  c3的x 加上 2个直角边 + 1 (因为像素点四舍五入)
        int c4y = c3y + offset * 2;    //c4的y坐标  c3的y 加上2个直角边
        int ex = x;                    //e的x坐标   就是O的x坐标
        int ey = c2y + (x - c2x);      //e的y坐标   c2的y 加上一个下面大的直角边(O的x - c2的x)
        int leftArcX = c1x - r - offset;   //Q的x坐标  c1的x 减去一个直角边 减去一个半径
        int leftArcY = c1y - (r - offset); //Q的y坐标  c1的y 减去一个 (半径 - 直角边)
        int rightArcX = c1x;      //Q' 的x坐标  与c1的x坐标一致
        int rightArcY = leftArcY; //Q' 的y坐标  与Q的y坐标一致
        //设置画图的颜色
        pic.setColor(Color.MAGENTA);//magenta 品红色
        //画一条线,从O点到c1点
        pic.drawLine(x,y,c1x,c1y);
        //画一条线,从O点到c3点
        pic.drawLine(x,y,c3x,c3y);
        //画左边的半圆形
        //从Q点的x和y坐标 长和宽(相等就变成圆形了) 水平开始逆时针偏移45度开始,画180度
        pic.drawArc(leftArcX,leftArcY,r*2,r*2,45,180);
        //画右边的半圆形
        //从Q'点的x和y坐标 长和宽 水平方向 水平开始逆时针偏移315度开始,逆时针画180度
        pic.drawArc(rightArcX,rightArcY,r*2,r*2,315,180);
        //画一条线,从c2点到e点
        pic.drawLine(c2x,c2y,ex,ey);
        //画一条线,从c4点到e点
        pic.drawLine(c4x,c4y,ex,ey);
    }
    //重写过来的paint方法  让它按照我们刚才设计的心形的规则描绘出这个窗体的面板
    public void paint(Graphics g){
        //一次性出来的
/*        Image image = this.createImage(WIDTH,HEIGHT);
        Graphics pic = image.getGraphics();
        this.drawHeart(pic,WIDTH/2,HEIGHT/2-100,100);
        g.drawImage(image,0,0,this);*/

        //由小变大
/*        for(int i = 1;i<=100;i++){
            Image image = this.createImage(WIDTH,HEIGHT);
            Graphics pic = image.getGraphics();
            this.drawHeart(pic,WIDTH/2,HEIGHT/2-200+i,i);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            g.drawImage(image,0,0,this);
        }*/

        //画10个心形图案,去叠加
        for(int count = 1;count<=10;count++){
            for(int i = 1;i<=100;i++){
                Image image = this.createImage(WIDTH,HEIGHT);
                Graphics pic = image.getGraphics();
                this.drawHeart(pic,WIDTH/2,HEIGHT/2-200+i,i);
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //每一次画完之后,将最后那个心形留在页面上
                for(int show = 1;show<=count;show++){
                    drawHeart(pic,WIDTH/2,HEIGHT/2-100-show,100-show);
                }
                //中间输出一个文字
                pic.drawString("我也喜欢你",WIDTH/2-30,HEIGHT/2);
                g.drawImage(image,0,0,this);
            }
        }

    }

}
package frame;

public class TestMain {
    public static void main(String[] args) {
        new MyFrame("I  Love  You");
    }
}

整个案例中就只有画心形图案的方法有些复杂,我至今也不是很懂。
在这里插入图片描述

画GUI界面和事件绑定虽然代码量多,但实际上难度并不大。

通过这个案例学到了:

  1. Java中使用Swing构建GUI界面的基本操作
  2. 了解到了画心形图案的相关算法
  3. 掌握了Java代码打包成 jar包的方式
  4. 学会了图片类静态资源无法打包成 jar的解决方案
  5. 掌握了使用 exe4j 将可执行 jar 打包成exe的方式

猜你喜欢

转载自blog.csdn.net/qq_43598138/article/details/106306565