2015-05-12 2 views
2

Я довольно новичок в Swing и пытаюсь написать лист свойств с помощью JTable, но вижу странное поведение. Я отложил NetBeans и закодировал эту маленькую жемчужину, чтобы понять, работают ли основы. В случае, если вам интересно, мой настоящий подклассы приложений JTextField и размещает диалоговые окна, чтобы помочь пользователю указать некоторые из значений; ImportField - один из этих классов.JTable не вызывает getValueAt

Эта программа отображает JTable, но имеет только заголовки столбцов. JTable никогда не вызывает getValueAt, поэтому данные не отображаются.

Может ли кто-нибудь помочь мне понять это поведение?

import java.awt.*; 
import java.awt.event.*; 
import java.util.StringTokenizer; 
import javax.swing.*; 
import javax.swing.table.*; 
import javax.swing.event.TableModelEvent; 

public class Y extends JFrame { 

    public Y() { 
     super("Y"); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     final Model model = new Model(); 
     JTable table = new JTable(); 
     table.setModel(model); 
     JScrollPane scrollpane = new JScrollPane(table); 

     JButton button = new JButton("Click Me"); 
     button.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent evt) { 
       model.setValueAt(model.getValueAt(0, 1), 0, 1); 
      } 
     }); 

     JPanel panel = new JPanel(new BorderLayout()); 
     panel.add(scrollpane, BorderLayout.CENTER); 
     panel.add(button, BorderLayout.SOUTH); 

     setContentPane(panel); 
     pack(); 
    } 

    public static void main (String[] args) throws Exception { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Y().setVisible(true); 
      } 
     }); 
    } 
} 


class ImportField extends JTextField implements FocusListener { 

    public ImportField() { 
     super(); 
     this.setInputVerifier(new ImportVerifier()); 
     this.addFocusListener(this); 
     this.setBorder(null); 
    } 

    @Override 
    public void focusGained(FocusEvent e) { 

     // We only want to do this ONCE 
     this.removeFocusListener(this); 

     System.out.println("Text field gained focus."); 
    } 

    @Override 
    public void focusLost(FocusEvent e) { 
     // IGNORE 
    } 

    class ImportVerifier extends InputVerifier { 

     @Override 
     public boolean verify(JComponent input) { 
      boolean valid = true; 
      JTextField fld = (JTextField) input; 
      if (fld.getText().length() > 0) { 
       StringTokenizer tok = new StringTokenizer(fld.getText(), ", "); 
       while (tok.hasMoreTokens()) { 
        String token = tok.nextToken().toLowerCase(); 
        if (! token.equals("insert") && ! token.equals("update") && 
         ! token.equals("ignore") && ! token.equals("abort") && 
         ! token.equals("none") && ! token.equals("all")) { 

         valid = false; 
        } 
       } 
      } 
      return valid; 
     } 
    } 
} 


class Model extends DefaultTableModel { 

    private String[] colNames = { "Key", "Value" }; 

    private Object[][] data = { { "item 1", "something" }, 
           { "item 2", "something else" }, 
           { "item 3", "other thing" } }; 

    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     System.out.format("%-15s %s\n", "getColumnClass", "String"); 
     return String.class; 
    } 

    @Override 
    public int getColumnCount() { 
     System.out.format("%-15s %d\n", "getColumnCount", colNames.length); 
     return colNames.length; 
    } 

    @Override 
    public String getColumnName(int columnIndex) { 
     System.out.format("%-15s %s\n", "getColumnName", colNames[columnIndex]); 
     return colNames[columnIndex]; 
    } 

    public int geRowlumnCount() { 
     System.out.format("%-15s %d\n", "getRowName", data.length); 
     return data.length; 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) { 
     System.out.format("%-15s %s\n", "getValueAt", data[rowIndex][columnIndex]); 
     return data[rowIndex][columnIndex]; 
    } 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) { 
     System.out.format("%-15s %s\n", "isCellEditable", rowIndex == 1); 
     return rowIndex == 1; 
    } 

    @Override 
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
     System.out.format("%-15s %s\n", "setValueAt", aValue); 
     data[rowIndex][columnIndex] = aValue; 
     fireTableChanged(new TableModelEvent(this)); 
    } 
} 

Ваша помощь будет очень признательна.

ответ

1

Попробуйте это, после того, как вы установите модель, звоните:

((DefaultTableModel)table.getModel()).fireTableDataChanged(); 
+0

Спасибо за предложение, @ user489041, но это не сработает. Это принципиально то, что я делал в своем ActionListener, за исключением того, что я вызывал setValueAt на модели, чтобы вызвать событие fireTableDataChanged. –

0

я узнал, что вам нужно вызвать table.validate(); (после установки TableModel, конечно)

0

Проблема возникает из того факта, что вы продлен DefaultTableModel и вы не реализовали метод:

public int getRowCount() 

Вот шаги, с момента инициализации модели с

final Model model = new Model(); 
  1. Суперкласс (DefaultTableModel) вызывается конструктор (но это лежащая в основе данных пуста).
  2. частных поля оборудования модели инициализируются (COLNAMES и данные)
  3. Остальная часть конструктора модели выполняются

[Для приятного объяснения этих шагов прочитать этот хороший пост Are fields initialized before constructor code is run in Java?]

Теперь, как вы не переопределили getRowCount(), класс Model будет использовать реализацию из суперкласса DefaultTableModel, который будет возвращать 0 все время, чтобы таблица всегда «думала», что ничего не видно.

Смежные вопросы