Как реализовать динамический графический интерфейс в swing
-
28-10-2019 - |
Вопрос
Прежде всего, приношу извинения за публикацию чего-то, возможно, немного чрезмерно специфичного, но я не очень разбираюсь в Swing и, похоже, не могу найти хороших примеров, соответствующих моим потребностям.
Итак, я пытаюсь найти наилучший способ реализации динамического графического интерфейса для выбора критериев фильтрации в Swing:
Базовая модель - это класс, содержащий список критериев, которые могут быть отвергнуты (т. е.применяется с префиксом NOT), и свойство, указывающее, следует ли их комбинировать с AND или OR.
Графический интерфейс позволил бы пользователю добавлять, изменять или удалять критерии и выбирать оператор комбинирования (и / или).Первый критерий, естественно, не имел бы комбинационного селектора, а третий и последующие критерии просто использовали бы тот же комбинационный оператор, что и второй.
Кнопки X справа будут использоваться для удаления критерия.При нажатии кнопки Добавить в нижней части будет добавлена новая строка компонентов.По мере внесения изменений они будут отражаться в базовой модели.
Конечно, я мог бы реализовать это довольно "примитивно", просто добавив компоненты в JPanel и затем соответствующим образом обновив модель, но я бы предпочел более аккуратное решение, например, предоставляемое TableModel.
Поэтому мне интересно, будет ли таблица с пользовательской TableModel и TableCellRenderer / Editor лучшим подходом, или есть лучший способ реализовать что-то подобное.Если table действительно является лучшим подходом, я был бы признателен за несколько указаний на то, как можно было бы использовать TableCellRenderers или -Editors для достижения этой цели.
Заранее благодарю.
Решение
единственный пример, все жестко запрограммировано, для хорошего понимания
Редактировать:
как заметила клеопатра, переместила JTable#fireTableDataChanged() из ActionListener в TableModel, изменила все имена классов, начинающиеся со строчной
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.table.*;
public class ComponentTableTest {
private JFrame frame;
private JTable CompTable = null;
private CompTableModel CompModel = null;
private JButton addButton = null;
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ComponentTableTest().makeUI();
}
});
}
public void makeUI() {
CompTable = CreateCompTable();
JScrollPane CompTableScrollpane = new JScrollPane(CompTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JPanel bottomPanel = CreateBottomPanel();
frame = new JFrame("Comp Table Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(CompTableScrollpane, BorderLayout.CENTER);
frame.add(bottomPanel, BorderLayout.SOUTH);
frame.setPreferredSize(new Dimension(800, 400));
frame.setLocation(150, 150);
frame.pack();
frame.setVisible(true);
}
public JTable CreateCompTable() {
CompModel = new CompTableModel();
CompModel.addRow();
JTable table = new JTable(CompModel);
table.setRowHeight(new CompCellPanel().getPreferredSize().height);
table.setTableHeader(null);
CompCellEditorRenderer compCellEditorRenderer = new CompCellEditorRenderer();
table.setDefaultRenderer(Object.class, compCellEditorRenderer);
table.setDefaultEditor(Object.class, compCellEditorRenderer);
return table;
}
public JPanel CreateBottomPanel() {
addButton = new JButton("Add Comp");
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (source == addButton) {
CompModel.addRow();
//CompModel.fireTableDataChanged(); // moved to TableModel
}
}
});
JPanel panel = new JPanel(new GridBagLayout());
panel.add(addButton);
return panel;
}
}
class CompCellEditorRenderer extends AbstractCellEditor implements TableCellRenderer, TableCellEditor {
private static final long serialVersionUID = 1L;
private CompCellPanel renderer = new CompCellPanel();
private CompCellPanel editor = new CompCellPanel();
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
renderer.setComp((Comp) value);
return renderer;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
editor.setComp((Comp) value);
return editor;
}
@Override
public Object getCellEditorValue() {
return editor.getComp();
}
@Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
}
class CompTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
@Override
public int getColumnCount() {
return 1;
}
public void addRow() {
super.addRow(new Object[]{new Comp(0, 0, "", "")});
//super.fireTableDataChanged();
}
}
class Comp {
int type;
int relation;
String lower;
String upper;
public Comp(int type, int relation, String lower, String upper) {
this.type = type;
this.relation = relation;
this.lower = lower;
this.upper = upper;
}
}
class CompCellPanel extends JPanel {
private static final long serialVersionUID = 1L;
private JLabel labelWith = new JLabel("With ");
private JComboBox typeCombo = new JComboBox(new Object[]{"height", "length", "volume"});
private JComboBox relationCombo = new JComboBox(new Object[]{"above", "below", "between"});
private JTextField lowerField = new JTextField();
private JLabel labelAnd = new JLabel(" and ");
private JTextField upperField = new JTextField();
private JButton removeButton = new JButton("remove");
CompCellPanel() {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
relationCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
enableUpper(relationCombo.getSelectedIndex() == 2);
}
});
enableUpper(false);
removeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JTable table = (JTable) SwingUtilities.getAncestorOfClass(JTable.class, (Component) e.getSource());
int row = table.getEditingRow();
table.getCellEditor().stopCellEditing();
((DefaultTableModel) table.getModel()).removeRow(row);
}
});
add(labelWith);
add(typeCombo);
add(relationCombo);
add(lowerField);
add(labelAnd);
add(upperField);
add(Box.createHorizontalStrut(100));
add(removeButton);
}
private void enableUpper(boolean enable) {
labelAnd.setEnabled(enable);
upperField.setEnabled(enable);
}
public void setComp(Comp Comp) {
typeCombo.setSelectedIndex(Comp.type);
relationCombo.setSelectedIndex(Comp.relation);
lowerField.setText(Comp.lower);
upperField.setText(Comp.upper);
enableUpper(Comp.relation == 2);
}
public Comp getComp() {
return new Comp(typeCombo.getSelectedIndex(), relationCombo.getSelectedIndex(), lowerField.getText(), upperField.getText());
}
}
Другие советы
Я думаю, что такой пользовательский TableModel и TableCellRenderer / Editor - лучший выбор.http://download.oracle.com/javase/tutorial/uiswing/components/table.html С этого было бы неплохо начать.
добавьте все компоненты для критериев поиска на панель и добавьте / удалите конкретную панель.Я не думаю, что табличная модель здесь является хорошим выбором.
Netbeans имеет приятный пользовательский интерфейс, который делает что-то похожее на то, что вы описываете:
Почему бы не встать на плечи гигантов?Панели Netbeans выглядят красиво и хорошо работают.Реализация даже четко разделена между пользовательским интерфейсом и кодом модели.Если бы я был на вашем месте (а это был июнь 2011 года), я бы основывал свое решение на приведенном здесь исходном коде:
http://hg.netbeans.org/main/file/14d339767aef/tasklist.ui/src/org/netbeans/modules/tasklist/filter
KeywordPanel.java содержит этот загадочный комментарий:"Графический интерфейс основан на интерфейсе почтового инструмента Mozilla".
Интересно, что бы это могло быть?
Извините за поздний ответ.