Frage

ich diese Aufgabe machte, macht ein Programm, das löst Sudoku. Ich habe ein Panel mit einem Raster von SudokuTextBox JFormattedTextField erstreckt. Ich habe einen MaskFormatter, so dass es nur eine ganze Zahl pro Textfeld akzeptiert. Da ist in meinem Panel habe ich diesen Code, wenn ein Schlüssel relesed wird.

 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();
 }

Die Sache ist, wenn ich einen gültigen Wert in einem Textfeld setzen, dann gehe ich zurück und geben Sie einen ungültigen Wert (nach den Regeln von Sudoku) das Textfeld gelöscht wird. Aber dann, wenn ich Registerkarte vorwärts der vorherige gültige Wert in dem Textfeld angezeigt. Mein sudokumatrix dass alle Zahlen enthält, die den Wert löschen inputed wurden, wie es sollte, so ist es nur in dem entsprechenden Textfeld ein.

Um die Sache zu machen noch mehr verwirrend, wenn ich ändern „SudokuTextBox erstreckt JFormattedTextField“ auf „SudokuTextBox JTextField erstreckt“ es funktioniert wie ein Charme. Aber ich kann nicht die Größe von JTextField so eingestellt, dass es Platz ist, und ich kann nicht nur eine ganze Zahl pro Textfeld erzwingen.

Bin ich etwas wirklich offensichtlich fehlt?

War es hilfreich?

Lösung 2

Ok, so jetzt finde ich es, „Einer der Nachteile des Maskenformatierer ist, dass ab der aktuellen Implementierung (Java 5), ??hat es keine Unterstützung für einen Benutzer revert ein Feld auf den Blindwert zu lassen (den Anfangswert des Feldes vor jeder Benutzereingabe), sobald sie das Feld an einer beliebigen Stelle verlassen haben. "

So, da ich ein MaskFormatter Ich verwende kann das Feld nicht löschen.

Andere Tipps

Hier ist ein Beispiel für eine veränderbare Komponente, die für ein solches Spiel geeignet sein könnten. Obwohl es keine Spiellogik enthält, behandelt es einigermaßen gut Eingabe. Ein Klick auf die Maus oder die Leertaste drücken Pop ist ein Menü auf, und die Registerkarte und die Zifferntasten funktionieren wie erwartet. Insbesondere ist Digit.EMPTY ein gültiger Wert.

alt text

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;
    }
}

Obwohl es nicht die gleiche Frage, ich war wie diese durch die (zu viele) Fragen zu suchen. In meinem Fall wollte ich in der Lage sein zu füllen zwei weitere Felder (jtfStarePatReq und jtfStarePatFound die JTextFields sind) entweder durch einen Index direkt aufzublicken oder durch ein paar Spinner mit und eine Zeichenfolge erstellen und dann diese Zeichenfolge aufzuzublicken (okay, vielleicht auch das ist vage, aber ich denke, es ist genug Kontext ist). Was ich wollte, ist, dass, wenn der Benutzer gelöscht oder gelöscht, um den Wert in der JFormattedTextField jftfStareOpsIndex, dann die anderen beiden Felder als auch gelöscht werden würde. Ich war mit dem .isEmpty () -Methode auf dem JFormattedTextField zu entscheiden, ob ich dieses Feld verwenden sollte oder verwenden Sie die länger berechnete Suchmethode. Also ich brauche es leer zu sein, wenn jemand aus aufzublicken ihren eigenen Index gilt für den Index, den die Software-Suche zu lassen. Wie auch immer, ich versuchte, die commitEdit () Ausnahme abfangen und den Wert auf Null setzen und es scheint, den Trick zu tun.

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);
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top