“千里冰封” 兄弟的截屏程序酷斃了,但是好像9月4日之后就沒有繼續(xù)更新了,我們來(lái)繼續(xù)為他的程序改進(jìn),順便也把我們這幾天都在講的2D繪制用進(jìn)來(lái),我們的目標(biāo)是讓冰封的截屏程序成為截屏程序里的王!
今天先改進(jìn)一下截圖時(shí)候的選框,還是先放上截圖的截圖(*o*):

這是原來(lái)的圖片,下面是改進(jìn)后的

和改進(jìn)的代碼部分:
這部分代碼插入 Temp類的paintComponent方法中的 if (showTip) 這句的前面
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 0.3F));
g2d.setColor(Color.RED.brighter().brighter());
int sX = Math.min(startX, endX);
int sY = Math.min(endY, startY);
g2d.fillRect(sX, sY, Math.abs(endX - startX), Math.abs(endY
- startY));
g2d.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 1F));
boolean drawCTip = endX - startX != 0 && endY - startY != 0;
if (drawCTip) {
String cTip = String.format("%dX%d", Math.abs(endX - startX),
Math.abs(endY - startY));
int cTipH = 20;
Font cTipFont = new Font("system", Font.BOLD, 16);
g2d.setFont(cTipFont);
int cTipW = SwingUtilities.computeStringWidth(
getFontMetrics(cTipFont), cTip);
g2d.setPaint(Color.BLACK);
int cStartY = sY - cTipH > 0 ? sY - cTipH : sY;
g2d.fillRect(sX, cStartY, cTipW, cTipH);
g2d.setPaint(Color.WHITE);
g2d.drawString(cTip, sX, cStartY == sY ? sY + cTipH - 3
: sY - 3);
}
g2d.dispose();
怎么樣,比起QQ的截圖程序,我們又近一步了,嗯。
posted @
2007-09-13 13:28 ruislan 閱讀(1488) |
評(píng)論 (10) |
編輯 收藏
摘要: 嗯,BeanSoft的話很有道理,令我敬佩,也許是昨天在下對(duì)那個(gè)“更好的”三個(gè)字感到一時(shí)憤慨,所以看到UI就自己擴(kuò)大了問題,想到迎合LookAndFeel上面去了,在此說(shuō)句對(duì)不起了。你的回帖里面偏重于從整個(gè)組件的設(shè)計(jì)和重用性上,我的文章主要講的是如何將2D繪制和組件的繪制結(jié)合起來(lái),看客如果既了解了如何繪制自己想要的組件,又能設(shè)計(jì)得體,重用性高的話也算是對(duì)我拋磚引玉的欣慰了。...
閱讀全文
posted @
2007-09-12 13:36 ruislan 閱讀(2440) |
評(píng)論 (11) |
編輯 收藏
看來(lái)我們的JTextField之旅也到了一個(gè)階段,已經(jīng)很不錯(cuò)了,現(xiàn)在我們來(lái)改造JButton,讓那個(gè)呆板的Swing看起來(lái)舒服一些。
還是先放上完成后的效果圖:

普通的狀態(tài)

鼠標(biāo)滑過(guò)

