Frage

Ich habe viele benutzerdefinierte Editoren für eine JTable und es ist eine Untertreibung zu sagen, dass die Benutzerfreundlichkeit, insbesondere im Hinblick auf die Bearbeitung mit der Tastatur, fehlt.

Der Hauptgrund dafür ist, dass meine Redakteure sind immer mit einer ähnlichen erstellt (wenn auch oft komplexen) Situation folgendermaßen aus:

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
  JPanel container = new JPanel();
  container.setLayout(new BorderLayout());
  container.add(field, BorderLayout.CENTER);
  field.setText((String) value);
  container.add(new JButton("..."), BorderLayout.EAST);
  return container;
}

I.E ein Panel mit mehr als einer Komponente im Innern. Der eigentliche Text-Editor ist ein Nachkomme der Komponente als Editor zurückgegeben werden. Also, Rendering Fragen beiseite, von dem, was ich sagen kann, die JTable die Komponente konzentriert, die so durch die getTableCellEditorComponent Methode zurückgegeben wird, wenn Sie eine Taste mit einer Zelle drücken markiert es passiert Fokus und drücken Sie die Taste auf dem Bedienfeld, das Denken, das ist der Herausgeber .
Gibt es trotzdem kann ich JTable informieren, dass die „echten“ Editor ist das JTextField? Hinzufügen eines Hacky requestFocusInWindow auf der richtigen Komponente ist unzureichend, da der Tastendruck nicht weitergegeben bekommen.

War es hilfreich?

Lösung

Überprüfen

einige verwandte Artikel hier und hier .

Ein weiterer guter Artikel über JTable Bearbeitung im Allgemeinen .

Andere Tipps

Wenn ich Ihre Frage richtig lesen, möchten Sie die Benutzer in der Lage sein, in eine Zelle sofort zu geben, ohne zuerst die Zellen-Editor zu aktivieren, das heißt, wollen Sie, was Tastendruck die Zelle aktiviert das erste Zeichen in das Textfeld eingegeben werden .

Mein erster Versuch war ein Property auf der focusOwner Eigenschaft des KeyboardFocusManager hinzuzufügen, nur zu bemerken, dass der Fokus nie die JTable verlässt. Sie lief wahrscheinlich, dass in so gut. Zeit für Plan B.

Ich habe die „erste keypress“ Ding durch Zugabe eines KeyListener an den Tisch zu arbeiten, die die letzte KeyEvent für die keyPressed () -Methode in einem Instanzfeld aufzeichnet. Die getTableCellEditorComponent () Methode liest den Charakter von dort. Ich brauchte auch, dass Hacky requestFocusInWindow () rufen Sie an, ob der Benutzer alle Zeichen zu halten, ist die Eingabe nach dem ersten.

Für meine Beispielanwendung, habe ich eine Unterklasse von JTable, die eine KeyListener sich fügt. Es ist eine viel bessere Idee, um Ihre CellEditor Instanz implementieren KeyListener zu machen und dass statt dem regulären JTable hinzufügen, aber das werde ich Ihnen überlassen.

Hier ist Ihr Code-Schnipsel, wie ich es geändert:

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    JPanel container = new JPanel();
    container.setLayout(new BorderLayout());
    container.add(field, BorderLayout.CENTER);

    // Will want to add an instanceof check as well as a check on Character.isLetterOrDigit(char).
    char keypressed = ((StickyKeypressTable)table).getLastKeyPressed();
    field.setText(String.valueOf(keypressed));

    container.add(new JButton("..."), BorderLayout.EAST);

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // This needs to be in an invokeLater() to work properly
            field.requestFocusInWindow();
        }
    });
    return container;
}

Was Bösartigkeit geht das sitzt irgendwo dort oben mit Vogon Poesie, aber es sollte Ihr unmittelbares Problem lösen.

Ich reparierte etwas ähnliches in 2 Schritten

Sie zuerst die editCellAt von Ihrem JTable außer Kraft setzen und rufen nach request den Editor vorbereiten:

