我正在尝试制作一个充当按钮的JLabel,当您按下它时,您按下的下一个键将成为文本。当我将一个类添加到JPanel时,它可以正常工作。但是,如果我添加更多,则仅添加的第一个起作用。这是课程:

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) {}
}


我不知道怎么了,我需要帮助。谢谢!

最佳答案

当涉及组件焦点时,KeyListeners非常脆弱-仅当侦听组件获得焦点时,KeyListener才起作用。

您的第一个组件正在抓住焦点而不放开它,这就是问题所在,因为这意味着其他焦点“饥饿”的组件将无法工作。一种解决方案是避免KeyListeners,这是我通常要做的事情,通常是赞成使用Key Bindings。

另一个方法是将注意力集中在鼠标监听器上:

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

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


旁注:我更喜欢使用mousePressed而不是mouseClicked,因为前者会比后者捕获更多的鼠标按下。

例如:

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!

07-24 09:27