有关String的问题

clause3c7 2013-03-28 03:48:55
小弟在做練習题,遇到一个问题,解决了但不知原理,请大神指教:
我写了一个继承jpanel的class,里面包含一个String变量message,在constructor中加入了KeyListener,用来监听keyTyped与keyPressed事件;在完整的程序中,功能是用键盘打一串字符串,按回车后将字符串显示在调用了这个class实例的jframe的中间。代码就只放我写的jpanel的class了。
(请先阅读代码)
我一开始是直接用Class里的String变量来操作的,结果是按回车没有任何显示;正解是使用StringBuffer,功能正常。可是为何不能那么做呢?求点拨!(我把StringBuffer相关的语句改注释了,所以下面的代码就是我不明白为什么不行的代码)

问题出在 message += e.getKeyChar() 上?


class StringPanel extends JPanel {

private String message = "";
//private StringBuffer buffer = new StringBuffer();

public StringPanel() {
addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
//buffer.append(e.getKeyChar());
message += e.getKeyChar();
}

@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
//message = buffer.toString().trim();
repaint();
message = ""; // In the correct version, this line is deleted
//buffer.setLength(0);
}
}
});
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

FontMetrics fm = g.getFontMetrics();
int stringAscent = fm.getAscent();
int stringWidth = fm.stringWidth(message);
int x = getWidth() / 2 - stringWidth / 2;
int y = getHeight() / 2 - stringAscent / 2;
g.drawString(message, x, y);
}
}
...全文
126 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
clause3c7 2013-03-28
  • 打赏
  • 举报
回复
Thanks! 解答的很足够了!
raistlic 2013-03-28
  • 打赏
  • 举报
回复
要想知道原理, google搜索: Java Swing EDT, Swing 绘制原理, Swing 线程 …… 或者阅读: 《Filthy Rich Clients》
raistlic 2013-03-28
  • 打赏
  • 举报
回复
问题出在你那句 message = ""; 上,而不在于你到底用 String 还是用 StringBuffer 。 也许不是特别直观,不过事实是这样: message = ""; 的运行, 在重绘之前。 换句话说,当你的控件重绘的时候, message 的值是 "" 。 要想只用 String,那么试试这样:

class StringPanel extends JPanel {
     
    private String message = "";
    //private StringBuffer buffer = new StringBuffer();
     
    public StringPanel() {
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                //buffer.append(e.getKeyChar());
                message += e.getKeyChar();
            }
             
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    //message = buffer.toString().trim();
                    repaint();

                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            
                            message = "";
                        }
                    });
                    //message = ""; // In the correct version, this line is deleted
                    //buffer.setLength(0);
                }
            }
        });
    }
     
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
         
        FontMetrics fm = g.getFontMetrics();
        int stringAscent = fm.getAscent();
        int stringWidth = fm.stringWidth(message);
        int x = getWidth() / 2 - stringWidth / 2;
        int y = getHeight() / 2 - stringAscent / 2;
        g.drawString(message, x, y);
    }
}
另外从代码效率来考虑的话, String 也好 StringBuffer 也好都是不推荐的, —— 应该用 StringBuilder。 代码简单更正如下:

class StringPanel extends JPanel {
    
    private String message = "";
    private StringBuilder buffer = new StringBuilder();
     
    public StringPanel() {

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {

                buffer.append(e.getKeyChar());
            }
             
            @Override
            public void keyPressed(KeyEvent e) {

                if (e.getKeyCode() == KeyEvent.VK_ENTER) {

                    message = buffer.toString().trim();
                    buffer.delete(0, buffer.length());
                    repaint();
                }
            }
        });
    }
     
    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
         
        FontMetrics fm = g.getFontMetrics();
        int stringAscent = fm.getAscent();
        int stringWidth = fm.stringWidth(message);
        int x = getWidth() / 2 - stringWidth / 2;
        int y = getHeight() / 2 - stringAscent / 2;
        g.drawString(message, x, y);
    }
}
(上面两个示例代码都没有测试,也许有错误)
Ganymede 2013-03-28
  • 打赏
  • 举报
回复
String 雖然也可以追加,但是追加后會生成新的String對象,所以追加操作要用StringBuffer

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