public boolean editCellAt( int row, int column, EventObject e )
{
  if ( cellEditor != null && !cellEditor.stopCellEditing() )
    {
    return false;
    }

  if ( row < 0 || row >= getRowCount() ||
      column < 0 || column >= getColumnCount() )
    {
    return false;
    }

  if ( !isCellEditable(row, column) )
    return false;

  TableCellEditor editor=getCellEditor(row, column);
  if ( editor != null && editor.isCellEditable(e) )
    {
    editorComp=prepareEditor(editor, row, column);
    if ( editorComp == null )
      {
      removeEditor();
      return false;
      }
    //aangepast
    Rectangle rect=getCellRect(row, column, false);
    if ( datamodel_.useAdaptedEditorRect() )
      rect=datamodel_.changeRectangle(rect, editorComp);
    editorComp.setBounds(rect);
    add(editorComp);
    editorComp.validate();

    setCellEditor(editor);
    setEditingRow(row);
    setEditingColumn(column);
    editor.addCellEditorListener(this);
    //NEXT LINE ADDED 
    editorComp.requestFocus();
    return true;
    }
  return false;
}

Überlastung dann die request von Ihrem JPanel und stellen Sie sicher, dass Ihr Textfeld als editorComponent gesetzt wird:

public class EditorPanel extends JPanel {
   JComponent editorComponent;

   public boolean isRequestFocusEnabled()
   {
     return true;
   }

   public void requestFocus()
   {
   editorComponent.requestFocus();
   }
}

Sie können jederzeit das keyEvent greifen und setzen Sie es selbst:

AWTEvent event = EventQueue.getCurrentEvent();
if ( event instanceof KeyEvent )
  {
  char newSelection = ( (KeyEvent) event).getKeyChar();
  int keyCode = ( (KeyEvent) event ).getKeyCode();
  editorComponent.requestFocus();
  if ( editorComponent instanceof JTextField )
    {
    if ( ( newSelection >= (char) FIRST_ALLOWED_CHAR ) && ( newSelection != (char) LAST_ALLOWED_CHAR ) ) //comes from DefaultKeyTypedAction
       ( (JTextField) editorComponent ).setText(Character.toString(newSelection));
    if ( keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_DELETE )
      ( (JTextField) editorComponent ).setText("");          
    }
  }
else
  editorComponent.requestFocus();

Ich denke, dass ich es gelöst.
Um Ihnen die Wahrheit zu sagen, ich weiß nicht, was das Problem gelöst, da ich einen benutzerdefinierten Editor, einen benutzerdefinierten Renderer und so ...

Wenn eine Zelle markiert ist, und ich drücke „abc“, gehen die drei Buchstaben auf dem Bildschirm (Zelle, in diesem Fall).

grid.addKeyListener(new KeyAdapter() {
    public void keyTyped(KeyEvent ke) {
        int l = grid.getSelectedRow();
        int c = grid.getSelectedColumn();
        grid.editCellAt(l, c);
    }
});

Nun ... Ich habe versucht, ... =)
(Ich weiß nicht, ob es das gleiche ist, weil mein JTable JTextField und JComboBox als Editoren verwendet).

Ich hatte sehr ähnliches Problem. In meinem Fall hatte ich komplexe TableCellEditor, die von JSpinner und einigen anderen Komponenten besteht. Das Problem war, dass, wenn Zellen-Editor begann ich den Fokus auf seine interne Komponente übertragen wollte. Ich reparierte diese durch panel.transferFocusDownCycle() Aufruf aber dies wiederum verursacht Tastaturereignisse funktionieren - wenn meine interne Komponente den Fokus hatte und ich gedrückte Taste, ich hatte erwartet, dass die Komponente dieses Ereignis abfangen und seinen Wert ändern. Stattdessen verändert Tabellenzeile den Fokus auf eine über ... ich diese KeyListener durch Zugabe von festen und alle wichtigen Ereignisse direkt an die interne Komponente Dispatching.

Dies ist Wrapper-Klasse basiert auf JPanel schrieb ich mein Leben einfacher zu machen.

public class ContainerPanel extends JPanel implements KeyListener, FocusListener {

    private JComponent component = null;

    public ContainerPanel(JComponent component) {
        this.component = component;
        addKeyListener(this);
        addFocusListener(this);
        setFocusCycleRoot(true);
        setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy());
        add(component);
    }

    @Override
    public void keyTyped(KeyEvent e) {
        component.dispatchEvent(e);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        component.dispatchEvent(e);
    }

    @Override
    public void keyReleased(KeyEvent e) {
        component.dispatchEvent(e);
    }

    @Override
    public void focusGained(FocusEvent e) {
        component.transferFocusDownCycle();
    }

    @Override
    public void focusLost(FocusEvent e) {
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top