Java定时弹窗提示与开启多线程展示图片

自顶向下介绍,首先是定时弹窗功能,可以用Java自带的ScheduledExecutorService库完成函数调用。
package healthReminder;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TimerScheduledTask {

    // how to write a timer task?
    // https://blog.csdn.net/qq_39731011/article/details/123332641
    public static void main(String[] args) {
        // This class is a subclass of Thread
        OpenAPicture oap = new OpenAPicture();
        ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
        ses.scheduleAtFixedRate(()->{
            // static method to show dialog
// print current time System.out.println(new Date().toString().substring(4, 19));
TipAfterAWhile.showAlarm(); oap.start(); },
1, 3000, TimeUnit.SECONDS); } }

其次是所被调用的函数,即弹窗。

窗口布局为:标题、文本区、勾选框、两个按键,其中一个按键同右上角一样功能为关闭,另一个按键用于打开一张图片。

该程序为设计窗口布局和功能。

package healthReminder;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

public class TipAfterAWhile extends JDialog {

    private static final long serialVersionUID = -6493879146336970741L;
    private final JPanel contentPanel = new JPanel();

    /**
     * Launch the application.
     */
    public static void showAlarm() {
        try {
            // UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Throwable e) {
            e.printStackTrace();
        }

        try {
            TipAfterAWhile dialog = new TipAfterAWhile();
            dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dialog.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public TipAfterAWhile() {
        setTitle("Health Reminder");
        setBounds(100, 100, 480, 300);
        getContentPane().setLayout(new BorderLayout());
        contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        getContentPane().add(contentPanel, BorderLayout.CENTER);
        contentPanel.setLayout(new BorderLayout(0, 0));
        
        {
            JPanel panel = new JPanel();
            contentPanel.add(panel, BorderLayout.NORTH);
            {
                JLabel label = new JLabel("Stand up and Relax!");
                label.setFont(new Font("微软雅黑", Font.PLAIN, 16));
                panel.add(label);
            }
        }

        {
            JPanel panel = new JPanel();
            contentPanel.add(panel, BorderLayout.SOUTH);
            panel.setLayout(new BorderLayout(0, 0));
            {
                JCheckBox checkBox = new JCheckBox("Don't Prompt Again!");
                checkBox.setFont(new Font("微软雅黑", Font.PLAIN, 16));
                panel.add(checkBox);
            }
        }
        {
            JPanel panel = new JPanel();
            contentPanel.add(panel, BorderLayout.WEST);
        }
        {
            JPanel panel = new JPanel();
            contentPanel.add(panel, BorderLayout.EAST);
        }
        {
            JScrollPane scrollPane = new JScrollPane();
            contentPanel.add(scrollPane, BorderLayout.CENTER);
            {
                JTextArea textArea = new JTextArea();
                textArea.setFont(new Font("微软雅黑", Font.PLAIN, 14));
                textArea.setLineWrap(true);
                textArea
                        .setText("You have been working for an hour, why not stand up and have a relax?");
                scrollPane.setViewportView(textArea);
            }
        }
        {
            JPanel buttonPane = new JPanel();
            buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
            getContentPane().add(buttonPane, BorderLayout.SOUTH);

            {
                JButton cancelButton = new JButton("Concel");
                cancelButton.setFont(new Font("微软雅黑", Font.PLAIN, 16));
                cancelButton.setActionCommand("Cancel");
                cancelButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        // dispose();  // 也可关闭但不是真的关闭
                        System.exit(0);
                    }
                });
                buttonPane.add(cancelButton);
            }
            {
                JButton okButton = new JButton("Give me a setu!");
                okButton.setFont(new Font("微软雅黑", Font.PLAIN, 16));
                okButton.setActionCommand("OK");
                OpenAPicture oap = new OpenAPicture();
                okButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        oap.start();
                    }
                }); buttonPane.add(okButton); getRootPane().setDefaultButton(okButton); } } } }

接着是打开一张图片的功能(作为按键事件监听器的调用方法),该方法会访问下述自定义JPanel子类,BackgroundPanel,功能是展示图片的。

package healthReminder;

import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;

public class BackgroundPanel extends JPanel {
    
