【问题标题】:JFormattedTextField is not properly clearedJFormattedTextField 未正确清除
【发布时间】:2011-05-08 02:15:21
【问题描述】:

我正在做这个作业,做一个解决数独的程序。我有一个带有 SudokuTextBox 网格的面板扩展了 JFormattedTextField。我有一个 MaskFormatter,因此每个文本框只接受一个整数。 然后在我的面板中,当一个键被释放时,我有这个代码。

 public void keyReleased(KeyEvent e) {
  SudokuTextBox tb = (SudokuTextBox) e.getSource();
  int row = tb.getRow();
  int col = tb.getCol();
  int value = toInteger(tb.getText());
  //System.out.println(value);
  if(sudoku.isValid(row, col, value)) {
   sudoku.set(row, col, value);
  }
  else {
   sudoku.set(row, col, 0);
   tb.setText(null);
  }
  tb.setCaretPosition(0);
  sudoku.print();
 }

问题是,如果我在文本框中输入了一个有效值,然后我返回并输入一个无效值(根据数独规则),文本框就会被清除。但是,当我向前选项卡时,前一个有效值会显示在文本框中。 我的 sudokumatrix 包含所有已输入的数字,确实清除了应有的值,因此它仅在相应的文本框中。

当我将“SudokuTextBox 扩展 JFormattedTextField”更改为“SudokuTextBox 扩展 JTextField”时,事情变得更加混乱,它就像一个魅力。但是我无法将 JTextField 的大小设置为正方形,并且我不能对每个文本框强制执行一个整数。

我是否遗漏了一些非常明显的东西?

