2017-03-05 7 views
0

ボタンとして機能するJLabelを作成しようとしています。押すと、次に押すキーがテキストになります。クラスの1つをJPanelに追加すると、正常に動作します。しかし、追加した場合、最初のものだけが追加されます。これはクラスです:Java KeyListenerは静的であるような変数を扱います

package foo; 

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class LabelButton extends JLabel implements MouseListener, KeyListener{ 
    String text = ""; 
    boolean editMode = false; 
    public LabelButton(){ 
     setHorizontalAlignment(SwingConstants.CENTER); 
     setVerticalTextPosition(JLabel.CENTER); 
     addMouseListener(this); 
     addKeyListener(this); 
     setFocusable(true); 
    } 
    public LabelButton(String text){ 
     setHorizontalAlignment(SwingConstants.CENTER); 
     setVerticalTextPosition(JLabel.CENTER); 
     addMouseListener(this); 
     addKeyListener(this); 
     setFocusable(true); 
     this.text = text; 
    } 
    public void paintComponent(Graphics g){ 
     if(!editMode){ 
      g.setColor(new Color(210,210,210)); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
      g.setColor(new Color(140,140,140)); 
      g.drawRect(0, 0, getWidth()-1, getHeight()-1); 
      FontMetrics metrics = g.getFontMetrics(g.getFont()); 
      Rectangle textrect = new Rectangle(1,1,getWidth()+2,getHeight()-1); 
      int textx = (textrect.width - metrics.stringWidth(text))/2; 
      int texty = ((textrect.height - metrics.getHeight())/2) + metrics.getAscent(); 
      g.setColor(new Color(40,40,40)); 
      g.drawString(text, textx, texty); 
     }else{ 
      g.setColor(new Color(160,160,160)); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
      g.setColor(new Color(210,210,210)); 
      g.drawRect(0, 0, getWidth()-1, getHeight()-1); 
      FontMetrics metrics = g.getFontMetrics(g.getFont()); 
      Rectangle textrect = new Rectangle(1,1,getWidth()+2,getHeight()-1); 
      int textx = (textrect.width - metrics.stringWidth("..."))/2; 
      int texty = ((textrect.height - metrics.getHeight())/2) + metrics.getAscent(); 
      g.setColor(new Color(40,40,40)); 
      g.drawString("...", textx, texty); 
     } 
    } 
    public void mouseClicked(MouseEvent e) { 
     if(e.getButton() == 1){ 
      editMode = !editMode; 
      System.out.println(text); 
      repaint(); 
     } 
    } 
    public void mousePressed(MouseEvent e) { 
    } 
    public void mouseReleased(MouseEvent e) {} 
    public void mouseEntered(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) { 
     editMode = false; 
     repaint(); 
    } 
    public void keyTyped(KeyEvent e) {} 
    public void keyPressed(KeyEvent e) { 
     System.out.println(text); 
     if(editMode){ 
      text = (String.valueOf(e.getKeyChar()).toUpperCase()); 
      System.out.println(String.valueOf(e.getKeyChar()).toUpperCase()); 
      editMode = false; 
      repaint(); 
     } 
    } 
    public void keyReleased(KeyEvent e) {} 
} 

私は何が間違っている、と私は助けが必要です。ありがとう!

+1

サイドノート:コードに重複が多くありますので、最小限に抑えることを目指してください。あなたのコンストラクタとペイントメソッドを見て、あなたは実際のロジックよりもずっと多くのコードを持っています。 – Dici

+1

あなたの期待される行動は何ですか?観察された行動は何ですか?これらについての完全な説明をしてください。 –

+0

編集を参照して回答してください。 –

答えて

3

KeyListenersは非常にです。コンポーネントフォーカスになると脆くなります。コンポーネントにフォーカスしている場合にのみ機能します。

最初のコンポーネントはフォーカスを取得していますが、そこには問題がありません。これは、他のフォーカスが "空いている"コンポーネントが機能しないことを意味します。 1つの解決策は、私が一般的に行うことであり、通常はKey Bindingsを好むKeyListenersを避けることです。

