我正在尝试制作一个充当按钮的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!