如何在摆动中实现动态GUI

| 首先,为发布一些过分具体的内容而道歉,但是我对Swing不太了解,并且似乎找不到适合我需求的好例子。 因此,我试图找出实现动态GUI以便在Swing中选择过滤条件的最佳方法: 基础模型是一个类,其中包含可否定的条件列表(即使用NOT前缀应用)以及指示这些条件应与AND还是OR组合的属性。 GUI将允许用户添加,更改或删除条件,并选择组合运算符(和/或)。第一个条件自然不会具有组合选择器,而第三个条件和后续条件将仅使用与第二个条件相同的组合操作符。 右侧的X按钮将用于删除条件。当按下添加按钮时,新的组件行将被添加到底部。 进行更改时,这些更改将反映在基础模型中。 当然,通过简单地将组件添加到JPanel然后相应地更新模型,我可以“非常原始地”实现此功能,但是我更喜欢更整洁的解决方案,例如TableModel提供的解决方案。 因此,我想知道带有自定义TableModel和TableCellRenderer / Editor的表是否是最好的方法,或者是否有更好的方法来实现这种方式。如果table确实是最好的方法,我将对使用TableCellRenderers或-Editors如何完成此工作的一些指示表示赞赏。 提前致谢。     
已邀请:
        仅作为示例,所有内容都经过硬编码,以更好地理解 编辑: 正如kleopatra所注意到的那样,将JTable#fireTableDataChanged()从ActionListener移到了TableModel,修改了所有ClassName以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());
    }
}
    
        我认为这样的自定义TableMOdel和TableCellRenderer / Editor是最佳选择。 http://download.oracle.com/javase/tutorial/uiswing/components/table.html 那将是很好的开始。     
        将搜索条件的所有组件添加到面板中,然后添加/删除特定的面板。我认为Tablemodel在这里不是一个好的选择。     
        Netbeans有一个不错的ui,它的功能类似于您所描述的: 为什么不站在巨人的肩膀上呢? Netbeans面板看起来不错并且运行良好。实现甚至在ui和模型代码之间完全分开。如果我正穿上鞋子(那是2011年6月),我的解决方案将基于以下来源: http://hg.netbeans.org/main/file/14d339767aef/tasklist.ui/src/org/netbeans/modules/tasklist/filter KeywordPanel.java包含以下神秘注释:\“ GUI基于Mozilla邮件工具中的GUI \”。 我不知道那会是什么? 抱歉回复晚了。     

要回复问题请先登录注册