usuario tutorial interfaz gui grafica español ejemplos componentes java swing event-handling reusability variable-names

interfaz - java swing tutorial pdf español



Java Swing, 100 TextFields tienen una tarea similar, así que quiero escribir la función para hacerlo (1)

Estoy trabajando en un proyecto pequeño (con el Generador de GUI Java de NetBeans) en el que tengo 100 TextFields que hace exactamente lo mismo en diferentes datos . Están dispuestos en 10 filas y 10 columnas , los nombres (Variable) son como:

txt11, txt12, ... txt110 txt21, txt22, ... txt210 . . ... . txt101, txt102, ... txt1010

por lo tanto, que los nombres pueden generarse fácilmente por el número de fila y columna, así como también puedo extraer fácilmente la fila y la columna de un campo de texto al que pertenece (pero no puedo).

Como realizan una tarea similar , puedo escribir un único método que toma los argumentos row y col como argumentos y se ejecuta cada vez que el usuario escribe algo en cualquiera de los TextField. Para cumplir con la tarea, debo averiguar la fila y la columna a la que pertenecen.

Traté de usar el siguiente código dentro del detector de eventos (he agregado el mismo detector de eventos para todo JTextField):

private void TextFieldAnswerTyped(java.awt.event.KeyEvent evt) { String name = ((JTextField)evt.getSource()).getName(); int row,col; if(name.endsWith("10")) { col=10; name=name.substring(0, name.length()-2); } else { col=Integer.parseInt(name.substring(name.length()-1,name.length())); name=name.substring(0, name.length()-1); } if(name.endsWith("10")) row=10; else row=Integer.parseInt(name.substring(name.length()-1,name.length())); checkForCell(row, col); //Performs the task }

Cada vez que ocurre el evento me da null como el name . ¿Estoy cometiendo un error aquí o hay alguna buena alternativa?


Tu problema es que estás confundiendo el nombre de la variable con el campo de nombre JTextField. Al llamar a getName() en JTextField, se devuelve el último, su campo de nombre, que como descubrirá está configurado de forma predeterminada como nulo. Varias soluciones se presentan:

  • Podrías tratar de usar la reflexión para obtener el objeto al que se refiere la variable que te interesa -una idea mala, quebradiza y complicada- simplemente no lo hagas.
  • De hecho, puede establecer que el campo de nombre sea el mismo que el nombre de la variable, al llamar a setName(...) en el JTextField después de crearlo, otro setName(...)
  • Sería mejor colocar todos sus objetos JTextField en una matriz o colección de 1 o 2 dimensiones. Al hacer esto, sería fácil descubrir en qué fila y columna se encuentra su campo.
  • Quizás la mejor solución (difícil de saber sin conocer más requisitos) sería usar una JTable, una con 10 filas y 10 columnas.

Su pregunta parece ser, de hecho, un problema XY en el que pregunta "¿cómo puedo arreglar este código?" Cuando la solución real es utilizar un enfoque diferente por completo. Cuéntenos más sobre su "espacio problemático": qué problema general está tratando de resolver, ya que una vez más creo que es probable que exista una mejor solución para usted.

Otro problema: parece que está intentando usar KeyListener con JTextFields, algo que tampoco recomiendo, ya que puede interferir con el procesamiento de claves nativas de los campos de texto. En cambio, casi siempre es mejor usar un DocumentListener o un DocumentFilter.

Otra opción es establecer el método del componente Swing, putClientProperty(...) , para que tus JTextFields "sepan" en qué fila y columna se encuentran. Un ejemplo de esto que usa el método anterior más su equivalente getter, y que usa un ActionListener en JTextField para obtener los datos es el siguiente:

import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; @SuppressWarnings("serial") public class ManyFields extends JPanel { private static final int ROWS = 10; private static final int COLS = ROWS; private static final int GAP = 2; private static final int TF_COLS = 5; public static final String ROW = "row"; public static final String COL = "col"; private JTextField[][] fieldGrid = new JTextField[ROWS][COLS]; public ManyFields() { setLayout(new GridLayout(ROWS, COLS, GAP, GAP)); setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); TFieldListener tFieldListener = new TFieldListener(); for (int row = 0; row < fieldGrid.length; row++) { for (int col = 0; col < fieldGrid[row].length; col++) { JTextField tField = new JTextField(TF_COLS); tField.putClientProperty(ROW, row); tField.putClientProperty(COL, col); tField.addActionListener(tFieldListener); add(tField); fieldGrid[row][col] = tField; } } } private class TFieldListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { JTextField field = (JTextField) e.getSource(); int row = (int) field.getClientProperty(ROW); int col = (int) field.getClientProperty(COL); // or another way to get row and column using the array: int row2 = -1; int col2 = -1; for (int r = 0; r < fieldGrid.length; r++) { for (int c = 0; c < fieldGrid[r].length; c++) { if (field == fieldGrid[r][c]) { row2 = r; col2 = c; } } } // now here row2 and col2 are set String text = field.getText(); String title = String.format("Text for Cell [%d, %d]", col, row); String message = "text: " + text; int messageType = JOptionPane.INFORMATION_MESSAGE; JOptionPane.showMessageDialog(ManyFields.this, message, title, messageType); field.transferFocus(); // move to next component } } private static void createAndShowGui() { ManyFields mainPanel = new ManyFields(); JFrame frame = new JFrame("Many Fields"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> createAndShowGui()); } }

Pero, de nuevo, es probable que una JTable ofrezca una mejor solución, sin embargo, es difícil saber exactamente cómo crear esto sin más información sobre los requisitos.