Android like Toast in Swing

java, swing

Solution

Try this code for toast:

public class Test extends JFrame {

    private JPanel contentPane;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test frame = new Test();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Test() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JButton btnTestToast = new JButton("Test Toast");
        btnTestToast.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ToastMessage toastMessage = new ToastMessage("Sample text to toast ",3000);
                toastMessage.setVisible(true);
            }
        });
        contentPane.add(btnTestToast, BorderLayout.SOUTH);
    }

}

public class ToastMessage extends JDialog {
    int miliseconds;
    public ToastMessage(String toastString, int time) {
        this.miliseconds = time;
        setUndecorated(true);
        getContentPane().setLayout(new BorderLayout(0, 0));

        JPanel panel = new JPanel();
        panel.setBackground(Color.GRAY);
        panel.setBorder(new LineBorder(Color.LIGHT_GRAY, 2));
        getContentPane().add(panel, BorderLayout.CENTER);

        JLabel toastLabel = new JLabel("");
        toastLabel.setText(toastString);
        toastLabel.setFont(new Font("Dialog", Font.BOLD, 12));
        toastLabel.setForeground(Color.WHITE);

        setBounds(100, 100, toastLabel.getPreferredSize().width+20, 31);


        setAlwaysOnTop(true);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        int y = dim.height/2-getSize().height/2;
        int half = y/2;
        setLocation(dim.width/2-getSize().width/2, y+half);
        panel.add(toastLabel);
        setVisible(false);

        new Thread(){
            public void run() {
                try {
                    Thread.sleep(miliseconds);
                    dispose();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}

Problem

I am trying to develop a Toast (Android) like feature in my Swing application. As a standalone, its working perfectly. But when integrated into the application, its posing problems. The Class file is: ``` import java.awt.*; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.geom.RoundRectangle2D; import javax.swing.ImageIcon; import javax.swing.JDialog; import javax.swing.JLabel; import net.mindcrew.utils.LayoutHelper.Packer; public class Toast extends JDialog { String text; public Toast(String text) { this.text = text; initComponents(); } private void initComponents(){ setLayout(new GridBagLayout()); addComponentListener(new ComponentAdapter() { // Give the window an rounded rect shape. LOOKS GOOD // If the window is resized, the shape is recalculated here. @Override public void componentResized(ComponentEvent e) { setShape(new RoundRectangle2D.Double(0,0,getWidth(),getHeight(),50,50)); } }); setUndecorated(true); setSize(300,100); setLocationRelativeTo(null); getContentPane().setBackground(Color.BLACK); // Determine what the GraphicsDevice can support. GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); final boolean isTranslucencySupported = gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT); //If shaped windows aren't supported, exit. if (!gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT)) { System.err.println("Shaped windows are not supported"); } //If translucent windows aren't supported, //create an opaque window. if (!isTranslucencySupported) { System.out.println( "Translucency is not supported, creating an opaque window"); } // Set the window to 70% translucency, if supported. if (isTranslucencySupported) { setOpacity(0.9f); } ImageIcon loading = new ImageIcon(Toast.class.getResource("/net/mindcrew/utils/userinterface/resources/loading-photo.gif")); JLabel label = new JLabel(text); label.setForeground(Color.WHITE); label.setIcon(loading); Packer packer = new Packer(this); packer.pack(label).fillboth().west().inset(0, 50, 0, 20); } public static Toast showDailog(String textToDisplay){ final Toast toast = new Toast(textToDisplay); // Display the window. Thread thread = new Thread(new Runnable() { @Override public void run() { toast.setVisible(true); } }); thread.start(); return toast; } @Override public void hide(){ EventQueue.invokeLater(new Runnable() { @Override public void run() { setVisible(false); dispose(); } }); } public static void main(String... args){ Toast toast = Toast.showDailog("Display"); try{ Thread.sleep(5000); } catch (Exception e){} toast.hide(); } } ``` There may be some implementation faults, but this is the basic thing. This works well. But when I try to put it up in the way of a resource intensive operation, its tripping. As in the GIF animation is not showing up, which I think implies that its sort of stalled. The use is: ``` Toast toast = Toast.showDailog("Generating PDF"); //resource intensive operation. Takes about 3-5seconds to execute toast.hide(); ``` To add to my misery, even after the "Toast" has been disposed, the application is becoming dreadfully slow. I am pretty sure that the slowing down is not because of the operation in question, since its working perfectly if I do away with the "Toast". Can somebody please point out what is wrong here??? I went through this question. But the things there are far too complicated than what I am looking for. What I am looking for is a simple dialog. Not a full blown frame which needs to accommodate several components.

Original source