【问题讨论】:

    标签: java jtextfield sudoku keyevent jformattedtextfield


    【解决方案1】:

    好的,现在我发现了,“掩码格式化程序的缺点之一是,从当前实现(Java 5)开始,它不支持让用户将字段恢复为空白值(初始值)任何用户输入之前的字段),一旦他们在任何时候离开该字段。”

    因此,由于我使用的是 MaskFormatter,因此我无法清除该字段。

    【讨论】:

      【解决方案2】:

      这是一个可能适用于此类游戏的可调整大小组件的示例。尽管它不包含游戏逻辑,但它可以很好地处理输入。单击鼠标或按空格键会弹出一个菜单,Tab 键和数字键按预期工作。特别是,Digit.EMPTY 是一个有效值。

      import java.awt.*;
      import java.awt.event.*;
      import java.awt.image.BufferedImage;
      import java.util.EnumSet;
      import javax.swing.*;
      
      /** @see http://stackoverflow.com/questions/4148336 */
      public class CellTest extends JPanel {
      
          public static void main(String[] args) {
              EventQueue.invokeLater(new Runnable() {
                  //@Override
                  public void run() {
                      createGUI();
                  }
              });
          }
      
          public static void createGUI() {
              JFrame frame = new JFrame();
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setLayout(new GridLayout(3, 3));
              for (Digit d : Digit.digits) {
                  frame.add(new CellTest(d));
              }
              frame.pack();
              frame.setVisible(true);
          }
      
          CellTest(Digit digit) {
              this.setLayout(new BorderLayout());
              this.setBorder(BorderFactory.createLineBorder(Color.black, 1));
              this.setBackground(new Color(0x00e0e0));
      
              JLabel candidates = new JLabel("123456789");
              candidates.setHorizontalAlignment(JLabel.CENTER);
              this.add(candidates, BorderLayout.NORTH);
      
              JDigit cellValue = new JDigit(digit);
              add(cellValue, BorderLayout.CENTER);
          }
      }
      
      class JDigit extends JButton {
      
          private static final int SIZE = 128;
          private static final int BASE = SIZE / 32;
          private static final Font FONT = new Font("Serif", Font.BOLD, SIZE);
          private JPopupMenu popup = new JPopupMenu();
          private Digit digit;
          private Image image;
          private int width, height;
      
          public JDigit(Digit digit) {
              this.digit = digit;
              this.image = getImage(digit);
              this.setPreferredSize(new Dimension(64, 64));
              this.setBackground(new Color(0xe0e000));
              this.setForeground(Color.black);
              this.setBorderPainted(false);
              this.setAction(new ButtonAction());
              this.addFocusListener(new FocusHandler());
              for (Digit d : Digit.values()) {
                  Action select = new SelectAction(d);
                  JMenuItem item = new JMenuItem(select);
                  getInputMap().put(KeyStroke.getKeyStroke(
                      KeyEvent.VK_0 + d.value(), 0), d.toString());
                  getInputMap().put(KeyStroke.getKeyStroke(
                      KeyEvent.VK_NUMPAD0 + d.value(), 0), d.toString());
                  getActionMap().put(d.toString(), select);
                  popup.add(item);
              }
          }
      
          public Digit getDigit() {
              return digit;
          }
      
          public void setDigit(Digit digit) {
              this.digit = digit;
              this.image = getImage(digit);
              this.repaint();
          }
      
          @Override
          protected void paintComponent(Graphics g) {
              int w = this.getWidth();
              int h = this.getHeight();
              g.setColor(this.getBackground());
              int dx1 = w * width / height / 4;
              int dx2 = w - dx1;
              g.fillRect(dx1, 0, dx2 - dx1, h);
              g.drawImage(image,
                  dx1, 0, dx2, h,
                  0, 0, width, height, null);
          }
      
          private Image getImage(Digit digit) {
              BufferedImage bi = new BufferedImage(
                  SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
              Graphics2D g2d = bi.createGraphics();
              g2d.setRenderingHint(
                  RenderingHints.KEY_ANTIALIASING,
                  RenderingHints.VALUE_ANTIALIAS_ON);
              g2d.setColor(this.getForeground());
              g2d.setFont(FONT);
              FontMetrics fm = g2d.getFontMetrics();
              width = fm.stringWidth(digit.toString());
              height = fm.getAscent();
              g2d.drawString(digit.toString(), 0, height - BASE);
              g2d.dispose();
              return bi;
          }
      
          private class ButtonAction extends AbstractAction {
              //@Override
              public void actionPerformed(ActionEvent e) {
                  popup.show(JDigit.this, getWidth() - width, getHeight() / 2);
              }
          }
      
          private class SelectAction extends AbstractAction {
      
              private Digit digit;
      
              public SelectAction(Digit digit) {
                  this.digit = digit;
                  this.putValue(Action.NAME, digit.toString());
              }
      
              //@Override
              public void actionPerformed(ActionEvent e) {
                  setDigit(digit);
              }
          }
      
          private class FocusHandler implements FocusListener {
      
              private Color background = getBackground();
      
              //@Override
              public void focusGained(FocusEvent e) {
                  setBackground(background.brighter());
              }
      
              //@Override
              public void focusLost(FocusEvent e) {
                  setBackground(background);
              }
          }
      }
      
      enum Digit {
      
          EMPTY(0, " "), ONE(1, "1"), TWO(2, "2"), THREE(3, "3"), FOUR(4, "4"),
          FIVE(5, "5"), SIX(6, "6"), SEVEN(7, "7"), EIGHT(8, "8"), NINE(9, "9");
          public static EnumSet<Digit> digits = EnumSet.range(Digit.ONE, Digit.NINE);
          private int i;
          private String s;
      
          Digit(int i, String s) {
              this.i = i;
              this.s = s;
          }
      
          @Override
          public String toString() {
              return s;
          }
      
          public int value() {
              return i;
          }
      }
      

      【讨论】:

      • 很抱歉没有接受您的回答。然而,我更感兴趣的是为什么我不能让 JFormattedTextField 做我想做的事情,而不是如何滚动我自己的组件。不过谢谢!
      • @refuser:没问题;我正在探索键绑定。
      【解决方案3】:

      虽然不是同一个问题,但我正在搜索(太多)这样的问题。就我而言,我希望能够通过直接查找索引或使用一些微调器并创建一个字符串然后查找该字符串来填充其他两个字段(jtfStarePatReq 和 jtfStarePatFound,它们是 JTextFields)(好吧,也许这也是含糊不清,但我认为这是足够的上下文)。我想要的是,如果用户删除或清除了 JFormattedTextField jftfStareOpsIndex 中的值,那么其他两个字段也将被清除。我在 JFormattedTextField 上使用 .isEmpty() 方法来决定是否应该使用该字段或使用更长的计算搜索方法。因此,如果有人从查找自己的索引到让软件搜索索引,我需要它为空。无论如何,我尝试捕获 commitEdit() 异常并将值设置为 null,这似乎可以解决问题。

      public class stareOpsIndexListener extends KeyAdapter implements FocusListener {
      
          public void focusGained(FocusEvent e) {
          }
      
          public void focusLost(FocusEvent e) {
              try {
                  JFormattedTextField jftf = (JFormattedTextField) e.getComponent();
                  jftf.commitEdit();
                  updateStareOpsIndex(jftf);
              } catch (ParseException ex) {
                      jtfStarePatReq.setText("");
                      jtfStarePatFound.setText("");
                      jftfStareOpsIndex.setValue(null);
              }
          }
      
          public void keyPressed(KeyEvent e) {
      
              int key = e.getKeyCode();
      
              if (key == KeyEvent.VK_ENTER) {
                  try {
                      JFormattedTextField jftf = (JFormattedTextField) e.getComponent();
                      jftf.commitEdit();
                      updateStareOpsIndex(jftf);
                  } catch (ParseException ex) {
                      jtfStarePatReq.setText("");
                      jtfStarePatFound.setText("");
                      jftfStareOpsIndex.setValue(null);
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-08-03
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 2015-10-30
        • 2022-09-30
        • 1970-01-01
        相关资源
        最近更新 更多