随笔 - 18  文章 - 96  trackbacks - 0
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567


常用链接

留言簿(4)

随笔档案

相册

我的兄弟们

搜索

  •  

最新评论

阅读排行榜

评论排行榜

“千里冰封” 兄弟的截屏程序酷毙了,但是好像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(205255205);
 29     public static final Color BUTTON_COLOR2 = new Color(5115447);
 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(00new Color(000), 0, h - 1,
 74                     new Color(100100100));
 75             p2 = new GradientPaint(01new Color(00050), 0, h - 3,
 76                     new Color(255255255100));
 77         } else {
 78             p1 = new GradientPaint(00new Color(100100100), 0, h - 1,
 79                     new Color(000));
 80             p2 = new GradientPaint(01new Color(255255255100), 0,
 81                     h - 3new Color(00050));
 82         }
 83         g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
 84                 tran));
 85         RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(00, w - 1,
 86                 h - 12020);
 87         Shape clip = g2d.getClip();
 88         g2d.clip(r2d);
 89         GradientPaint gp = new GradientPaint(0.0F0.0F, BUTTON_COLOR1, 0.0F,
 90                 h, BUTTON_COLOR2, true);
 91         g2d.setPaint(gp);
 92         g2d.fillRect(00, w, h);
 93         g2d.setClip(clip);
 94         g2d.setPaint(p1);
 95         g2d.drawRoundRect(00, w - 1, h - 12020);
 96         g2d.setPaint(p2);
 97         g2d.drawRoundRect(11, w - 3, h - 31818);
 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(2222)));

        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(2102102100);
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)编辑 收藏
仅列出标题
共2页: 上一页 1 2