鼠標(biāo)按下
和代碼:
1 /**
2 * @(#)RJButton.java 0.1.0 2007-9-11
3 */
4 package ruislan.rswing;
5
6 import java.awt.AlphaComposite;
7 import java.awt.Color;
8 import java.awt.Font;
9 import java.awt.GradientPaint;
10 import java.awt.Graphics;
11 import java.awt.Graphics2D;
12 import java.awt.RenderingHints;
13 import java.awt.Shape;
14 import java.awt.event.MouseAdapter;
15 import java.awt.event.MouseEvent;
16 import java.awt.geom.RoundRectangle2D;
17
18 import javax.swing.JButton;
19
20 /**
21 * Custom JButton
22 *
23 * @version 0.1.0
24 * @author ruislan <a href="mailto:z17520@126.com"/>
25 */
26 public class RButton extends JButton {
27 private static final long serialVersionUID = 39082560987930759L;
28 public static final Color BUTTON_COLOR1 = new Color(205, 255, 205);
29 public static final Color BUTTON_COLOR2 = new Color(51, 154, 47);
30 // public static final Color BUTTON_COLOR1 = new Color(125, 161, 237);
31 // public static final Color BUTTON_COLOR2 = new Color(91, 118, 173);
32 public static final Color BUTTON_FOREGROUND_COLOR = Color.WHITE;
33 private boolean hover;
34
35 public RButton() {
36 setFont(new Font("system", Font.PLAIN, 12));
37 setBorderPainted(false);
38 setForeground(BUTTON_COLOR2);
39 setFocusPainted(false);
40 setContentAreaFilled(false);
41 addMouseListener(new MouseAdapter() {
42 @Override
43 public void mouseEntered(MouseEvent e) {
44 setForeground(BUTTON_FOREGROUND_COLOR);
45 hover = true;
46 repaint();
47 }
48
49 @Override
50 public void mouseExited(MouseEvent e) {
51 setForeground(BUTTON_COLOR2);
52 hover = false;
53 repaint();
54 }
55 });
56 }
57
58 @Override
59 protected void paintComponent(Graphics g) {
60 Graphics2D g2d = (Graphics2D) g.create();
61 int h = getHeight();
62 int w = getWidth();
63 float tran = 1F;
64 if (!hover) {
65 tran = 0.3F;
66 }
67
68 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
69 RenderingHints.VALUE_ANTIALIAS_ON);
70 GradientPaint p1;
71 GradientPaint p2;
72 if (getModel().isPressed()) {
73 p1 = new GradientPaint(0, 0, new Color(0, 0, 0), 0, h - 1,
74 new Color(100, 100, 100));
75 p2 = new GradientPaint(0, 1, new Color(0, 0, 0, 50), 0, h - 3,
76 new Color(255, 255, 255, 100));
77 } else {
78 p1 = new GradientPaint(0, 0, new Color(100, 100, 100), 0, h - 1,
79 new Color(0, 0, 0));
80 p2 = new GradientPaint(0, 1, new Color(255, 255, 255, 100), 0,
81 h - 3, new Color(0, 0, 0, 50));
82 }
83 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
84 tran));
85 RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0, w - 1,
86 h - 1, 20, 20);
87 Shape clip = g2d.getClip();
88 g2d.clip(r2d);
89 GradientPaint gp = new GradientPaint(0.0F, 0.0F, BUTTON_COLOR1, 0.0F,
90 h, BUTTON_COLOR2, true);
91 g2d.setPaint(gp);
92 g2d.fillRect(0, 0, w, h);
93 g2d.setClip(clip);
94 g2d.setPaint(p1);
95 g2d.drawRoundRect(0, 0, w - 1, h - 1, 20, 20);
96 g2d.setPaint(p2);
97 g2d.drawRoundRect(1, 1, w - 3, h - 3, 18, 18);
98 g2d.dispose();
99 super.paintComponent(g);
100 }
101 }
102
注意代碼中的幾個(gè)部分:
首先是paintComponent方法中最后一行,我們調(diào)用了父類的paintComponent方法,這是因?yàn)槲覀円扛割悂?lái)繪制字符,但是父類的這個(gè)方法除了繪制字符之外還會(huì)繪制其他的,所以我們需要關(guān)閉掉其他的(當(dāng)然我們也可以自己來(lái)繪制字符,但是JButton提供了方法為什么不用呢),所以我們?cè)跇?gòu)造方法那里調(diào)用了:
setBorderPainted(false);
setFocusPainted(false);
setContentAreaFilled(false);
告訴父類不用繪制邊框,不用繪制焦點(diǎn),不用繪制內(nèi)容部分,這部分我們自己來(lái)搞*o*。
然后就是這一句了g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)告訴繪制API我們需要平滑一點(diǎn),否則繪制出來(lái)會(huì)有很多鋸齒喲。
接下來(lái)的這一句g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,tran))告訴繪圖API我們需要繪制一個(gè)有透明度的,tran就是透明度(0-1)。
然后就是將邊框的邊角變直角為圓角,我們繪制一個(gè)RoundRectangle2D,這個(gè)就是邊角都為圓角的方形,然后我們根據(jù)這個(gè)方形來(lái)clip我們的方形,這樣方形就被RoundRectangle2D的圓角方形包裹,從而變成了圓角方形。
最后就是繪制外邊線和內(nèi)邊線,通過(guò)改變內(nèi)邊線和外邊線的色變從而造成陷入或者突出效果。
整個(gè)JButton改造完畢,如果你能夠活用clip的話,你也可以做一個(gè)五角星的JButton喲。
整個(gè)源代碼我連同Eclipse工程文件已經(jīng)打包成zip放在我的文件里面,下載鏈接如下:
http://www.tkk7.com/Files/ruislan/rswing-0.1.0.zip
posted @
2007-09-11 12:24 ruislan 閱讀(5553) |
評(píng)論 (20) |
編輯 收藏
昨天我們給JTextField增加了一個(gè)泡泡提示窗口,今天我們繼續(xù)昨天的,首先處理在顯示泡泡的時(shí)候忽略輸入的Backspace、Enter、Delete、Esc按鍵,然后加上錯(cuò)誤的時(shí)候的聲音提示,最后再給JTextField換裝備,讓它看起來(lái)像MSN 8.5beta的輸入框,還是先放上圖片:

