“千里冰封” 兄弟的截屏程序酷毙了,但是好像9月4日之后就没有继续更新了,我们来继续为他的程序改进,顺便也把我们这几天都在讲的2D绘制用进来,我们的目标是让冰封的截屏程序成为截屏程序里的王!
今天先改进一下截图时候的选框,还是先放上截图的截图(*o*):
这是原来的图片,下面是改进后的
和改进的代码部分:
这部分代码插入 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 阅读(1481) |
评论 (10) |
编辑 收藏
摘要: 嗯,BeanSoft的话很有道理,令我敬佩,也许是昨天在下对那个“更好的”三个字感到一时愤慨,所以看到UI就自己扩大了问题,想到迎合LookAndFeel上面去了,在此说句对不起了。你的回帖里面偏重于从整个组件的设计和重用性上,我的文章主要讲的是如何将2D绘制和组件的绘制结合起来,看客如果既了解了如何绘制自己想要的组件,又能设计得体,重用性高的话也算是对我抛砖引玉的欣慰了。...
阅读全文
posted @
2007-09-12 13:36 ruislan 阅读(2437) |
评论 (11) |
编辑 收藏
看来我们的JTextField之旅也到了一个阶段,已经很不错了,现在我们来改造JButton,让那个呆板的Swing看起来舒服一些。
还是先放上完成后的效果图:
普通的状态
鼠标滑过
鼠标按下
和代码:
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
注意代码中的几个部分:
首先是paintComponent方法中最后一行,我们调用了父类的paintComponent方法,这是因为我们要靠父类来绘制字符,但是父类的这个方法除了绘制字符之外还会绘制其他的,所以我们需要关闭掉其他的(当然我们也可以自己来绘制字符,但是JButton提供了方法为什么不用呢),所以我们在构造方法那里调用了:
setBorderPainted(false);
setFocusPainted(false);
setContentAreaFilled(false);
告诉父类不用绘制边框,不用绘制焦点,不用绘制内容部分,这部分我们自己来搞*o*。
然后就是这一句了g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)告诉绘制API我们需要平滑一点,否则绘制出来会有很多锯齿哟。
接下来的这一句g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,tran))告诉绘图API我们需要绘制一个有透明度的,tran就是透明度(0-1)。
然后就是将边框的边角变直角为圆角,我们绘制一个RoundRectangle2D,这个就是边角都为圆角的方形,然后我们根据这个方形来clip我们的方形,这样方形就被RoundRectangle2D的圆角方形包裹,从而变成了圆角方形。
最后就是绘制外边线和内边线,通过改变内边线和外边线的色变从而造成陷入或者突出效果。
整个JButton改造完毕,如果你能够活用clip的话,你也可以做一个五角星的JButton哟。
整个源代码我连同Eclipse工程文件已经打包成zip放在我的文件里面,下载链接如下:
http://www.blogjava.net/Files/ruislan/rswing-0.1.0.zip
posted @
2007-09-11 12:24 ruislan 阅读(5541) |
评论 (20) |
编辑 收藏
昨天我们给JTextField增加了一个泡泡提示窗口,今天我们继续昨天的,首先处理在显示泡泡的时候忽略输入的Backspace、Enter、Delete、Esc按键,然后加上错误的时候的声音提示,最后再给JTextField换装备,让它看起来像MSN 8.5beta的输入框,还是先放上图片:
这幅图是MSN的输入框,输入框的内部到光标有一部分是有点毛玻璃的感觉,不过这个style是死的,我们改进一下,我们的JTextField在输入之前是看似普通的,在鼠标放上去之后,看起来就与MSN的输入框类似了,而且我们还给这个输入框加入一个淡黄色的背景。
好了,现在很明确要做的事情了
1. 加入鼠标事件监听器,监听MouseEnter和MouseExit事件,根据这个两个事件设置不同的背景色和边框
2. 做一个能够显示毛玻璃效果的边框
以下是边框的代码和部分MyJTextField的代码,完整的代码待我会打包传上来的
MyJTextField.java
在初始化组件的时候加上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();
}
});
以及屏蔽功能性按钮和发出声音提示的代码:
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
然后来欣赏我们的结果吧:
鼠标放上去之前
鼠标放上去之后
我们输入了不是数字的字符
至此,我们的JTextField又向前走了一步,下次我们还能如何改进呢?把JTextField这个死板的长方形改造成云状的或者其他形状的?
附源代码下载地址:http://www.blogjava.net/Files/ruislan/myjtextfield.zip
posted @
2007-09-10 13:21 ruislan 阅读(4333) |
评论 (3) |
编辑 收藏
摘要: 接着昨天的MyJTextField,我们继续为JTextField增强,今天我们为MyJTextField增加一个泡泡提示。先看图片:
当输入第三个字符'a'时,由于昨天我们的MyJTextField做了处理,所以'a'不能被输入,而且弹出泡泡提示你下次不要了哟!
同样的,下一张图片:
为MyJTextField增加泡泡提示功能要做以下几件事情:
1. 泡泡窗口
2. 显示的...
阅读全文
posted @
2007-09-09 13:32 ruislan 阅读(5174) |
评论 (2) |
编辑 收藏
在网上Google了一下,基本上的做法有两种,第一种是JFormattedTextField;另外一种是自己继承PlainDocument,
Override
insertString方法,然后用JTextFiled.setDocument的方法放入自己继承的对象实例。但是最终我都没有采用这两种方法,首
先我对JFormattedTextField的方式不太舒服,然后感觉继承PlainDocument有点太重,所以自己考虑了一种方案,也许有人跟我
的想法雷同,那就纯属巧合了。
下面放上代码:
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;
}
}
整个思路很简单,就是检查Type事件,如果超出了限制就删除新增加的字符,如果设置了只是数字,那么不是数字的就删除新增加的字符。使用的时候只需要
MyJTextField textField = new MyJTextField();
textField.setLimit(8);
textField.setNumberOnly(true);
结果就是最多输入8个字符而且只能是数字。
posted @
2007-09-09 00:41 ruislan 阅读(1279) |
评论 (2) |
编辑 收藏
其实认识这里也有一段时间了,平常也常常上来看看,也用someone的给一些博主有些留言。但是因为自己有了blogspot,所以始终没有注册。可惜的是blogspot被封太久了,我也懒得去改什么东西来破解,所以遗憾的放弃了blogspot,当然这里也并非我退而其次的选择。今天在这里注册了就算正式与blogspot告别了。blogspot上的文章也不打算转过来了。从头开始写吧。
posted @
2007-09-08 13:59 ruislan 阅读(203) |
评论 (1) |
编辑 收藏