JWindow是一個能夠在使用者桌面的任何地方顯示的容器,所以能夠使用它來建構提示訊息,如下圖所示。
1. 於桌面上任意地方彈出(右下)提示訊息之程式範例
◎主程式(呼叫PopupMessageModel)
public class PopupMessageDemo {
public static void main(String[] args) {
String[][] message = {{"1~ElsaElsaElsaElsa~1", "99最新訊息最新訊息最新訊息最新訊息最新訊息最新訊息最新訊息最新訊息99"},
{"2*ElsaElsaElsaElsaElsaElsaElsa*2", "6最新訊息最新訊息9"}};
new PopupMessageModel(message);
}
}
◎PopupMessageModel之建構子,並設定提示訊息顯示之位置與時間
其分為三種:
a. 顯示於桌面之正中央
new PopupMessageBuilder().withDelay(4000).withMessage(message).show();
b. 顯示於使用者指定之位置
new PopupMessageBuilder().at(new Point(10, 10)).withDelay(4000).withMessage(message).show();
c. 顯示在右下角
new PopupMessageBuilder().isBottomRight(true).withDelay(4000).withMessage(message).show();
或
newPopupMessageBuilder().at(new Point(10, 10)).isBottomRight(true).withDelay(4000).withMessage(message).show();
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
/**
*
* @author Elsa
*/
public class PopupMessageModel {
public PopupMessageModel(String[][] message) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
// setLookAndFeel()用於設置圖形介面的外觀,而在此可透過UIManager的getStstemLookAndFeelClassName回傳系統平台的String,例如:com.sun.java.swing.plaf.windows.WindowsLookAndFeel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new PopupMessageBuilder().isBottomRight(true).withDelay(4000).withMessage(message).show();
}
});
}
◎建置提示訊息之初始化元件、方法(PopupMessageBuilder)
/*
* 提示訊息之建置
*/
public class PopupMessageBuilder {
private int delay;
private Point location;
private boolean isBottomRight = false;
private String[][] strMessage;
private long startTime;
/*
* 設定視窗位置
*/
public PopupMessageBuilder at(Point p) {
this.location = p;
return this;
}
/*
* 判斷是否將視窗顯示在右下角
*/
public PopupMessageBuilder isBottomRight(boolean isBottomRight) {
this.isBottomRight = isBottomRight;
return this;
}
/*
* 設定視窗顯示之時間
*/
public PopupMessageBuilder withDelay(int delay) {
this.delay = delay;
return this;
}
/*
* 取得要顯示之資訊
*/
public PopupMessageBuilder withMessage(String[][] msg) {
this.strMessage = msg;
return this;
}
▲設定可使用之func,如isBottomRight、withDelay、withMessage
/*
* 設定顯示提示視窗之內容
*/
public PopupMessageBuilder show() {
int messageArrayLength = strMessage.length;
for(int i = 0; i < messageArrayLength; i++) {
// 1.設定frame之基本設定
final JWindow frame = new JWindow();
frame.setOpacity(0f); // 設定視窗為透明化,其值為0.0f~1.0f,大於或小於的話會出現IllegalArgumentException錯誤
frame.setBackground(new Color(0, 0, 0, 0));
MessagePane pane = new MessagePane(frame);
pane.setMessage(strMessage[i]); // 設定要顯示之訊息
frame.add(pane);
//frame.pack(); // 將視窗中的各個元件,自動依版面配置作適當的排列
frame.setVisible(true);
frame.setAlwaysOnTop(true);
// 2.設定提示視窗顯示之時間與消失之時間
new FadeTimer(frame, 1000, 0f, 1f, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Timer timer = new Timer(delay, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new FadeTimer(frame, 1000, 1f, 0f, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
}).start();
}
});
timer.setRepeats(false); //如為false,則timer只執行一次action
timer.start();
}
}).start();
// 3.判斷視窗顯示之位置
if (location == null && isBottomRight == false) { // 位置與右下角皆無設定者,其視窗置中
frame.setLocationRelativeTo(null);
} else if (location != null && isBottomRight == false){ // 有設定位置,且右下角為false者,依據使用者指定之位置顯示
frame.setLocation(location);
} else { // isBottomRight為true者,皆為顯示在右下角
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize(); // size of the screen
Insets toolHeight = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration()); // height of the task bar
frame.setLocation(scrSize.width - frame.getWidth(), scrSize.height - toolHeight.bottom - frame.getHeight() * (messageArrayLength - i)); //messageArrayLength-i用於設定第一筆在最上面之y位置
}
}
return this;
}
▲設定show func,其為JWindow、MessagePane等元件建置/初始化之部分,以及設定提示視窗顯示與消失之時間、位置等動作
/*
* 設置提示視窗顯示與消失之時間,以及隨之設定視窗的透明度,以達到漸顯之效果
*/
public class FadeTimer extends Timer implements ActionListener {
private final float startAt;
private final float endAt;
private final int duration;
private long startTimer;
private ActionListener endListener;
private Window window;
public FadeTimer(Window window, int duration, float startAt, float endAt, ActionListener endListener) {
super(5, null); // 每5秒執行一次
addActionListener(this);
this.duration = duration;
this.startAt = startAt;
this.endAt = endAt;
this.window = window;
this.endListener = endListener;
// 設定提示視窗之大小,如無設置則為依照字數長度來變動
this.window.setSize(300, 120);
}
@Override
public void start() {
startTime = System.currentTimeMillis(); // 取得系統目前之時間
super.start();
}
@Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long lapsed = now - startTime;
float opacity = startAt;
// 判斷是否超出預計之顯示時間,如超過的話,再停止Timer,並執行後續的ActionListener動作
if (lapsed >= duration) {
opacity = endAt; // 設定視窗透明度的數值,顯示為1f/隱藏0f
((Timer) e.getSource()).stop(); // 提示視窗往上顯示/往下縮小時,停止第一/二次呼叫之ActionListener
if (endListener != null) {
// ActionEvent(Object source, int id, String command) --> source - 發起事件的對象; id - 標識事件的整數; command - String型態,它可以用來指定與事件所相關的一條命令
// ActionEvent.ACTION_PERFORMED 代表此事件 id 指示發生了有意義的動作
endListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Stopped")); // 回到FadeTimer中的new ActionListener()的actionPerformed(ActionEvent e)方法,以執行後續的動作
}
} else { // 計算視窗的透明度
float progress = (float) lapsed / (float) duration;
float distance = endAt - startAt;
opacity = (float) (distance * progress);
opacity += startAt;
}
window.setOpacity(opacity); // 設定視窗的透明度
}
}
▲設置提示視窗顯示與消失之時間,以及隨之設定視窗的透明度,以達到漸顯之效果
/*
* 設置提示視窗相關元件之設定
*/
public class MessagePane extends JPanel {
private JLabel labBuyer, labGoodsName;
public MessagePane(JWindow frame) {
setBorder(new EmptyBorder(40, 40, 40, 40));
setOpaque(false); // 設置元件的透明度
setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
JLabel labInfoIcon = new JLabel();
labInfoIcon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/information.png")));
add(labInfoIcon, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 10, -1, -1));
JLabel labCloseButton = new JLabel();
labCloseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/close.png")));
labCloseButton.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
frame.dispose(); // 關閉視窗
}
public void mouseEntered(java.awt.event.MouseEvent evt) {
labCloseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/close_enter.png")));
}
public void mouseExited(java.awt.event.MouseEvent evt) {
labCloseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/close.png")));
}
public void mousePressed(java.awt.event.MouseEvent evt) {
labCloseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/close.png")));
}
});
add(labCloseButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(274, 10, -1, -1));
JLabel labTitle = new JLabel();
labTitle.setFont(new java.awt.Font("微軟正黑體", 1, 16));
labTitle.setForeground(new java.awt.Color(255, 255, 255));
labTitle.setText("新訊! 訊息通知");
add(labTitle, new org.netbeans.lib.awtextra.AbsoluteConstraints(50, 12, -1, -1));
JLabel labBuyerTitle = new JLabel();
labBuyerTitle.setFont(new java.awt.Font("微軟正黑體", 1, 14));
labBuyerTitle.setForeground(new java.awt.Color(255, 255, 255));
labBuyerTitle.setText("帳號:");
add(labBuyerTitle, new org.netbeans.lib.awtextra.AbsoluteConstraints(50, 40, -1, -1));
labBuyer = new JLabel();
labBuyer.setFont(new java.awt.Font("微軟正黑體", 1, 14));
labBuyer.setForeground(new java.awt.Color(255, 255, 255));
add(labBuyer, new org.netbeans.lib.awtextra.AbsoluteConstraints(95, 40, 170, -1));
JLabel labGoodsNameTitle = new JLabel();
labGoodsNameTitle.setFont(new java.awt.Font("微軟正黑體", 1, 14));
labGoodsNameTitle.setForeground(new java.awt.Color(255, 255, 255));
labGoodsNameTitle.setText("訊息內容:");
add(labGoodsNameTitle, new org.netbeans.lib.awtextra.AbsoluteConstraints(50, 62, -1, -1));
labGoodsName = new JLabel();
labGoodsName.setFont(new java.awt.Font("微軟正黑體", 1, 14));
labGoodsName.setForeground(new java.awt.Color(255, 255, 255));
add(labGoodsName, new org.netbeans.lib.awtextra.AbsoluteConstraints(122, 62, 140, -1));
JLabel labLogo = new JLabel();
labLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/logo.png")));
add(labLogo, new org.netbeans.lib.awtextra.AbsoluteConstraints(242, 90, -1, -1));
}
▲ 設置提示視窗相關元件之設定
/*
* 填入帳號與訊息內容之資訊
*/
public void setMessage(String[] msg) {
labBuyer.setText(msg[0]);
labGoodsName.setText(msg[1]);
}
▲ 設定訊息至label中
@Override
protected void paintComponent(Graphics g) { // 重繪元件
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 設定反鋸齒效果
/*g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); // 設定Alpha插值提示鍵
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); // 控制顏色的著色方式
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); // 控制如何處理抖動
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); // 文本的質量
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); // 確定怎麼做內插
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); // 設定如何呈現提示鍵
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); // 筆劃規範化控制提示鍵*/
// LinearGradientPaint提供利用線性顏色漸層模式填充形狀的方式,即可以指定二種或多種漸層顏色,及起始與結束點,以讓顏色呈現漸變之情況
// LinearGradientPaint(Point2D start, Point2D end, float[] fractions, Color[] colors)
// fractions 用於指定如何分布漸變的顏色,0f為起始色、1f結束色,其值的範圍從0f到1f,例如:{0.0f, 0.2f, 1.0f} <-> {Color.RED, Color.WHITE, Color.BLUE}
LinearGradientPaint linearGradientPaint = new LinearGradientPaint(
new Point(0, 0),
new Point(0, getHeight()),
new float[]{0f, 1f},
new Color[]{new Color(255, 145, 36), new Color(189, 94, 0)}); //淺橘 -> 深橘
// 設置透明化
//AlphaComposite.SRC_OVER:SRC類的又稱為[源模式],也就是將源(Source/src)放在上面,目標放在下面(Destination/dst),其有in - 忽略掉src在dst外面的部分、out - 忽略掉裡面部分、over - 覆蓋在dst的上面
float alpha = 0.8f;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
// 繪製圓角矩形
// Float(float x, float y, float w, float h, float arcw, float arch) --> x坐標、y坐標、RoundRectangle2D 的寬度、RoundRectangle2D 的高度、圓弧角的寬度、圓弧角的高度
RoundRectangle2D frame = new RoundRectangle2D.Float(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
g2d.setPaint(linearGradientPaint);
g2d.fill(frame);
g2d.setColor(Color.WHITE); // 設置畫筆顏色為白色
g2d.draw(frame);
}
▲ 重繪JPanel元件,以讓其呈現圓角矩形及具半透明之效果
2. 於桌面上任意地方彈出(右下)提示訊息之執行結果
▲顯示於桌面之正中央
▲ 設定訊息至label中
▲顯示於使用者指定之位置
▲ 提示訊息以漸變的方式消失於畫面中
參考網址:
http://www.28im.com/java/a441053.html