這幅圖是MSN的輸入框,輸入框的內(nèi)部到光標(biāo)有一部分是有點(diǎn)毛玻璃的感覺,不過(guò)這個(gè)style是死的,我們改進(jìn)一下,我們的JTextField在輸入之前是看似普通的,在鼠標(biāo)放上去之后,看起來(lái)就與MSN的輸入框類似了,而且我們還給這個(gè)輸入框加入一個(gè)淡黃色的背景。
好了,現(xiàn)在很明確要做的事情了
1. 加入鼠標(biāo)事件監(jiān)聽器,監(jiān)聽MouseEnter和MouseExit事件,根據(jù)這個(gè)兩個(gè)事件設(shè)置不同的背景色和邊框
2. 做一個(gè)能夠顯示毛玻璃效果的邊框
以下是邊框的代碼和部分MyJTextField的代碼,完整的代碼待我會(huì)打包傳上來(lái)的
MyJTextField.java
在初始化組件的時(shí)候加上Border的初始化:
hoverBorder = new CoolBorder(HOVER_BORDER_COLOR, 3);
border = BorderFactory.createCompoundBorder(new LineBorder(
BORDER_COLOR, 1), new EmptyBorder(new Insets(2, 2, 2, 2)));
setBackground(BACKGROUND_COLOR);
setBorder(border);
和事件的初始化:
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setBorder(hoverBorder);
setBackground(HOVER_BACKGROUND_COLOR);
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
setBorder(border);
setBackground(BACKGROUND_COLOR);
repaint();
}
});
以及屏蔽功能性按鈕和發(fā)出聲音提示的代碼:
addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
char input = e.getKeyChar();
// ESC27 ,Backspace 8 ,Enter 10, Del 127, must ignore
boolean ignoreInput = input == (char) KeyEvent.VK_ESCAPE
|| input == (char) KeyEvent.VK_BACK_SPACE
|| input == (char) KeyEvent.VK_ENTER
|| input == (char) KeyEvent.VK_DELETE;
if (ignoreInput) {
limitTip.setVisible(false);
numberTip.setVisible(false);
return;
}
if (getText().length() + 1 > limit) {
Toolkit.getDefaultToolkit().beep();
deleteInputChar(e);
limitTip.setVisible(true);
return;
} else {
limitTip.setVisible(false);
}
if (numberOnly) {
if (!Character.isDigit(input)) {
numberTip.setVisible(true);
Toolkit.getDefaultToolkit().beep();
deleteInputChar(e);
} else {
numberTip.setVisible(false);
}
}
}
private void deleteInputChar(KeyEvent source) {
source.setKeyChar((char) KeyEvent.VK_CLEAR);
}
});
下面是Border的完整代碼:
1 /**
2 * @(#)CoolBorder.java 0.1.2 2007-9-10
3 */
4 package ruislan;
5
6 import java.awt.Color;
7 import java.awt.Component;
8 import java.awt.Dimension;
9 import java.awt.GradientPaint;
10 import java.awt.Graphics;
11 import java.awt.Graphics2D;
12 import java.awt.Insets;
13
14 import javax.swing.border.Border;
15
16 /**
17 * Custom Border.
18 *
19 * @version 0.1.2, 2007-9-10
20 * @author ruislan <a href="mailto:z17520@126.com"/>
21 */
22 public class CoolBorder implements Border {
23 private int thickness;
24 private Insets insets;
25 private Dimension lastComponentSize;
26 private Color color;
27 private Color color2;
28
29 public CoolBorder(Color color, int thickness) {
30 this.color = color;
31 if (color == null) {
32 this.color = color = Color.gray;
33 }
34 color2 = new Color(210, 210, 210, 0);
35 this.thickness = thickness;
36 }
37
38 @Override
39 public Insets getBorderInsets(Component c) {
40 Dimension currentComponent = c.getSize();
41
42 if (currentComponent.equals(lastComponentSize)) {
43 return insets;
44 }
45
46 insets = new Insets(thickness, thickness, thickness, thickness);
47 lastComponentSize = currentComponent;
48 return insets;
49 }
50
51 @Override
52 public boolean isBorderOpaque() {
53 return true;
54 }
55
56 @Override
57 public void paintBorder(Component c, Graphics g, int x, int y, int width,
58 int height) {
59 Graphics2D g2d = (Graphics2D) g.create();
60 // 畫上邊緣
61 GradientPaint gp = new GradientPaint(x, y, color, x, y + thickness,
62 color2);
63 g2d.setPaint(gp);
64 g2d.fillRect(x, y, width, thickness);
65 // 畫下邊緣
66 gp = new GradientPaint(x, y + height - thickness - 1, color2, x, y
67 + height, color);
68 g2d.setPaint(gp);
69 g2d.fillRect(x, y + height - thickness - 1, width, thickness);
70 // 畫左邊緣
71 gp = new GradientPaint(x, y, color, x + thickness, y, color2);
72 g2d.setPaint(gp);
73 g2d.fillRect(x, y, thickness, height);
74 // 畫右邊緣
75 gp = new GradientPaint(x + width - thickness - 1, y, color2, x + width,
76 y, color);
77 g2d.setPaint(gp);
78 g2d.fillRect(x + width - thickness - 1, y, thickness, height);
79 // 畫外框
80 g2d.setPaint(color);
81 g2d.drawRect(x, y, width - 1, height - 1);
82 g2d.dispose();
83 }
84
85 }
86
然后來(lái)欣賞我們的結(jié)果吧:

