Domanda

Prima di tutto, mi scuso per aver pubblicato qualcosa di forse un po 'eccessivamente specifico, ma non ho molto esperienza con lo swing e non riesco a trovare buoni esempi che si adattino alle mie esigenze.

Quindi sto cercando di capire il modo migliore per implementare una GUI dinamica per la scelta di criteri di filtraggio in swing:

Mockup of GUI to implement

Il modello sottostante è una classe contenente un elenco di criteri che possono essere annullati (cioè applicati con un non prefisso) e una proprietà che indica se questi dovrebbero essere combinati con e o o.

La GUI consentirebbe all'utente di aggiungere, modificare o rimuovere i criteri e selezionare l'operatore di combinazione (e/o). Il primo criterio non avrebbe naturalmente un selettore di combinazione e il terzo e successivo criteri userebbero semplicemente lo stesso operatore combinato del secondo.

Gli X-Buttons a destra verrebbero utilizzati per eliminare un criterio. Quando viene premuto l'aggiunta, una nuova linea di componenti verrebbe aggiunta sul fondo. Man mano che vengono apportate modifiche, queste si riflettono nel modello sottostante.

Naturalmente potrei implementare questo abbastanza "primitivamente" aggiungendo semplicemente componenti a un JPanel e quindi aggiornando il modello di conseguenza, ma preferirei una soluzione più ordinata, come quella fornita da un tablemodel.

Quindi mi chiedo se una tabella con un tablemodel personalizzato e tablecellrender/editor sarebbe l'approccio migliore o se esiste un modo migliore per implementare qualcosa del genere. Se la tabella è davvero l'approccio migliore, apprezzerei alcuni suggerimenti su come si userebbe le tablecellrender o i redattori per raggiungere questo obiettivo.

Grazie in anticipo.

È stato utile?

Soluzione

L'unico esempio, tutto è codificato, per una buona comprensione

MODIFICARE:

Come notato da Kleopatra, spostato Jtable#FireTableAtatetaChanged () da ActionListener al tablemodel, modificati tutti i nomi di classe iniziano con un minuscolo

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());
    }
}

Altri suggerimenti

Penso che un tablemodel così personalizzato e un tablecellrender/editor siano la scelta migliore.http://download.oracle.com/javase/tutorial/uiswing/components/table.htmlSarebbe bello iniziare.

Aggiungi tutti i componenti per un criterio di ricerca a un pannello e aggiungi/rimuovi il pannello specifico. Non credo che un tablemodel sia una buona scelta qui.

NetBeans ha una bella interfaccia utente che fa qualcosa di simile a quello che descrivi:Task List Filter KeywordPanel

Perché non stare sulle spalle dei giganti? I pannelli Netbeans sembrano belli e funzionano bene. L'implementazione è persino separata in modo pulito tra l'interfaccia utente e il codice modello. Se fossi nelle tue scarpe (ed era giugno del 2011), baserei la mia soluzione sulla fonte qui:

http://hg.netbeans.org/main/file/14d339767aef/tasklist.ui/src/org/netbeans/modules/tasklist/filter

Key wordpanel.java contiene questo commento criptico: "La GUI si basa su quella nello strumento di posta di Mozilla".

Mi chiedo cosa potrebbe essere?

Scusa per la risposta tardiva.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top