Hallo Leute!
Ich habe eine Frage zur Programmstruktur.
Ich möchte gerne mit Action-Klassen (abgeleitet von "AbstractAction") arbeiten, da mehrere Komponenten (z.B. Menü, Button, Taste auf dem Keyboard) dieselbe Funktion aufrufen sollen. Doch gleich bei einer der ersten gibt's ein Problem, für das ich keine Lösung weiß.
Die Klasse "ToggleFilterPanelAction" wird im Konstruktor "MainFrame()" vor dem Aufruf der Methode "initComponents()" initialisiert. Dummerweise benötigt "ToggleFilterPanelAction" die Instanz? des "JXCollapsiblePane" (in meinem Beispiel die Variable "cp1"). Diese gibt es zu dem Zeitpunkt der Initialisierung der besagten Action-Klasse noch nicht und somit wird die Funktion auch nicht richtig ausgeführt.
Initialisierung ich die Action-Klasse erst nach "initComponents()", dann fehlt den Komponenten (derzeit nur das entsprechende Menü-Item) die Instanz? der Action-Klasse. Somit funktioniert auch dies nicht.
Wie kann ich das Problem lösen?
Würde mich sehr über eure Hilfe freuen!
Ich habe eine Frage zur Programmstruktur.
Ich möchte gerne mit Action-Klassen (abgeleitet von "AbstractAction") arbeiten, da mehrere Komponenten (z.B. Menü, Button, Taste auf dem Keyboard) dieselbe Funktion aufrufen sollen. Doch gleich bei einer der ersten gibt's ein Problem, für das ich keine Lösung weiß.
Die Klasse "ToggleFilterPanelAction" wird im Konstruktor "MainFrame()" vor dem Aufruf der Methode "initComponents()" initialisiert. Dummerweise benötigt "ToggleFilterPanelAction" die Instanz? des "JXCollapsiblePane" (in meinem Beispiel die Variable "cp1"). Diese gibt es zu dem Zeitpunkt der Initialisierung der besagten Action-Klasse noch nicht und somit wird die Funktion auch nicht richtig ausgeführt.
Initialisierung ich die Action-Klasse erst nach "initComponents()", dann fehlt den Komponenten (derzeit nur das entsprechende Menü-Item) die Instanz? der Action-Klasse. Somit funktioniert auch dies nicht.
Wie kann ich das Problem lösen?
Würde mich sehr über eure Hilfe freuen!
Java:
package view;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableRowSorter;
import model.LibraryTableModel;
import model.Paper;
import model.Subjects;
import org.jdesktop.swingx.JXCollapsiblePane;
import org.jdesktop.swingx.JXFrame;
import org.jdesktop.swingx.JXStatusBar;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.combobox.ListComboBoxModel;
import org.jdesktop.swingx.decorator.HighlighterFactory;
/**
* Diese Klasse dient zur Darstellung des Hauptfensters des Programms.
*/
public class MainFrame extends JXFrame {
private LibraryTableModel libraryTableModel;
private JXTable libraryTable;
private TableRowSorter<LibraryTableModel> sorter;
private JPanel controlPanel;
private JTextField filterText;
private JComboBox strictComboBox;
private JList filterSubject;
private DefaultListModel filterSubjectModel;
private JComponent statusBarLeft;
private JLabel actionStatus;
private JLabel tableRows;
private JLabel modelRows;
JXCollapsiblePane cp1;
ToggleFilterPanelAction actionToggleFilter;
CloseAction actionClose;
/**
* Konstruktur.
*/
public MainFrame() {
super("GreatLibrary");
setDefaultCloseOperation(JXFrame.EXIT_ON_CLOSE);
actionToggleFilter = new ToggleFilterPanelAction();
actionClose = new CloseAction();
initComponents();
pack();
setLocationRelativeTo(null);
}
/**
* Initialisierung und Zusammenbau der Komponenten des Hauptfensters.
*/
private void initComponents() {
// Menu
JMenuBar menuBar = new JMenuBar();
menuBar.add(createFileMenu());
setJMenuBar(menuBar);
setLayout(new BorderLayout());
cp1 = new JXCollapsiblePane();
cp1.setLayout(new BorderLayout());
controlPanel = createControlPanel();
cp1.add(controlPanel, BorderLayout.NORTH);
add(cp1, BorderLayout.NORTH);
libraryTableModel = new LibraryTableModel();
libraryTable = new JXTable(libraryTableModel);
libraryTable.setColumnControlVisible(true);
libraryTable.setShowGrid(false, false);
libraryTable.addHighlighter(HighlighterFactory.createSimpleStriping());
libraryTable.setVisibleRowCount(25);
libraryTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
libraryTable.getColumnModel().getColumn(0).setPreferredWidth(1100);
libraryTable.getColumnModel().getColumn(1).setPreferredWidth(400);
libraryTable.getColumnModel().getColumn(2).setPreferredWidth(75);
libraryTable.getColumnModel().getColumn(3).setPreferredWidth(200);
sorter = new TableRowSorter<LibraryTableModel>(libraryTableModel);
libraryTable.setRowSorter(sorter);
JScrollPane scrollpane = new JScrollPane(libraryTable);
libraryTableModel.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
System.out.println("TableModelListener -> tableChanged()");
updateStatusBar();
}
});
add(scrollpane, BorderLayout.CENTER);
add(createStatusBar(), BorderLayout.SOUTH);
updateStatusBar();
}
protected JPanel createControlPanel() {
ArrayList<String> list;
JPanel panel = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
panel.setLayout(gridbag);
c.gridx = 0;
c.gridy = 1;
c.gridheight = 1;
c.insets = new Insets(20, 10, 0, 10);
c.anchor = GridBagConstraints.SOUTHWEST;
JLabel l1 = new JLabel("Title:");
panel.add(l1, c);
c.gridx = 0;
c.gridy = 2;
c.weightx = 1.0;
c.insets.top = 0;
c.insets.bottom = 12;
c.anchor = GridBagConstraints.SOUTHWEST;
filterText = new JTextField(24);
panel.add(filterText, c);
filterText.getDocument().addDocumentListener(
new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
newFilter();
}
public void insertUpdate(DocumentEvent e) {
newFilter();
}
public void removeUpdate(DocumentEvent e) {
newFilter();
}
});
// ##################################################################
c.gridx = 1;
c.gridy = 1;
c.gridheight = 1;
c.insets = new Insets(20, 10, 0, 10);
c.anchor = GridBagConstraints.SOUTHWEST;
JLabel l2 = new JLabel("Subject:");
// searchLabel.setName("searchLabel");
panel.add(l2, c);
c.gridx = 1;
c.gridy = 2;
c.weightx = 1.0;
c.insets.top = 0;
c.insets.bottom = 12;
c.anchor = GridBagConstraints.SOUTHWEST;
strictComboBox = new JComboBox();
Subjects subjects = Subjects.getInstance();
list = subjects.getSubjects();
strictComboBox.setModel(new ListComboBoxModel<String>(list));
// AutoCompleteDecorator.decorate(strictComboBox);
strictComboBox.addKeyListener(
new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.VK_ENTER) {
String str = (String) strictComboBox.getSelectedItem();
if (filterSubjectModel.contains(strictComboBox.getSelectedItem()) == false) {
System.out.println("add to subject filter: " + str);
filterSubjectModel.addElement(str);
} else {
System.out.println("do not add to subject filter = " + str);
}
}
}
});
panel.add(strictComboBox, c);
filterSubjectModel = new DefaultListModel();
filterSubjectModel.addListDataListener(
new ListDataListener() {
public void contentsChanged(ListDataEvent e) {
}
public void intervalAdded(ListDataEvent e) {
newFilter();
}
public void intervalRemoved(ListDataEvent e) {
newFilter();
}
});
filterSubject = new JList(filterSubjectModel);
filterSubject.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
filterSubject.addKeyListener(
new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.VK_ENTER) {
if (filterSubject.isSelectionEmpty() == false) {
String str = (String) filterSubject.getSelectedValue();
System.out.println("remove from subject filter: " + str);
filterSubjectModel.removeElement(str);
} else {
System.out.println("remove from subject filter: no entry");
}
}
}
});
JScrollPane sp = new JScrollPane(filterSubject);
c.gridx = 3;
c.gridy = 1;
c.gridheight = 2;
c.insets = new Insets(20, 10, 0, 10);
c.anchor = GridBagConstraints.SOUTHWEST;
panel.add(sp, c);
return panel;
}
/**
* TODO: Müssen alle Filter in einer Funktion sein, oder kann ich auch mehrere Funktionen schreiben?
*/
private void newFilter() {
RowFilter<LibraryTableModel, Integer> filter1 = new RowFilter<LibraryTableModel, Integer>() {
@Override
public boolean include(Entry<? extends LibraryTableModel, ? extends Integer> entry) {
LibraryTableModel tableModel = entry.getModel();
Paper paper = tableModel.getPaper(entry.getIdentifier());
String title = paper.getTitle().toLowerCase();
String text = paper.getText().toLowerCase();
String comment = paper.getComment().toLowerCase();
String id = String.valueOf(paper.getId());
final String filter = filterText.getText().toLowerCase();
if (title.contains(filter) || text.contains(filter) || comment.contains(filter) || id.startsWith(filter)) {
return true;
}
return false;
}
};
RowFilter<LibraryTableModel, Integer> filter2 = new RowFilter<LibraryTableModel, Integer>() {
@Override
public boolean include(Entry<? extends LibraryTableModel, ? extends Integer> entry) {
LibraryTableModel tableModel = entry.getModel();
Paper paper = tableModel.getPaper(entry.getIdentifier());
ArrayList<String> arrayList = new ArrayList<String>();
for (int i = 0; i < filterSubjectModel.size(); i++) {
System.out.println("i=" + i + "\t" + filterSubjectModel.size() + "\t" + filterSubjectModel.get(i)); // TODO: Wieso kommt diese Aussage mehrmals?
arrayList.add((String) filterSubjectModel.get(i));
}
if (paper.getSubjects().containsAll(arrayList)) {
return true;
}
return false;
}
};
final ArrayList<RowFilter<LibraryTableModel, Integer>> filters = new ArrayList<RowFilter<LibraryTableModel, Integer>>(2);
filters.add(filter1);
filters.add(filter2);
final RowFilter<LibraryTableModel, Integer> filter = RowFilter.andFilter(filters);
sorter.setRowFilter(filter);
updateStatusBar();
}
/**
* TODO: Den Inhalt dieser Funktion verstehe ich nicht komplett.
* @return
*/
protected Container createStatusBar() {
JXStatusBar statusBar = new JXStatusBar();
statusBar.putClientProperty("auto-add-separator", Boolean.FALSE);
// Left status area
statusBar.add(Box.createRigidArea(new Dimension(10, 22)));
statusBarLeft = Box.createHorizontalBox();
statusBar.add(statusBarLeft, JXStatusBar.Constraint.ResizeBehavior.FILL);
actionStatus = new JLabel();
actionStatus.setName("loadingStatusLabel");
actionStatus.setHorizontalAlignment(JLabel.LEADING);
statusBarLeft.add(actionStatus);
statusBar.add(Box.createVerticalGlue());
statusBar.add(Box.createRigidArea(new Dimension(50, 0)));
// Right status area
JComponent bar = Box.createHorizontalBox();
bar.add(new JLabel("Showing "));
tableRows = new JLabel("0");
bar.add(tableRows);
bar.add(new JLabel(" of "));
modelRows = new JLabel("0");
bar.add(modelRows);
bar.add(new JLabel(" Papers"));
statusBar.add(bar);
statusBar.add(Box.createHorizontalStrut(12));
return statusBar;
}
/**
* Updates status labels. Called during loading and on changes to the filter controller state.
*/
protected void updateStatusBar() {
System.out.println("updateStatusBar()");
tableRows.setText("" + libraryTable.getRowCount());
modelRows.setText("" + libraryTableModel.getRowCount());
}
// ###############################################################################################
// MENU
// ###############################################################################################
private JMenu createFileMenu() {
JMenu ret = new JMenu("Datei");
JMenuItem mi;
mi = new JMenuItem(actionToggleFilter);
ret.add(mi);
ret.addSeparator();
mi = new JMenuItem(actionClose);
ret.add(mi);
return ret;
}
// ###############################################################################################
// ACTION
// ###############################################################################################
class ToggleFilterPanelAction extends AbstractAction {
Boolean status = true;
{
putValue(Action.NAME, "Filter ausblenden");
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F1));
}
@Override
public void actionPerformed(ActionEvent e) {
if(status == true) {
System.out.println("Filter aus");
putValue(Action.NAME, "Filter einblenden");
status = false;
} else {
System.out.println("Filter ein");
putValue(Action.NAME, "Filter ausblenden");
status = true;
}
cp1.getActionMap().get(JXCollapsiblePane.TOGGLE_ACTION);
}
}
class CloseAction extends AbstractAction {
{
putValue(Action.NAME, "Beenden");
putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, 0);
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}