转自
一文online 昨天我们给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:[email protected]"/>
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 on 2007-09-10 13:21
ruislan 阅读(490)
评论(1)
编辑
收藏
<script type="text/javascript"> // </script>
FeedBack:
你好!!
我在网上看到你这个textField的例子真的好震撼哦....崇拜一把
不过还是有点小问题, 你给textField定位的时候,
private void determineAndSetLocation() {
Point location = attachedComponent.getLocation();
setBounds(location .x, location .y - getPreferredSize().height,
getPreferredSize().width, getPreferredSize().height);
}
但是目前您的这个XY只是textField相对于他父panel的XY,但是你要show在layeredPane.
如果这个textField在多层panel里面的话,这样计算就不对. 所以你的location应该是textfield相对于layeredPane的XY才对
所以这里我想改一下 但是我不知道如何得到textField相对于layeredPane的X和Y呢?
我只想到一个相当笨的方法, 不断getParent()后在把所以XY相加, 不知道还有其他方法吗?