私は、JGoodies を使用して JTable 行をテーブルの下のテキスト フィールドにバインドする Java EE プロジェクトで顧客のために働いています。これは正常に機能しますが、1 つのダイアログにフィルタリング チェック ボックスがあります。すべてのチェック ボックス (3 つ) をクリックすると、すべての項目が表示されます。チェックされていない場合、テーブルは空のままです。一部の行をフィルターで除外することは可能ですが、テーブル モデルを使用する JGoodies はこのフィルター処理を認識していません。フィルタリングされたテーブルの最初の行をクリックすると、フィルタリングされていないテーブルの最初の行の要素が下のテキスト フィールドに表示されます。この問題を回避する方法はありますか?
私の意見では、問題は JGoodies の問題ではなく、フィルタリングされたテーブルのテーブル モデルを使用してテキスト フィールドを JGoodies にバインドすることです。
テキスト フィールドを Bindings.bind メソッドでバインドできなかった例を添付しましたが、問題が示されています。私は自分の目的のために、インターネット上で見つけたいくつかのコードを採用しました。
テーブルは、コンボ ボックスの内容に従ってフィルター処理されます。GENERAL タイプの食事が選択されている場合、下のテキスト フィールドのバインドは問題ありません。ただし、コンボ ボックスでテーブル コンテンツの一部を選択した場合でも、下のテキスト フィールドは (フィルター処理されていない) テーブル モデルから情報を取得します。ここで、適切な方法でこれを行う方法についての情報が必要です。
事前に助けてくれてありがとう!
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
* A simplified mouse listener that reacts when the mouse has been clicked or pressed.
*
* @since 2013-08-12
*/
public abstract class ASimpleMouseListener implements MouseListener {
/**
* Event method that is called when the mouse has been clicked or pressed.
*
* @param mouseEvent the mouse event
*/
public abstract void mouseClickedOrPressed(final MouseEvent mouseEvent);
/**
* {@inheritDoc}
*/
@Override
public void mouseClicked(final MouseEvent mouseEvent) {
mouseClickedOrPressed(mouseEvent);
}
/**
* {@inheritDoc}
*/
@Override
public void mousePressed(final MouseEvent mouseEvent) {
mouseClickedOrPressed(mouseEvent);
}
/**
* {@inheritDoc}
*/
@Override
public void mouseReleased(final MouseEvent mouseEvent) { }
/**
* {@inheritDoc}
*/
@Override
public void mouseEntered(final MouseEvent mouseEvent) { }
/**
* {@inheritDoc}
*/
@Override
public void mouseExited(final MouseEvent mouseEvent) { }
}
/**
* The enumeration for eating.
*
* @since 2014-04-21
*/
public enum EEating {
/** The constant for the general. */
GENERAL,
/** The constant for the lactovegetarian. */
LACTOVEGETARIAN,
/** The constant for the ovolactovegetarian. */
OVOLACTOVEGETARIAN,
/** The constant for the vegan. */
VEGAN,
/** The constant for the vegetarian. */
VEGETARIAN,
;
}
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.regex.Pattern;
import javax.swing.DefaultRowSorter;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import swing.table.filtering.EEating;
import swing.table.filtering.ImprovedTableModel;
import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.list.ArrayListModel;
import com.jgoodies.binding.list.SelectionInList;
import common.view.ASimpleMouseListener;
/**
* The table sort demo.
*/
public class ImprovedTableFilterBindingDemo extends JPanel {
/**
* The Class WidgetToolkit.
*/
public class WidgetToolkit {
/** The description. */
private String description;
/** The name. */
private String name;
/** The producer. */
private String producer;
/**
* Instantiates a new widget toolkit.
*
* @param name the name
* @param description the description
* @param producer the producer
*/
public WidgetToolkit(String name, String description, String producer) {
this.description = description;
this.name = name;
this.producer = producer;
}
/**
* Gets the description.
*
* @return the description
*/
public String getDescription() {
return description;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Gets the producer.
*
* @return the producer
*/
public String getProducer() {
return producer;
}
/**
* Sets the description.
*
* @param description the new description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Sets the name.
*
* @param name the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Sets the producer.
*
* @param producer the new producer
*/
public void setProducer(String producer) {
this.producer = producer;
}
}
/** The constant serialVersionUID. */
private static final long serialVersionUID = 2843557005187163601L;
/** The surname column index. */
private final byte SURNAME_COLUMN_INDEX = 1;
/** The food type combo box. */
private final JComboBox<EEating> foodTypeComboBox;
/** The surname text field. */
private final JFormattedTextField surnameTextField;
/** The table row sorter. */
private final RowSorter<? extends TableModel> tableRowSorter;
/** The JTable. */
private JTable jTable;
/** The table model. */
private final TableModel tableModel = new ImprovedTableModel();
/** The array list model. */
private final ArrayListModel<WidgetToolkit> arrayListModel;
/**
* Instantiates a new table sort demo.
*/
public ImprovedTableFilterBindingDemo() {
super(new GridLayout(3, 1));
getTable().setPreferredScrollableViewportSize(new Dimension(500, 70));
getTable().setFillsViewportHeight(true);
getTable().setAutoCreateRowSorter(true);
System.out.println("Test EEating first…");
final EEating[] eatings = EEating.values();
for (byte y = 0; y < eatings.length; y++) {
System.out.println("EEating: " + eatings[y].toString());
}
this.arrayListModel = new ArrayListModel<WidgetToolkit>();
this.arrayListModel.add(new WidgetToolkit("Swing", "Is a Java API", "Sun"));
this.arrayListModel.add(new WidgetToolkit("Flash", "Is NOT a Java API", "Macromedia"));
this.arrayListModel.add(new WidgetToolkit("SWT", "Is a Java API", "Eclipse"));
this.arrayListModel.add(new WidgetToolkit("QT", "Is NOT a Java API", "Trolltech"));
this.arrayListModel.add(new WidgetToolkit("AWT", "Is a Java API", "Sun"));
final SelectionInList<?> selectionInList =
new SelectionInList<ArrayListModel<WidgetToolkit>>(this.arrayListModel);
final JList<?> jList = new JList<Object>();
Bindings.bind(jList, selectionInList);
final ImprovedTableModel model = new ImprovedTableModel();
tableRowSorter = new TableRowSorter<ImprovedTableModel>(model);
// Create the scroll pane and add the table to it.
final JScrollPane scrollPane = new JScrollPane(getTable());
foodTypeComboBox = new JComboBox<EEating>();
foodTypeComboBox.addItem(EEating.GENERAL);
foodTypeComboBox.addItem(EEating.LACTOVEGETARIAN);
foodTypeComboBox.addItem(EEating.OVOLACTOVEGETARIAN);
foodTypeComboBox.addItem(EEating.VEGETARIAN);
// Add the scroll pane to this panel.
add(foodTypeComboBox);
add(scrollPane);
surnameTextField = new JFormattedTextField();
add(surnameTextField);
foodTypeComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent ae) {
newFilter();
}
});
getTable().addMouseListener(new ASimpleMouseListener() {
@Override
public void mouseClickedOrPressed(MouseEvent mouseEvent) {
surnameTextField.setText((String) getTable().getModel().getValueAt(
getTable().getSelectedRow(), SURNAME_COLUMN_INDEX));
}
});
}
/**
* New filter.
*/
@SuppressWarnings("unchecked")
protected void newFilter() {
getTable().setRowSorter(tableRowSorter);
final String BEGIN = "(?i).*?\\b(", END = ")\\b.*";
final StringBuilder regularExpression = new StringBuilder("(");
final EEating selection = (EEating) foodTypeComboBox.getSelectedItem();
switch (selection) {
case LACTOVEGETARIAN:
regularExpression.append(BEGIN + EEating.LACTOVEGETARIAN + END);
break;
case OVOLACTOVEGETARIAN:
regularExpression.append(BEGIN + EEating.OVOLACTOVEGETARIAN + END);
break;
case VEGAN:
regularExpression.append(BEGIN + EEating.VEGAN + END);
break;
case VEGETARIAN:
regularExpression.append(BEGIN + EEating.VEGETARIAN + END);
break;
default:
regularExpression.append(".*");
}
regularExpression.append(")");
System.out.println("newFilter(): RegEx = \"" + regularExpression.toString() + "\"");
final RowFilter<ImprovedTableModel, Object> rowFilter =
RowFilter.regexFilter(Pattern.compile(
regularExpression.toString(), Pattern.CASE_INSENSITIVE).toString()
, 4);
((DefaultRowSorter<ImprovedTableModel, Integer>) tableRowSorter).setRowFilter(rowFilter);
tableRowSorter.modelStructureChanged();
}
/**
* Gets the table.
*
* @return the table
*/
private JTable getTable() {
if (jTable == null) {
jTable = new JTable(tableModel );
}
return jTable;
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("TableSortDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
ImprovedTableFilterBindingDemo newContentPane = new ImprovedTableFilterBindingDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
/**
* The main method.
*
* @param arguments the arguments
*/
public static void main(final String[] arguments) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
}
import javax.swing.table.AbstractTableModel;
/**
* The improved table sort model
*
* @since 2014-04-21
*/
public class ImprovedTableModel extends AbstractTableModel {
/** Automatically generated serial version UID */
private static final long serialVersionUID = 8348216048683404697L;
/** The column names. */
private final String[] columnNames = { "First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian",
};
/** The data. */
private final Object[][] data = {
{ "Kathy", "Smith", "Snowboarding", 5.5, EEating.GENERAL },
{ "John", "Doe", "Rowing", 3.03, EEating.VEGETARIAN },
{ "Sue", "Black", "Knitting", 2.78, EEating.GENERAL },
{ "Jane", "White", "Speed reading", 20.7, EEating.LACTOVEGETARIAN },
{ "Jonathan", "Browny", "Pool", 10.01, EEating.OVOLACTOVEGETARIAN },
{ "Joe", "Brown", "Pool", 10.98, EEating.GENERAL },
};
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getColumnCount()
*/
@Override
public int getColumnCount() {
return columnNames.length;
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getRowCount()
*/
@Override
public int getRowCount() {
return data.length;
}
/* (non-Javadoc)
* @see javax.swing.table.AbstractTableModel#getColumnName(final int)
*/
@Override
public String getColumnName(final int columnIndex) {
return columnNames[columnIndex];
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getValueAt(final int, int)
*/
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
return data[rowIndex][columnIndex];
}
/*
* JTable uses this method to determine the default renderer/
* editor for each cell. If we didn't implement this method,
* then the last column would contain text ("true"/"false"),
* rather than a check box.
*/
/* (non-Javadoc)
* @see javax.swing.table.AbstractTableModel#getColumnClass(int)
*/
@Override
@SuppressWarnings("unchecked")
public Class getColumnClass(final int columnIndex) {
return getValueAt(0, columnIndex).getClass();
}
/*
* Don't need to implement this method unless your table's editable.
*/
/* (non-Javadoc)
* @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
*/
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
// Note that the data/cell address is constant,
// no matter where the cell appears on screen.
return (columnIndex < 2) ? false : true;
}
/*
* Don't need to implement this method unless your table's
* data can change.
*/
/* (non-Javadoc)
* @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object, int, int)
*/
@Override
public void setValueAt(final Object value, final int rowIndex, final int columnIndex) {
data[rowIndex][columnIndex] = value;
}
}