もう一つは、あなたのMouseListenerでフォーカスをつかむためにある:

public void mouseClicked(MouseEvent e) { 
    if (e.getButton() == 1) { 
     editMode = !editMode; 

     // **** added **** 
     if (editMode) { 
      requestFocusInWindow(); 
     }    
    } 
} 

サイドノート:前者が後者よりもマウスプレスをキャプチャしますと、私はmouseClickedオーバーmousePressedを使用して好むだろう。

例えば:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class TestLabelButton extends JPanel { 

    public TestLabelButton() { 
     setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
     setLayout(new GridLayout(1, 0, 10, 10)); 

     for (int i = 0; i < 4; i++) { 
      add(new LabelButton("Text " + (i + 1))); 
     } 
    } 

    private static void createAndShowGui() { 
     TestLabelButton mainPanel = new TestLabelButton(); 

     JFrame frame = new JFrame("TestLabelButton"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

@SuppressWarnings("serial") 
class LabelButton extends JLabel { 
    private static final int PREF_W = 160; 
    private static final int PREF_H = 40; 
    private static final Color NON_EDIT_BG = new Color(210, 210, 210); 
    private static final Color EDIT_BG = new Color(160, 160, 160); 
    private static final Color EDIT_RECT_COLOR = new Color(210, 210, 210); 
    private static final Color NON_EDIT_RECT_COLOR = new Color(140, 140, 140); 
    private static final Color TEXT_COLOR = new Color(40, 40, 40); 
    public static final String EDITING_TEXT = "..."; 
    private boolean editMode = false; 

    public LabelButton() { 
     this(""); 
    } 

    public LabelButton(String text) { 
     super(text); 
     setHorizontalAlignment(SwingConstants.CENTER); 
     setVerticalTextPosition(JLabel.CENTER); 
     addMouseListener(new MyMouse()); 
     addKeyListener(new MyKey()); 
     setFocusable(true); 
     setOpaque(true); 
     setBackground(NON_EDIT_BG); 
     setForeground(TEXT_COLOR); 
     setBorder(BorderFactory.createLineBorder(NON_EDIT_RECT_COLOR)); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     Dimension superSz = super.getPreferredSize(); 
     if (isPreferredSizeSet()) { 
      return superSz; 
     } 
     int prefW = Math.max(superSz.width, PREF_W); 
     int prefH = Math.max(superSz.height, PREF_H); 
     return new Dimension(prefW, prefH); 
    } 

    public void setEditMode(boolean editMode) { 
     this.editMode = editMode; 
     Color bg = editMode ? EDIT_BG : NON_EDIT_BG; 
     Color rectColor = editMode ? EDIT_RECT_COLOR : NON_EDIT_RECT_COLOR; 
     String drawText = editMode ? "..." : getText(); 

     setBackground(bg); 
     setBorder(BorderFactory.createLineBorder(rectColor)); 
     setText(drawText); 

     if (editMode) { 
      requestFocusInWindow(); 
     } 
    } 

    public boolean isEditMode() { 
     return editMode; 
    } 

    private class MyMouse extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent e) { 
      if (e.getButton() == 1) { 
       setEditMode(!isEditMode()); 
      } 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
      setEditMode(false); 
     } 
    } 

    private class MyKey extends KeyAdapter { 
     @Override 
     public void keyPressed(KeyEvent e) { 
      if (editMode) { 
       String text = (String.valueOf(e.getKeyChar()).toUpperCase()); 
       setText(text); 
       setEditMode(false); 
      } 
     } 
    } 
} 

注:あなただけのテキストを描画している場合paintComponentをオーバーライドする必要はありません!

+0

これはすばらしかった、ありがとう!また、ほとんどの時間mousePressedを使用していますが、このためには完全なマウスのプレスとリリースが必要でした。しかし、助言をありがとう。 –

関連する問題