    private static final long serialVersionUID = 1L;
    /**
     * 背景图片
     */
    private Image image;
    
    /**
     * 构造方法
     */
    public BackgroundPanel() {
        super();
        setOpaque(false);
        setLayout(null);
    }
    
    /**
     * 设置图片的方法
     */
    public void setImage(Image image) {
        this.image = image;
    }
    
    @Override
    protected void paintComponent(Graphics g) {// 重写绘制组件外观
        if (image != null) {
            g.drawImage(image, 0, 0, this);// 绘制图片与组件大小相同
            // System.out.println("repaint!");
        }
        super.paintComponent(g);// 执行超类方法
    }
}

最后一个功能,设计图片所用到的弹窗,将作为按键的监听器调用方法:

首先定义一个Thread的子类:

package healthReminder;

public class OpenAPicture extends Thread {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        new ShowAPictureOnJF();
    }
}

然后是方法本身:

package healthReminder;

import java.awt.BorderLayout;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ShowAPictureOnJF extends JFrame {

    private static final long serialVersionUID = 1L;
    
    private final JPanel contentPane = new JPanel();
    public ShowAPictureOnJF() {
        this.setTitle("relax");
        this.setBounds(100, 100, 960, 540);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.setVisible(true);
        String ppath = this.returnFileRandomly("D:/kingz/ANIME");
        System.out.println(ppath);
        setContentPane(this.contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));
        BackgroundPanel backgroundPanel = new BackgroundPanel();// 创建背景面板
        try {
            Image img1 = ImageIO.read(new File(ppath));
            backgroundPanel.setImage(img1);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // backgroundPanel.setImage(getToolkit().getImage(
        //         getClass().getResource(ppath)));// 设置面板背景图片
        
        contentPane.add(backgroundPanel);// 把背景面板添加到窗体内容面板
    }

    // 返回某文件夹下随机一张图片
    private String returnFileRandomly(String dpath) {
        File directory = new File(dpath);
        File[] flist = directory.listFiles();
        int fllen = flist.length;
        if (flist == null || fllen == 0) {
            return null;
        }
        System.out.println("this directory has "+fllen+" pictures.");
        ArrayList<String> pngjpglist = new ArrayList<String>();
        for (File f : flist) {
            String fname = f.getName();
            if (f.isDirectory() || !((fname.substring(fname.length()-3)).equals("jpg")
                     || (fname.substring(fname.length()-3)).equals("png"))) {
                continue;
            }else {
                // System.out.println(fname.substring(fname.length()-3));
                pngjpglist.add(fname);
            }
        }
        System.out.println("the jpg or png picture's number is "+pngjpglist.size());
        Random rd = new Random();
        int iterNum = rd.nextInt(pngjpglist.size());
        int indexCount = 0;
        Iterator<String> it = pngjpglist.iterator();
        while (it.hasNext()) {
            String string = (String) it.next();
            indexCount++;
            if (indexCount>=iterNum) {
                return dpath + "/" + string;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        new ShowAPictureOnJF();
        // System.out.println(returnFileRandomly("D:\\kingz\\ANIME"));
    }
}

那么如果想一次打开两张图片呢?那就定义多个线程即可

// 错误案例:
OpenAPicture oap = new OpenAPicture();
okButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        for (int i = 0; i < 2; i++) {
            oap.start();
        }
    }
});
// 正确示例:
// OpenAPicture oap = new OpenAPicture();
okButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        for (int i = 0; i < 2; i++) {
             new OpenAPicture().start();
        }
    }
});

然后可以把该项目在命令行中通过javac进行编译,然后再通过DOS命令写一个bat文件,就更方便了。(注意路径)

~\src>javac -encoding UTF-8  healthReminder/TimerScheduledTask.java
~\src>java healthReminder/TimerScheduledTask.java

编写文件 src/TimerAlarm.bat,内含1行指令。(注意路径)

java healthReminder/TimerScheduledTask.java

优化空间:图片自适应窗口大小进行缩放、窗口最大化、多文件夹下选择图片。

System.out.println(new Date().toString().substring(4, 19));
posted @ 2023-07-28 12:47  倦鸟已归时  阅读(122)  评论(0编辑  收藏  举报