如何在swing中实现动态GUI [英] How to implement dynamic GUI in swing
问题描述
首先,对于发布的内容可能有点过于具体,但我对 Swing 的经验不是很丰富,而且似乎无法找到适合我需求的好例子,我深表歉意.
First of all, apologies for posting something perhaps a bit excessively specific, but I'm not very experienced with Swing, and can't seem to find good examples that fit my needs.
所以我试图找出实现动态 GUI 以在 Swing 中选择过滤条件的最佳方法:
So I'm trying to figure out the best way to implement the a dynamic GUI for choosing filtering criteria in Swing:
底层模型是一个包含可以否定的标准列表(即使用 NOT 前缀)的类,以及指示这些是否应该与 AND 或 OR 组合的属性.
The underlying model is a class containing a list of criteria that can be negated (i.e. applied with a NOT-prefix), and a property indicating whether these should be combined with AND or OR.
GUI 将允许用户添加、更改或删除标准,并选择组合运算符(和/或).第一个标准自然不会有组合选择器,而第三个和后续标准将简单地使用与第二个相同的组合运算符.
The GUI would allow the user to add, change or remove criteria, and select the combination operator (and/or). The first criterium would naturally not have a combination-selector, and the third and subsequent criteria would simply use the same combination-operator as the second one.
右侧的 X 按钮将用于删除条件.当按下添加按钮时,将在底部添加一行新的组件.随着更改的进行,这些将反映在基础模型中.
The X-buttons on the right would be used to delete a criterium. When the Add-button is pressed, a new line of components would be added to the bottom. As changes are made, these would be reflected in the underlying model.
当然,我可以通过简单地向 JPanel 添加组件然后相应地更新模型来实现这一点,但我更喜欢更简洁的解决方案,例如 TableModel 提供的解决方案.
Of course I could implement this quite "primitively" by simply adding components to a JPanel and then updating the model accordingly, but I would prefer a neater solution, such as that provided by a TableModel.
所以我想知道带有自定义 TableModel 和 TableCellRenderer/Editor 的表是否是最好的方法,或者是否有更好的方法来实现这样的东西.如果 table 确实是最好的方法,我会很感激一些关于如何使用 TableCellRenderers 或 -Editors 来实现这一点的指示.
So I'm wondering if a table with a custom TableModel and TableCellRenderer/Editor would be the best approach, or if there is a better way to implement something like this. If table is indeed the best approach, I would appreciate some pointers to how one would use TableCellRenderers or -Editors to accomplish this.
提前致谢.
推荐答案
仅为示例,一切都是硬编码的,便于理解
only example, everything is hardcoded, for good understanding
正如 kleopatra 所注意到的,将 JTable#fireTableDataChanged() 从 ActionListener 移动到 TableModel,修改了所有以小写开头的 ClassNames
as kleopatra's noticed, moved JTable#fireTableDataChanged() from ActionListener to the TableModel, amended all ClassNames start with lowerCase
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());
}
}
这篇关于如何在swing中实现动态GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!