我正在尝试在Swing应用程序中开发类似Toast(Android)的功能。作为一个独立的,它的工作完美。但是当它集成到应用程序中时,就会出现问题。
Class文件是:
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();
}
}
可能存在一些实现错误,但这是基本的事情。
这很有效。但是当我试图把它放在资源密集型操作的方式时,它就会绊倒。正如在GIF动画中没有出现,我认为这意味着它的停滞不前。
用途是:
Toast toast = Toast.showDailog("Generating PDF");
//resource intensive operation. Takes about 3-5seconds to execute
toast.hide();
为了增加我的痛苦,即使在“Toast”被处理之后,应用程序也变得非常缓慢。我很确定放慢速度并不是因为有问题的操作,因为如果我放弃“吐司”,它的工作就会完美。
有人可以指出这里有什么问题吗?
我经历了this question。但那里的东西太复杂了,而不是我想要的东西。我正在寻找的是一个简单的对话框。不是一个需要容纳多个组件的完整框架。
答案 0 :(得分:6)
尝试使用此代码进行吐司:
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();
}
}
答案 1 :(得分:1)
我将其实现为与工具提示类似。它已经过测试和运作。
import java.awt.Color;
import java.awt.Label;
import java.awt.Point;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.Popup;
import javax.swing.PopupFactory;
public class Toast {
private final JComponent component;
private Point location;
private final String message;
private long duration; //in millisecond
public Toast(JComponent comp, Point toastLocation, String msg, long forDuration) {
this.component = comp;
this.location = toastLocation;
this.message = msg;
this.duration = forDuration;
if(this.component != null)
{
if(this.location == null)
{
this.location = component.getLocationOnScreen();
}
new Thread(new Runnable()
{
@Override
public void run()
{
Popup view = null;
try
{
Label tip = new Label(message);
tip.setForeground(Color.red);
tip.setBackground(Color.white);
view = PopupFactory.getSharedInstance().getPopup(component, tip , location.x + 30, location.y + component.getHeight() + 5);
view.show();
Thread.sleep(duration);
} catch (InterruptedException ex)
{
Logger.getLogger(Toast.class.getName()).log(Level.SEVERE, null, ex);
}
finally
{
view.hide();
}
}
}).start();
}
}
public static void showToast(JComponent component, String message)
{
new Toast(component, null, message, 2000/*Default 2 Sec*/);
}
public static void showToast(JComponent component, String message, Point location, long forDuration)
{
new Toast(component, location, message, forDuration);
}
}
要使用此课程,您只需致电showToast()
答案 2 :(得分:0)
可能是你需要的JOptionPane吗?
答案 3 :(得分:0)
我认为您可以通过不覆盖Dialog
中的隐藏方法并将showDialog
方法修改为以下内容来解决您的问题:
public static void showDailog(String textToDisplay){
final Toast toast = new Toast(textToDisplay);
// Display the window.
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try{
toast.setVisible(true);
Thread.sleep(5000);
toast.setVisible(false);
toast.dispose();
}
catch(Exception ex){
ex.printStackTrace();
}
}
});
thread.start();
}
答案 4 :(得分:0)
我做了一些对我有用的修改,希望这会有所帮助 Android like Toast using Java Swing
答案 5 :(得分:0)
您可以使用舍入的自我配置JFrame作为相对于应用程序窗口定位的叠加层。通过淡出它看起来像Android Toast。这是代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
class Toast extends JFrame {
private final float MAX_OPACITY = 0.8f;
private final float OPACITY_INCREMENT = 0.05f;
private final int FADE_REFRESH_RATE = 20;
private final int WINDOW_RADIUS = 15;
private final int CHARACTER_LENGTH_MULTIPLIER = 9;
private final int DISTANCE_FROM_PARENT_BOTTOM = 100;
public Toast(JFrame owner, String toastText) {
setTitle("Transparent JFrame Demo");
setLayout(new GridBagLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setUndecorated(true);
setFocusableWindowState(false);
setOpacity(0.4f);
// setup the toast lable
JLabel b1 = new JLabel(toastText);
b1.setForeground(Color.WHITE);
b1.setOpaque(false);
add(b1);
setSize(toastText.length() * CHARACTER_LENGTH_MULTIPLIER, 50);
int x = (int) (owner.getLocation().getX() + (owner.getWidth() / 2));
int y = (int) (owner.getLocation().getY() + owner.getHeight() - DISTANCE_FROM_PARENT_BOTTOM);
setLocation(new Point(x, y));
// configure frame
setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), WINDOW_RADIUS, WINDOW_RADIUS));
getContentPane().setBackground(new Color(0, 0, 0, 170));
}
public void fadeIn() {
setOpacity(0);
setVisible(true);
final Timer timer = new Timer(FADE_REFRESH_RATE, null);
timer.setRepeats(true);
timer.addActionListener(new ActionListener() {
private float opacity = 0;
@Override
public void actionPerformed(ActionEvent e) {
opacity += OPACITY_INCREMENT;
setOpacity(Math.min(opacity, MAX_OPACITY));
if (opacity >= MAX_OPACITY) {
timer.stop();
}
}
});
timer.start();
}
public void fadeOut() {
final Timer timer = new Timer(FADE_REFRESH_RATE, null);
timer.setRepeats(true);
timer.addActionListener(new ActionListener() {
private float opacity = MAX_OPACITY;
@Override
public void actionPerformed(ActionEvent e) {
opacity -= OPACITY_INCREMENT;
setOpacity(Math.max(opacity, 0));
if (opacity <= 0) {
timer.stop();
setVisible(false);
dispose();
}
}
});
setOpacity(MAX_OPACITY);
timer.start();
}
public static void makeToast(final JFrame owner, final String toastText, final int durationSec) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Toast toastFrame = new Toast(owner, toastText);
toastFrame.fadeIn();
Thread.sleep(durationSec * 1000);
toastFrame.fadeOut();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
public static void main(String args[]) {
final JFrame frame = new JFrame("Cloud Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jPanel = new JPanel();
jPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
JButton toastButton = new JButton("show toast");
jPanel.add(toastButton);
toastButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Toast.makeToast(frame, "a toast!", 3);
}
});
frame.add(jPanel);
frame.setSize(800, 600);
frame.setVisible(true);
}
}
答案 6 :(得分:0)
下面的类是ToastMessage.java,应提供类似于Android的Toast消息。使用new ToastMessage(this, "Short message here!");
从项目中调用它。注意this
可以是调用JFrame中的任何组件或面板,用于确定屏幕上的位置。
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
public class ToastMessage extends JDialog {
private static final long serialVersionUID = 1L;
private static Boolean spamProtect = false;
private final int milliseconds = 1500;
public ToastMessage(JComponent caller, String toastString) {
if(spamProtect) {
return;
}
setUndecorated(true);
setAlwaysOnTop(true);
setFocusableWindowState(false);
setLayout(new GridBagLayout());
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
panel.setBackground(new Color(160, 160, 160));
JLabel toastLabel = new JLabel(toastString);
toastLabel.setForeground(Color.WHITE);
panel.add(toastLabel);
add(panel);
pack();
Window window = SwingUtilities.getWindowAncestor(caller);
int xcoord = window.getLocationOnScreen().x + window.getWidth() / 2 - getWidth() / 2;
int ycoord = window.getLocationOnScreen().y + (int)((double)window.getHeight() * 0.75) - getHeight() / 2;
setLocation(xcoord, ycoord);
setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), 30, 30));
setVisible(true);
new Thread(){
public void run() {
try {
spamProtect = true;
Thread.sleep(milliseconds);
dispose();
spamProtect = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}