鼠標(biāo)放上去之前

鼠標(biāo)放上去之后

我們輸入了不是數(shù)字的字符
至此,我們的JTextField又向前走了一步,下次我們還能如何改進(jìn)呢?把JTextField這個(gè)死板的長(zhǎng)方形改造成云狀的或者其他形狀的?
附源代碼下載地址:http://www.tkk7.com/Files/ruislan/myjtextfield.zip
posted @
2007-09-10 13:21 ruislan 閱讀(4348) |
評(píng)論 (3) |
編輯 收藏
摘要: 接著昨天的MyJTextField,我們繼續(xù)為JTextField增強(qiáng),今天我們?yōu)镸yJTextField增加一個(gè)泡泡提示。先看圖片:
當(dāng)輸入第三個(gè)字符'a'時(shí),由于昨天我們的MyJTextField做了處理,所以'a'不能被輸入,而且彈出泡泡提示你下次不要了喲!
同樣的,下一張圖片:
為MyJTextField增加泡泡提示功能要做以下幾件事情:
1. 泡泡窗口
2. 顯示的...
閱讀全文
posted @
2007-09-09 13:32 ruislan 閱讀(5179) |
評(píng)論 (2) |
編輯 收藏
在網(wǎng)上Google了一下,基本上的做法有兩種,第一種是JFormattedTextField;另外一種是自己繼承PlainDocument,
Override
insertString方法,然后用JTextFiled.setDocument的方法放入自己繼承的對(duì)象實(shí)例。但是最終我都沒有采用這兩種方法,首
先我對(duì)JFormattedTextField的方式不太舒服,然后感覺繼承PlainDocument有點(diǎn)太重,所以自己考慮了一種方案,也許有人跟我
的想法雷同,那就純屬巧合了。
下面放上代碼:
public class MyJTextField extends JTextField {
private int limit = Integer.MAX_VALUE;
private boolean numberOnly;
public MyJTextField() {
addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
if (getText().length() + 1 > limit) {
deleteInputChar(e);
return;
}
if (numberOnly) {
char input = e.getKeyChar();
if (!Character.isDigit(input)) {
deleteInputChar(e);
}
}
}
private void deleteInputChar(KeyEvent source) {
source.setKeyChar((char) KeyEvent.VK_CLEAR);
}
});
}
public void setMaxTextLength(int limit) {
if (limit < 0) {
return;
}
this.limit = limit;
}
public int getMaxTextLength() {
return limit;
}
public void setNumberOnly(boolean numberOnly) {
this.numberOnly = numberOnly;
}
public boolean isNumberOnly() {
return this.numberOnly;
}
}
整個(gè)思路很簡(jiǎn)單,就是檢查Type事件,如果超出了限制就刪除新增加的字符,如果設(shè)置了只是數(shù)字,那么不是數(shù)字的就刪除新增加的字符。使用的時(shí)候只需要
MyJTextField textField = new MyJTextField();
textField.setLimit(8);
textField.setNumberOnly(true);
結(jié)果就是最多輸入8個(gè)字符而且只能是數(shù)字。
posted @
2007-09-09 00:41 ruislan 閱讀(1285) |
評(píng)論 (2) |
編輯 收藏
其實(shí)認(rèn)識(shí)這里也有一段時(shí)間了,平常也常常上來(lái)看看,也用someone的給一些博主有些留言。但是因?yàn)樽约河辛薭logspot,所以始終沒有注冊(cè)。可惜的是blogspot被封太久了,我也懶得去改什么東西來(lái)破解,所以遺憾的放棄了blogspot,當(dāng)然這里也并非我退而其次的選擇。今天在這里注冊(cè)了就算正式與blogspot告別了。blogspot上的文章也不打算轉(zhuǎn)過(guò)來(lái)了。從頭開始寫吧。
posted @
2007-09-08 13:59 ruislan 閱讀(207) |
評(píng)論 (1) |
編輯 收藏