What I want seems relatively simple, and I'm almost there. This will eventually be used to extend TableCellEditor, so the size is important. What I want is something like this:
With a combination of custom ComboBoxEditors and ListCellRenderers I've been able to get something like this:
Which has the inconveniences of:
Cutting off any components beyond the original width of the JComboBox
Forcing the height of the JComboBox to be the height of the JPanel in the drop-down
Allowing only one (1) click modification of the form before the drop-down disappears.
I'd like to have the drop-down stay visible until the user clicks the editor or the JComboBox looses focus to another control, and then have the value in the editor update. There will only ever be one (1) JPanel in the drop-down and I don't want the editor to be able to actually edit the string displayed.
My question is similar to #ErkanHaspalut 's question here but neither response is satisfying. I'd previously made a similar attempt by embedding a JPanel in a JPopupMenu and adding it to a JTextField but had similar issues about the popup disappearing prematurely.
I've tried forcing the size of the JComboBox both by setting the setMaximumSize height value (which has no effect) and with
Rectangle tmp = cboTest.getBounds();
tmp.height = 24;
cboTest.setBounds(tmp);
which simply shows the top 24 lines of the JComboBox. A minimum compilable example would be
/*
* Program to test having a JPanel in the JComboBox's drop-down but not the JComboBox's editor.
*/
package testdropdownsubform;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javafx.application.Application;
import javafx.stage.Stage;
import javax.swing.ComboBoxEditor;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.JTextField;
import javax.swing.plaf.basic.BasicComboBoxEditor;
/**
* #author Masked Coder
*/
public class Dim {
public Long DimWidth;
public Long DimHeight;
public Dim () {
DimWidth = 1L;
DimHeight = 1L;
}
#Override
public String toString() {
return DimWidth.toString() + "\' x " + DimHeight.toString() + "\'";
}
}
public class DimPanel extends javax.swing.JPanel {
public DimPanel() {
spnDimWidth = new javax.swing.JSpinner();
spnDimHeight = new javax.swing.JSpinner();
spnDimWidth.setModel(new javax.swing.SpinnerNumberModel(Long.valueOf(1L), Long.valueOf(0L), null, Long.valueOf(1L)));
spnDimWidth.setPreferredSize(new java.awt.Dimension(50, 24));
addComponent(spnDimWidth);
lblTween.setText(" x ");
addComponent(lblTween);
spnDimHeight.setModel(new javax.swing.SpinnerNumberModel(Long.valueOf(1L), Long.valueOf(0L), null, Long.valueOf(1L)));
spnDimHeight.setPreferredSize(new java.awt.Dimension(50, 24));
addComponent(spnDimHeight);
}
private javax.swing.JSpinner spnDimWidth;
private javax.swing.JLabel lblTween;
private javax.swing.JSpinner spnDimHeight;
}
public class DimListCellRenderer implements ListCellRenderer {
private DimPanel dpDim;
public DimListCellRenderer(DimPanel newDimPanel) {
dpDim = newDimPanel;
}
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Dim dValue = (Dim) value;
dpDim.setDim(dValue);
return dpDim;
}
}
public class DimComboBoxEditor extends BasicComboBoxEditor implements ComboBoxEditor {
JTextField txtDim = new JTextField();
Dim Item = new Dim();
public DimComboBoxEditor() {
txtDim.setEnabled(false);
txtDim.setOpaque(true);
}
#Override
public Component getEditorComponent() {
txtDim.setText(Item.toString());
return txtDim;
}
#Override
public void setItem(Object anObject) {
Item = (Dim) anObject;
}
#Override
public Object getItem() {
return Item;
}
#Override
public void selectAll() {
txtDim.selectAll();
}
#Override
public void addActionListener(ActionListener l) {
txtDim.addActionListener(l);
}
#Override
public void removeActionListener(ActionListener l) {
txtDim.removeActionListener(l);
}
}
public class MainTestForm extends javax.swing.JFrame {
public MainTestForm() {
lblPrevComponent = new javax.swing.JLabel();
chkPrevComponent = new javax.swing.JCheckBox();
lblTest = new javax.swing.JLabel();
cboTest = new JComboBox<testdropdownsubform.DicePanel>();
lblNextComponent = new javax.swing.JLabel();
scpNextComponent = new javax.swing.JScrollPane();
txaNextComponent = new javax.swing.JTextArea();
btnForceHeight = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
lblPrevComponent.setText("Prev. Component");
chkPrevComponent.setText("jCheckBox1");
lblTest.setText("Dimension");
cboTest.setEditable(true);
cboTest.setEditor(new DimComboBoxEditor());
cboTest.setRenderer(new DimListCellRenderer(new DimPanel()));
cboTest.addItem(new Dim());
lblNextComponent.setText("Next Component");
txaNextComponent.setColumns(20);
txaNextComponent.setRows(5);
scpNextComponent.setViewportView(txaNextComponent);
btnForceHeight.setText("Force");
btnForceHeight.setToolTipText("Force test combobox height");
btnForceHeight.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnForceHeightActionPerformed(evt);
}
});
.addComponent(lblPrevComponent)
.addComponent(chkPrevComponent))
.addComponent(lblTest)
.addComponent(cboTest)
.addComponent(lblNextComponent)
.addComponent(scpNextComponent)
.addComponent(btnForceHeight))
}
private void btnForceHeightActionPerformed(java.awt.event.ActionEvent evt) {
Rectangle tmp = cboTest.getBounds();
tmp.height = 24;
cboTest.setBounds(tmp);
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainTestForm().setVisible(true);
}
});
}
private javax.swing.JButton btnForceHeight;
private javax.swing.JComboBox cboTest;
private javax.swing.JCheckBox chkPrevComponent;
private javax.swing.JLabel lblNextComponent;
private javax.swing.JLabel lblPrevComponent;
private javax.swing.JLabel lblTest;
private javax.swing.JScrollPane scpNextComponent;
private javax.swing.JTextArea txaNextComponent;
}
public class TestDropdownSubform extends Application {
#Override
public void start(Stage primaryStage) {
MainTestForm mtfMain = new MainTestForm();
mtfMain.setVisible(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
My question is, am I missing a detail, or can anyone see a better way to accomplish this? Thanks in advance for your advice.
Edit: Declaring the JComboBox as
JComboBox cboTest = new JComboBox<DimPanel>() {
private boolean layingOut = false;
#Override
public void doLayout(){
try{
layingOut = true;
super.doLayout();
}finally{
layingOut = false;
}
}
#Override
public Dimension getSize(){
Dimension dim = super.getSize();
if(!layingOut) {
dim.width = Math.max(dim.width, dpThis.getPreferredSize().width);
}
return dim;
}
};
fixes the width of the drop-down. Declaring it as
JComboBox cboTest = new JComboBox<testdropdownsubform.DicePanel>() {
private boolean layingOut = false;
#Override
public void doLayout(){
try{
layingOut = true;
super.doLayout();
}finally{
layingOut = false;
}
}
#Override
public Dimension getSize(){
Dimension dim = super.getSize();
if(!layingOut) {
Dimension dim2 = dpThis.getPreferredSize();
dim.width = Math.max(dim.width, dim2.width);
// dim.height = dim2.height;
}
return dim;
}
#Override
public DimPanel getPrototypeDisplayValue() {
DimPanel tmpPanel = new DimPanel();
if(isCalledFromComboPopup()) {
//
}
else {
Dimension r = dcbeEditor.getPreferredSize();
tmpPanel.setPreferredSize(r);
}
return tmpPanel;
}
/**
* Hack method to determine if called from within the combo popup UI.
*/
public boolean isCalledFromComboPopup() {
try {
final Throwable t = new Throwable();
t.fillInStackTrace();
StackTraceElement[] st = t.getStackTrace();
// look only at top 5 elements of call stack
int max = Math.min(st.length, 5);
for (int i=0; i<max; ++i) {
final String name = st[i].getClassName();
System.out.println(i + ") " + name);
return ((name != null) && name.contains("ComboPopup"));
}
} catch (final Exception e) {
// if there was a problem, assume not called from combo popup
}
return false;
}
};
fixes the editor size but now the drop-down is the width and height of the editor.
So, I ended up going on a different track, creating my own pseudo-combobox with a JTextField and a JButton in a JPanel. I believe I've quite handily genericized the result into four related classes. First, you need an implementation of AbstractPopupPanel (which quite handily loads into the NetBeans designer if you're using it):
package complexcombobox;
/**
*
* #author MaskedCoder
*
* #param E - the object to be edited in the panel
*/
public abstract class AbstractPopupPanel<E> extends javax.swing.JPanel {
/**
* Creates new form PopupPanel
*/
public AbstractPopupPanel() {
initComponents();
}
public abstract boolean isChanged();
public abstract E getValue();
public abstract void setValue(E newValue);
private void initComponents() {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}
}
With that created to your satisfaction, we need to place it in a pop-up menu:
package complexcombobox;
import javax.swing.JPopupMenu;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
*
* #author MaskedCoder
*
* #param E - the object to be edited
* #param P - the extension of AbstractPopupPanel that will display the object as you wish
*/
public class ComplexPopup<E, P extends AbstractPopupPanel<E>> extends JPopupMenu {
/*
* Interface to notify user of editing
*/
public interface EditListener<E> {
// return the object's value to be edited.
// if the user returns null, the existing Dice is used.
public E beforeEdit();
// receives the new value
// called *only* when the object has actually changed.
public void afterEdit(E newValue);
}
/*
*internal variables
*/
private P thisPanel;
private EditListener<E> userListener;
// private Class<E> eClass;
// private Class<P> pClass;
private PopupMenuListener myPopupListener = new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
if(userListener != null) {
E tmpSize = userListener.beforeEdit();
if(tmpSize != null) thisPanel.setValue(tmpSize);
}
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
if(userListener != null) {
// if(thisPanel.isChanged())
userListener.afterEdit((E) thisPanel.getValue());
}
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
popupMenuWillBecomeInvisible(e);
}
};
/*
* Constructors
*/
public ComplexPopup(E iniValue, P iniDropdownPanel, EditListener<E> iniListener) {
super();
init(iniValue, iniDropdownPanel, iniListener);
}
private void init(E iniValue, P iniDropdownPanel, EditListener<E> iniListener) {
thisPanel = iniDropdownPanel;
thisPanel.setValue(iniValue);
add(thisPanel);
userListener = iniListener;
this.addPopupMenuListener(myPopupListener);
}
/*
* Public Properties
*/
public E getValue() {
return (E) thisPanel.getValue();
}
public void setValue(E newObjectSize) {
thisPanel.setValue(newObjectSize);
}
public EditListener getUserListener() {
return userListener;
}
public void setEditListener(EditListener newListener) {
userListener = newListener;
}
/*
* functional extensions
*/
public void afterEdit(E newValue) {
if(userListener != null) {
if(thisPanel.isChanged())
userListener.afterEdit((E) thisPanel.getValue());
}
}
}
This places the form in a JPopupMenu and allows access to the object to be edited as well as notification before and after editing. Now, I couldn't co-opt the JComboBox interface without getting deeper into the mechanics than I wanted to go, so I fudged the combo box, as I mentioned:
package complexcombobox;
/**
*
* #author MaskedCoder
*
* #param <I> the Item (Object) to be edited
* #param <Q> the AbstractPopupPanel to be used to do the editing.
*/
public class ComplexComboBox<I, Q extends AbstractPopupPanel<I>> extends javax.swing.JPanel {
private ComplexPopup<I, Q> thePopup;
private ComplexPopup.EditListener<I> myListener = new ComplexPopup.EditListener<I>() {
#Override
public I beforeEdit() {
return null; // no changes so, just let it ride.
}
#Override
public void afterEdit(I newValue) {
txtEditor.setText(thePopup.getValue().toString());
}
};
/**
* Creates new form ObjectSizeComboBox
*/
public ComplexComboBox(I iniValue, Q iniPanel) {
initComponents();
thePopup = new ComplexPopup<I, Q>(iniValue, iniPanel, myListener);
}
public I getValue() {
return thePopup.getValue();
}
public void setValue(I newValue) {
thePopup.setValue(newValue);
}
private void initComponents() {
txtEditor = new javax.swing.JTextField();
btnShowPanel = new javax.swing.JButton();
setBackground(new java.awt.Color(255, 255, 255));
setMinimumSize(new java.awt.Dimension(40, 19));
txtEditor.setEditable(false);
txtEditor.setToolTipText("");
txtEditor.setOpaque(false);
btnShowPanel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/testpopupsubform/art/dropdownarrow.png"))); // NOI18N
btnShowPanel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnShowPanelActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(txtEditor, javax.swing.GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE)
.addGap(1, 1, 1)
.addComponent(btnShowPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnShowPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(txtEditor)
);
}
private void btnShowPanelActionPerformed(java.awt.event.ActionEvent evt) {
thePopup.show(txtEditor, 0, txtEditor.getHeight());
}
private javax.swing.JButton btnShowPanel;
private javax.swing.JTextField txtEditor;
}
This seems to work very well in a cell editor for a table, provided you make the row heights tall enough. That's no different than a regular JComboBox editor, though:
package complexcombobox;
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
/**
*
* #author MaskedCoder
*
* #param <E> the Element (Object) to be edited
* #param <P> the AbstractPopupPanel to be used to do the editing.
*/
public class ComplexCellEditor<E, P extends AbstractPopupPanel<E>> extends AbstractCellEditor
implements TableCellEditor {
private ComplexComboBox<E, P> ComplexEditor;
/*
* Constructors
*/
public ComplexCellEditor(E iniValue, P iniPanel) {
super();
ComplexEditor = new ComplexComboBox<E, P>(iniValue, iniPanel);
}
/*
* AbstractCellEditor Extensions
*/
#Override
public boolean stopCellEditing() {
return super.stopCellEditing();
}
/*
* TableCellEditor Implementation
*/
#Override
public E getCellEditorValue() {
return ComplexEditor.getValue();
}
#Override
public Component getTableCellEditorComponent(JTable iniTable, Object iniValue, boolean isSelected, int row, int column) {
ComplexEditor.setValue((E) iniValue);
return ComplexEditor;
}
}
Three things I'm not entirely satisfied with:
- I'd like to grab the JComboBox down-arrow icon from the system rather than relying on a project resource
- I've had to pass through the AbstractPopupPanel instance which means that the coder has to create the panel themselves and then hand it to the constructor for ComplexComboBox or ComplexCellEditor. I'd rather have created the panel internally, in ComplexPopup and managed it myself. I ran into difficulty instantiating Generic constructors. Pass-through does allow the coder more control but I don't think that's needed and I'd like it to be optional at least.
My knowledge of Generics isn't advanced but this seems to do the trick.
Related
Using this example here:
https://stackoverflow.com/a/30509195
Works great to create multiple tables for summation rows. I also needed the scrollbar visible on the bottom table as well. However, the bottom table's scrollbar doesn't sync with the main table (at first with empty content). When there is data, the scrollbar syncs properly.
When you add data to the table, then remove the data, again, scroll bars sync properly. So I know they can still be synced with a table with empty content.
Here is the example code (with two buttons on the top to add and clear items)
package testsummary;
import java.text.Format;
import java.time.LocalDate;
import java.time.Month;
import java.util.Set;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
* Table with a summary table. The summary table is a 2nd table which is
* synchronized with the primary table.
*
* TODO: + always show vertical bars for both the primary and the summary table,
* otherweise the width of both tables wouldn't be the same + hide the
* horizontal scrollbar of the summary table
*
*/
public class SummaryTableDemo extends Application
{
private TableView<Data> mainTable = new TableView<>();
private TableView<SumData> sumTable = new TableView<>();
private final ObservableList<Data> data
= FXCollections.observableArrayList();
// TODO: calculate values
private final ObservableList<SumData> sumData
= FXCollections.observableArrayList(
new SumData("Sum", 0.0, 0.0, 0.0),
new SumData("Min", 0.0, 0.0, 0.0),
new SumData("Max", 0.0, 0.0, 0.0)
);
final HBox hb = new HBox();
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage stage)
{
Scene scene = new Scene(new Group());
// load css
// scene.getStylesheets().addAll(getClass().getResource("application.css").toExternalForm());
stage.setTitle("Table View Sample");
stage.setWidth(250);
stage.setHeight(550);
// setup table columns
setupMainTableColumns();
setupSumTableColumns();
// fill tables with data
mainTable.setItems(data);
sumTable.setItems(sumData);
// set dimensions
sumTable.setPrefHeight(90);
// bind/sync tables
for (int i = 0; i < mainTable.getColumns().size(); i++)
{
TableColumn<Data, ?> mainColumn = mainTable.getColumns().get(i);
TableColumn<SumData, ?> sumColumn = sumTable.getColumns().get(i);
// sync column widths
sumColumn.prefWidthProperty().bind(mainColumn.widthProperty());
// sync visibility
sumColumn.visibleProperty().bindBidirectional(mainColumn.visibleProperty());
}
// allow changing of column visibility
//mainTable.setTableMenuButtonVisible(true);
// hide header (variation of jewelsea's solution: http://stackoverflow.com/questions/12324464/how-to-javafx-hide-background-header-of-a-tableview)
sumTable.getStyleClass().add("tableview-header-hidden");
// hide horizontal scrollbar via styles
// sumTable.getStyleClass().add("sumtable");
// create container
BorderPane bp = new BorderPane();
Button addButton = new Button("+");
Button clearButton = new Button("X");
addButton.setOnAction((ActionEvent c) ->
{
data.add(new Data(LocalDate.of(2015, Month.JANUARY, 11), 40.0, 50.0, 60.0));
});
clearButton.setOnAction((ActionEvent c) ->
{
data.clear();
});
HBox buttonBar = new HBox(clearButton, addButton);
bp.setTop(buttonBar);
bp.setCenter(mainTable);
bp.setBottom(sumTable);
// fit content
bp.prefWidthProperty().bind(scene.widthProperty());
bp.prefHeightProperty().bind(scene.heightProperty());
((Group) scene.getRoot()).getChildren().addAll(bp);
stage.setScene(scene);
stage.show();
// synchronize scrollbars (must happen after table was made visible)
ScrollBar mainTableHorizontalScrollBar = findScrollBar(mainTable, Orientation.HORIZONTAL);
ScrollBar sumTableHorizontalScrollBar = findScrollBar(sumTable, Orientation.HORIZONTAL);
mainTableHorizontalScrollBar.valueProperty().bindBidirectional(sumTableHorizontalScrollBar.valueProperty());
}
/**
* Primary table column mapping.
*/
private void setupMainTableColumns()
{
TableColumn<Data, LocalDate> dateCol = new TableColumn<>("Date");
dateCol.setPrefWidth(120);
dateCol.setCellValueFactory(new PropertyValueFactory<>("date"));
TableColumn<Data, Double> value1Col = new TableColumn<>("Value 1");
value1Col.setPrefWidth(90);
value1Col.setCellValueFactory(new PropertyValueFactory<>("value1"));
value1Col.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.RIGHT));
TableColumn<Data, Double> value2Col = new TableColumn<>("Value 2");
value2Col.setPrefWidth(90);
value2Col.setCellValueFactory(new PropertyValueFactory<>("value2"));
value2Col.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.RIGHT));
TableColumn<Data, Double> value3Col = new TableColumn<>("Value 3");
value3Col.setPrefWidth(90);
value3Col.setCellValueFactory(new PropertyValueFactory<>("value3"));
value3Col.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.RIGHT));
mainTable.getColumns().addAll(dateCol, value1Col, value2Col, value3Col);
}
/**
* Summary table column mapping.
*/
private void setupSumTableColumns()
{
TableColumn<SumData, String> textCol = new TableColumn<>("Text");
textCol.setCellValueFactory(new PropertyValueFactory<>("text"));
TableColumn<SumData, Double> value1Col = new TableColumn<>("Value 1");
value1Col.setCellValueFactory(new PropertyValueFactory<>("value1"));
value1Col.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.RIGHT));
TableColumn<SumData, Double> value2Col = new TableColumn<>("Value 2");
value2Col.setCellValueFactory(new PropertyValueFactory<>("value2"));
value2Col.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.RIGHT));
TableColumn<SumData, Double> value3Col = new TableColumn<>("Value 3");
value3Col.setCellValueFactory(new PropertyValueFactory<>("value3"));
value3Col.setCellFactory(new FormattedTableCellFactory<>(TextAlignment.RIGHT));
sumTable.getColumns().addAll(textCol, value1Col, value2Col, value3Col);
}
/**
* Find the horizontal scrollbar of the given table.
*
* #param table
* #return
*/
private ScrollBar findScrollBar(TableView<?> table, Orientation orientation)
{
// this would be the preferred solution, but it doesn't work. it always gives back the vertical scrollbar
// return (ScrollBar) table.lookup(".scroll-bar:horizontal");
//
// => we have to search all scrollbars and return the one with the proper orientation
Set<Node> set = table.lookupAll(".scroll-bar");
for (Node node : set)
{
ScrollBar bar = (ScrollBar) node;
if (bar.getOrientation() == orientation)
{
return bar;
}
}
return null;
}
/**
* Data for primary table rows.
*/
public static class Data
{
private final ObjectProperty<LocalDate> date;
private final SimpleDoubleProperty value1;
private final SimpleDoubleProperty value2;
private final SimpleDoubleProperty value3;
public Data(LocalDate date, double value1, double value2, double value3)
{
this.date = new SimpleObjectProperty<LocalDate>(date);
this.value1 = new SimpleDoubleProperty(value1);
this.value2 = new SimpleDoubleProperty(value2);
this.value3 = new SimpleDoubleProperty(value3);
}
public final ObjectProperty<LocalDate> dateProperty()
{
return this.date;
}
public final LocalDate getDate()
{
return this.dateProperty().get();
}
public final void setDate(final LocalDate date)
{
this.dateProperty().set(date);
}
public final SimpleDoubleProperty value1Property()
{
return this.value1;
}
public final double getValue1()
{
return this.value1Property().get();
}
public final void setValue1(final double value1)
{
this.value1Property().set(value1);
}
public final SimpleDoubleProperty value2Property()
{
return this.value2;
}
public final double getValue2()
{
return this.value2Property().get();
}
public final void setValue2(final double value2)
{
this.value2Property().set(value2);
}
public final SimpleDoubleProperty value3Property()
{
return this.value3;
}
public final double getValue3()
{
return this.value3Property().get();
}
public final void setValue3(final double value3)
{
this.value3Property().set(value3);
}
}
/**
* Data for summary table rows.
*/
public static class SumData
{
private final SimpleStringProperty text;
private final SimpleDoubleProperty value1;
private final SimpleDoubleProperty value2;
private final SimpleDoubleProperty value3;
public SumData(String text, double value1, double value2, double value3)
{
this.text = new SimpleStringProperty(text);
this.value1 = new SimpleDoubleProperty(value1);
this.value2 = new SimpleDoubleProperty(value2);
this.value3 = new SimpleDoubleProperty(value3);
}
public final SimpleStringProperty textProperty()
{
return this.text;
}
public final java.lang.String getText()
{
return this.textProperty().get();
}
public final void setText(final java.lang.String text)
{
this.textProperty().set(text);
}
public final SimpleDoubleProperty value1Property()
{
return this.value1;
}
public final double getValue1()
{
return this.value1Property().get();
}
public final void setValue1(final double value1)
{
this.value1Property().set(value1);
}
public final SimpleDoubleProperty value2Property()
{
return this.value2;
}
public final double getValue2()
{
return this.value2Property().get();
}
public final void setValue2(final double value2)
{
this.value2Property().set(value2);
}
public final SimpleDoubleProperty value3Property()
{
return this.value3;
}
public final double getValue3()
{
return this.value3Property().get();
}
public final void setValue3(final double value3)
{
this.value3Property().set(value3);
}
}
/**
* Formatter for table cells: allows you to align table cell values
* left/right/center
*
* Example for alignment form
* http://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm
*
* #param <S>
* #param <T>
*/
public static class FormattedTableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>>
{
private TextAlignment alignment = TextAlignment.LEFT;
private Format format;
public FormattedTableCellFactory()
{
}
public FormattedTableCellFactory(TextAlignment alignment)
{
this.alignment = alignment;
}
public TextAlignment getAlignment()
{
return alignment;
}
public void setAlignment(TextAlignment alignment)
{
this.alignment = alignment;
}
public Format getFormat()
{
return format;
}
public void setFormat(Format format)
{
this.format = format;
}
#Override
#SuppressWarnings("unchecked")
public TableCell<S, T> call(TableColumn<S, T> p)
{
TableCell<S, T> cell = new TableCell<S, T>()
{
#Override
public void updateItem(Object item, boolean empty)
{
if (item == getItem())
{
return;
}
super.updateItem((T) item, empty);
if (item == null)
{
super.setText(null);
super.setGraphic(null);
} else if (format != null)
{
super.setText(format.format(item));
} else if (item instanceof Node)
{
super.setText(null);
super.setGraphic((Node) item);
} else
{
super.setText(item.toString());
super.setGraphic(null);
}
}
};
cell.setTextAlignment(alignment);
switch (alignment)
{
case CENTER:
cell.setAlignment(Pos.CENTER);
break;
case RIGHT:
cell.setAlignment(Pos.CENTER_RIGHT);
break;
default:
cell.setAlignment(Pos.CENTER_LEFT);
break;
}
return cell;
}
}
}
No solution (which probably would require some real work in the bowels of VirtualFlow and/or TableViewSkin) but a dirty trick: add/remove data after wiring the scrollBars
addButton.fire();
Platform.runLater(( ) -> {
clearButton.fire();
});
The drawback is a short but perceptible flicker ...
Update
After a bit of digging ("geht-nicht-gibt's-nicht" - don't know the English idiom, sry) I found a way to force the VirtualFlow into an initial layout pass even if there are no items: the basic idea is to temporarily set the flow's cellCount > 0 even if there are no items. The tricky part is to do it at the right time in the skin's life: only once, sometime early but only after the normal layout has happened.
The implementation below
has a flag to indicate whether or not to fake the itemCount
sets the flag in a listener to the containing window's showing property: this assumes a normal setting of the default skin while being added to the scenegraph
overridden getItemCount to return at least 1 if the flag is set
overridden layoutChildren that forces a fake layout if the flag is set
the forced layout is achieved by calling updateItemCount twice: once with and once without flag
Still dirty, but more fun :)
public static class TweakedTableSkin<T> extends TableViewSkin<T> {
private boolean forceNotEmpty = false;
ChangeListener showingListener = (src, ov, nv) -> {
initForceNotEmpty(src);
};
public TweakedTableSkin(TableView<T> control) {
super(control);
Window window = getSkinnable().getScene().getWindow();
if (window != null)
window.showingProperty().addListener(showingListener);
}
/**
* Overridden to force a re-layout with faked itemCount after calling
* super if the fake flag is true.
*/
#Override
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
if (forceNotEmpty) {
forceNotEmptyLayout();
}
}
/**
* Callback from listener installed on window's showing property.
* Implemented to set the forceNotEmpty flag and remove the listener.
*/
private void initForceNotEmpty(ObservableValue src) {
forceNotEmpty = true;
src.removeListener(showingListener);
}
/**
* Enforces a layout pass on the flow with at least one row.
* Resets the forceNotEmpty flag and triggers a second
* layout pass with the correct count.
*/
private void forceNotEmptyLayout() {
if (!forceNotEmpty) return;
updateItemCount();
forceNotEmpty = false;
updateItemCount();
}
/**
* Overridden to return at least 1 if forceNotEmpty is true.
*/
#Override
protected int getItemCount() {
int itemCount = super.getItemCount();
if (forceNotEmpty && itemCount == 0) {
itemCount = 1;
}
return itemCount;
}
}
Usage by extending TableView with an overridden createDefaultSkin:
private TableView<Data> mainTable = new TableView<>() {
#Override
protected Skin<?> createDefaultSkin() {
return new TweakedTableSkin<>(this);
}
};
You can copy the search in combobox test run and after the filter selected it still get the original value.
You can see my code and complete the data received after the data filtering help me, more than a week searching but could not do it. hope you help. Thank you very much
Form.java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.JTextField;
public class Form implements Runnable {
private static JFrame frame;
private static DetailedComboBox combo;
private static JTextField textField;
private static DetailedComboBox comboLop;
private static JTextField textField2;
/**
* #wbp.parser.entryPoint
*/
#Override
public void run() {
// TODO Auto-generated method stub
List<List<?>> tableData = new ArrayList<List<?>>();
tableData.add(new ArrayList<String>(
Arrays.asList("0","Nam", "Phan Nam", "1")));
tableData.add(new ArrayList<String>(
Arrays.asList( "1","Long", "Dinh Hoang Long", "2")));
tableData.add(new ArrayList<String>(
Arrays.asList( "3","Luc", "Phan Cong Luc", "4")));
tableData.add(new ArrayList<String>(
Arrays.asList( "4","Hoang", "Tran Hoang", "5")));
String[] columns = new String[]{"ID","Name", "Full Name", "Capital"};
int[] widths = new int[]{0,80, 200, 100};
combo = new DetailedComboBox(columns, widths, 0);
combo.setEditable(true);
// comboNhanVien.setEditable(true);
combo.setBounds(58, 50, 154, 23);
combo.setTableData(tableData);
combo.setSelectedIndex(-1);
combo.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
combo.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDetails();
}
});
/* combo.getEditor().getEditorComponent().addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent arg0) {
combo.showPopup();
combo.hidePopup();
}
#Override
public void focusLost(FocusEvent arg0) {
//combo.hidePopup();
}
});*/
combo.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
System.out.print(e.getKeyCode());
String value= combo.getEditor().getItem().toString();
if (value.trim().length() == 0 && e.getKeyCode() != 40) {
combo.hidePopup();
// System.out.print(e.getKeyCode());
}else {
combo.showPopup();
//System.out.print("X: "+e.getKeyCode());
}
}
});
List<List<?>> tableDataLop = new ArrayList<List<?>>();
tableDataLop.add(new ArrayList<String>(
Arrays.asList("0","Class A")));
tableDataLop.add(new ArrayList<String>(
Arrays.asList("1","Class B")));
String[] columnsLop = new String[]{"ID","Class"};
int[] widthsLop = new int[]{0,100};
comboLop = new DetailedComboBox(columnsLop, widthsLop, 0);
comboLop.setEditable(true);
// comboNhanVien.setEditable(true);
comboLop.setBounds(58, 50, 154, 23);
comboLop.setTableData(tableDataLop);
comboLop.setSelectedIndex(-1);
comboLop.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
comboLop.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDetailsLop();
}
});
comboLop.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
System.out.print(e.getKeyCode());
String value= comboLop.getEditor().getItem().toString();
if (value.trim().length() == 0 && e.getKeyCode() != 40) {
comboLop.hidePopup();
// System.out.print(e.getKeyCode());
}else {
comboLop.showPopup();
//System.out.print("X: "+e.getKeyCode());
}
}
});
comboLop.setEditable(true);
comboLop.setBounds(58, 94, 154, 23);
JPanel p = new JPanel();
p.setLayout(null);
p.add(combo);
p.add(comboLop);
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(p, BorderLayout.CENTER);
p.add(getTextField());
p.add(getTextField2());
//frame.getContentPane().setLayout(null);
//frame.getContentPane().add(comboNhanVien);
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
/**
* Launch the application.
*/
/**
* Create the application.
*/
private static void showDetails()
{
List<? extends Object> rowData = combo.getSelectedRow();
textField.setText(rowData.get(1).toString());
// capital.setText(rowData.get(2).toString());
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Form());
}
private JTextField getTextField() {
if (textField == null) {
textField = new JTextField();
textField.setBounds(234, 52, 86, 20);
textField.setColumns(10);
}
return textField;
}
private JTextField getTextField2() {
if (textField2 == null) {
textField2 = new JTextField();
textField2.setColumns(10);
textField2.setBounds(234, 96, 86, 20);
}
return textField2;
}
private static void showDetailsLop()
{
List<? extends Object> rowData = comboLop.getSelectedRow();
textField2.setText(rowData.get(1).toString());
// capital.setText(rowData.get(2).toString());
}
}
and DetailedComboBox.java
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;
import javax.swing.table.*;
/**
* A JComboBox that has a JTable as a drop-down instead of a JList
*/
#SuppressWarnings({ "rawtypes", "serial" })
public class DetailedComboBox extends JComboBox
{
public static enum Alignment {LEFT, RIGHT}
private List<List<? extends Object>> tableData;
private String[] columnNames;
private int[] columnWidths;
private Alignment popupAlignment = Alignment.LEFT;
/**
* Construct a TableComboBox object
*/
public DetailedComboBox(String[] colNames, int[] colWidths,
int displayColumnIndex)
{
super();
this.columnNames = colNames;
this.columnWidths = colWidths;
setUI(new TableComboBoxUI());
setEditable(false);
}
/**
* Set the type of alignment for the popup table
*/
public void setPopupAlignment(Alignment alignment)
{
popupAlignment = alignment;
}
/**
* Populate the combobox and drop-down table with the supplied data.
* If the supplied List is non-null and non-empty, it is assumed that
* the data is a List of Lists to be used for the drop-down table.
* The combobox is also populated with the column data from the
* column defined by <code>displayColumn</code>.
*/
#SuppressWarnings("unchecked")
public void setTableData(List<List<? extends Object>> tableData)
{
this.tableData = (tableData == null ?
new ArrayList<List<? extends Object>>() : tableData);
// even though the incoming data is for the table, we must also
// populate the combobox's data, so first clear the previous list.
removeAllItems();
// then load the combobox with data from the appropriate column
Iterator<List<? extends Object>> iter = this.tableData.iterator();
while (iter.hasNext())
{
List<? extends Object> rowData = iter.next();
// System.out.print(rowData.get(1));
addItem(rowData.get(1));
// addItem(rowData.get(displayColumn));
}
}
public List<? extends Object> getSelectedRow()
{
List<? extends Object> data = null;
if(tableData.get(getSelectedIndex()) != null){
data=tableData.get(getSelectedIndex());
}
System.out.println(data);
return data;
}
/**
* The handler for the combobox's components
*/
private class TableComboBoxUI extends MetalComboBoxUI
{
/**
* Create a popup component for the ComboBox
*/
#Override
protected ComboPopup createPopup()
{
return new TableComboPopup(comboBox, this);
}
/**
* Return the JList component
*/
public JList getList()
{
return listBox;
}
}
/**
* The drop-down of the combobox, which is a JTable instead of a JList.
*/
private class TableComboPopup extends BasicComboPopup
implements ListSelectionListener, ItemListener
{
/**
*
*/
private static final long serialVersionUID = 1L;
private final JTable table;
private TableComboBoxUI comboBoxUI;
private PopupTableModel tableModel;
private JScrollPane scroll;
// private JList list = new JList();
// private ListSelectionListener selectionListener;
// private ItemListener itemListener;
private void selectRow()
{
int index = comboBox.getSelectedIndex();
if (index != -1)
{
int idc=table.getRowCount();
if(idc>0){
//System.out.println("idc "+idc);
//table.setRowSelectionInterval(index, index);
//table.scrollRectToVisible(table.getCellRect(index, 0, true));
}
}
}
/**
* Construct a popup component that's a table
*/
public TableComboPopup(JComboBox combo, TableComboBoxUI ui)
{
super(combo);
this.comboBoxUI = ui;
tableModel = new PopupTableModel();
table = new JTable(tableModel);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
TableColumnModel tableColumnModel = table.getColumnModel();
tableColumnModel.setColumnSelectionAllowed(false);
for (int index = 0; index < table.getColumnCount(); index++)
{
TableColumn tableColumn = tableColumnModel.getColumn(index);
tableColumn.setPreferredWidth(columnWidths[index]);
}
table.removeColumn(table.getColumnModel().getColumn(0));
scroll = new JScrollPane(table);
scroll.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
selectionModel.addListSelectionListener(this);
combo.addItemListener(this);
table.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent event)
{
// java.awt.Point p = event.getPoint();
// int row = table.rowAtPoint(p);
//int row = table.convertRowIndexToModel(table.getEditingRow());
//System.out.println("row 2: "+row);
/// comboBox.setSelectedIndex(row);
//comboBox.getEditor().setItem("Text Has Changed");
hide();
}
});
table.setBackground(UIManager.getColor("ComboBox.listBackground"));
table.setForeground(UIManager.getColor("ComboBox.listForeground"));
}
/**
* This method is overridden from BasicComboPopup
*/
#Override
public void show()
{
if (isEnabled())
{
super.removeAll();
int scrollWidth = table.getPreferredSize().width +
((Integer) UIManager.get("ScrollBar.width")).intValue() + 1;
int scrollHeight = comboBoxUI.getList().
getPreferredScrollableViewportSize().height;
scroll.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
super.add(scroll);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(this);
selectRow();
selectionModel.addListSelectionListener(this);
int scrollX = 0;
int scrollY = comboBox.getBounds().height;
if (popupAlignment == Alignment.RIGHT)
{
scrollX = comboBox.getBounds().width - scrollWidth;
}
show(comboBox, scrollX, scrollY);
// table.setRowSelectionInterval(0, 0);
comboBox.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
String value= comboBox.getEditor().getItem().toString();
//System.out.println("value: " +value);
TableRowSorter<TableModel> rowSorter
= new TableRowSorter<>(table.getModel());
table.setRowSorter(rowSorter);
if (value.trim().length() == 0) {
rowSorter.setRowFilter(null);
table.setRowSelectionInterval(0, 0);
}else {
rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + value,1));
int index = comboBox.getSelectedIndex();
if (index != -1)
{
int idc=table.getRowCount();
if(idc>0){
//System.out.println("idc "+idc);
//table.setRowSelectionInterval(index, index);
//table.scrollRectToVisible(table.getCellRect(index, 0, true));
}
}
}
}
});
}
}
/**
* Implemention of ListSelectionListener
*/
public void valueChanged(ListSelectionEvent event)
{
int index = table.getSelectedRow();
int row = table.convertRowIndexToView(table.getEditingRow());
System.out.println("B "+row);
if (index != -1)
{
//System.out.print("B "+index);
comboBox.setSelectedIndex(table.getSelectedRow());
}
}
#Override
public void itemStateChanged(ItemEvent arg0) {
// TODO Auto-generated method stub
}
}
/**
* A model for the popup table's data
*/
private class PopupTableModel extends AbstractTableModel
{
/**
* Return the # of columns in the drop-down table
*/
public int getColumnCount()
{
return columnNames.length;
}
/**
* Return the # of rows in the drop-down table
*/
public int getRowCount()
{
return tableData == null ? 0 : tableData.size();
}
/**
* Determine the value for a given cell
*/
public Object getValueAt(int row, int col)
{
if (tableData == null || tableData.size() == 0)
{
return "";
}
return tableData.get(row).get(col);
}
/**
* All cells in the drop-down table are uneditable
*/
#Override
public boolean isCellEditable(int row, int col)
{
return false;
}
/**
* Pull the column names out of the tableInfo object for the header
*/
#Override
public String getColumnName(int column)
{
String columnName = null;
if (column >= 0 && column < columnNames.length)
{
columnName = columnNames[column].toString();
}
return (columnName == null) ? super.getColumnName(column) : columnName;
}
}
}
You need to be aware of the model/view index relationship between the combo box, table and model.
Your combo box will always have all the entries so its index is equivalent to the model index.
The table may be filtered or not so you need to convert its index to the model index so you can set the combo box index.
If I understand what you are attempting to do then this is the change I made to your valueChanged() method:
public void valueChanged(ListSelectionEvent event)
{
int index = table.getSelectedRow();
if (index != -1)
{
int row = table.convertRowIndexToModel(index);
comboBox.setSelectedIndex(row);
}
}
I have a program that creates a dynamic amount of jpanels and components based on selection at the start of the program that is user-defined. having said that each jpanel and component is created with a loop making them all the same, and they are then put into a list (the JPanel's are put into a list).
Having said that I have been able to get the jpanel out and then grab the componenets and display them using System.out. but they are in a component object. How can I get the values of the components? Or am I doing this wrong?
Basically I am trying to have the tabs/jpanels based on user-definition automatically generate, which works. Then the user fills out some information and hits "Generate" which is where I then need to iterate through the tabs/jpanels/componenents and put them into the correct object.
Below is a working example of my program in a simplified for, with less tyteps of tabs (I only let the AP tab be created) and less options for the object classes:
There are two object classes APObject is extending Generic Object. MVCE is the start of the main program where it asks you a few user-defined questions which generate the Tabs/Panels. It then goes from InfoGathering.java to DataGathering where it creates the tabs and panels. The GenerateActionPerformed(ActionEvent evt) method is where I am trying to grab the information from the panel components and put them into the APObject or whichever object they need to go into.
MVCE:
public class MVCE extends javax.swing.JFrame {
int numGenerate[];
private javax.swing.JComboBox cb;
/**
* Creates new form MVCE
*/
public MVCE() {
this.numGenerate = new int[3];
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jComboBox1 = new javax.swing.JComboBox();
jComboBox2 = new javax.swing.JComboBox();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "2", "3", "4", "5" }));
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox1ActionPerformed(evt);
}
});
jComboBox2.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "2", "3", "4", "5" }));
jComboBox2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox2ActionPerformed(evt);
}
});
jLabel1.setText("How many switches?");
jLabel2.setText("APS");
jButton1.setText("Create Button");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1)
.addComponent(jLabel2)
.addComponent(jButton1))
.addContainerGap(264, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(15, 15, 15)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jButton1)
.addContainerGap(140, Short.MAX_VALUE))
);
jLabel1.getAccessibleContext().setAccessibleName("How many switches");
pack();
}// </editor-fold>
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
this.setVisible(false);
InfoGathering Info = new InfoGathering(numGenerate);
}
private void jComboBox2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
cb = (javax.swing.JComboBox)evt.getSource();
String APNumber = (String)cb.getSelectedItem();
//System.out.println(APNumber + "AP Number");
numGenerate[1] = Integer.valueOf(APNumber);
}
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
cb = (javax.swing.JComboBox)evt.getSource();
String APNumber = (String)cb.getSelectedItem();
//System.out.println(APNumber + "AP Number");
numGenerate[0] = Integer.valueOf(APNumber);
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MVCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MVCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MVCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MVCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MVCE().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JComboBox jComboBox1;
private javax.swing.JComboBox jComboBox2;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
// End of variables declaration
}
INFOGATHERING:
public class InfoGathering {
//public int infoVariables[];
public InfoGathering(int[] infoVars) {
startInfo(infoVars);
}
private void startInfo(int[] infoVars) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DataGathering(infoVars).setVisible(true);
}
});
}
//End of clss below
}
DATAGATHERING:
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author kmalik
*/
public class DataGathering extends javax.swing.JFrame {
private int infoVariables[];
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel OuterPane;
//SwitchObject SWOb[] = new SwitchObject[30];
//APObject APOb[] = new APObject[30];
//ControllerObject CoOb[] = new ControllerObject[1];
//int devicesArrayCountSW = 0;
//int devicesArrayCountAP = 0;
//int devicesArrayCountCO = 0;
/**
* Creates new form DataGathering
* #param intVars
*/
public DataGathering(int[] intVars) {
infoVariables = Arrays.copyOf(intVars, intVars.length);
initComponents();
initDynamic();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jTabbedPane1 = new javax.swing.JTabbedPane();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new java.awt.GridLayout(1, 0));
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
private void initDynamic() {
OuterPane = new javax.swing.JPanel();
getContentPane().add(OuterPane);
OuterPane.add(jTabbedPane1);
JButton GenerateCode = new JButton("Generate Code");
OuterPane.setLayout(new BoxLayout(OuterPane, BoxLayout.Y_AXIS));
OuterPane.add(GenerateCode);
GenerateCode.addActionListener(new java.awt.event.ActionListener() {
private APObject Aobj;
private JPanel jobj;
private Component Components[];
private Component components;
public void actionPerformed(java.awt.event.ActionEvent evt) {
GenerateActionPerformed(evt);
}
private void GenerateActionPerformed(ActionEvent evt) {
//To change body of generated methods, choose Tools | Templates.
for(int i = 0; apList.size() > i; i++) {
//jobj = (JPanel) jList.get(i);
//System.out.println(jobj
Aobj = apList.get(i);
jobj = jList.get(i);
Components = jobj.getComponents();
System.out.println(Components + " Componenets of first panel");
for (int a=0; a < Components.length; a++) {
components = jobj.getComponent(a);
System.out.println(components);
if (Components[a] instanceof JComboBox) {
}
}
}
}
});
int SwitchCount = 1 , APCount = 1,CoCount = 1;
//String jp;
//need public# of switches, APs and controllers
for(int devicesCount =0;devicesCount < infoVariables.length;devicesCount++) {
if (devicesCount == 2 && infoVariables[devicesCount] == 1) {
createTab(CoCount, devicesCount);
}
for(int b=0; b < infoVariables[devicesCount]; b++) {
if (devicesCount == 0) {
//SWITCHES DYNAMICALLY CREATE
createTab(SwitchCount,devicesCount);
SwitchCount++;
} else if (devicesCount==1) {
//AP DYNAMICALLY CREATE
createTab(APCount,devicesCount);
APCount++;
} //end of full if loop
} //end of for loop
} // end of outer for loop
}
private javax.swing.JTabbedPane jTabbedPane1;
//ArrayList<SwitchObject> swList = new ArrayList<>();
ArrayList<APObject> apList = new ArrayList<>();
//ArrayList<ControllerObject> coList = new ArrayList<>();
ArrayList<JPanel> jList = new ArrayList<>();
private void createTab(int z,int y) {
if (y==0) {
//CREATE SWITCH TAB/PANEL
} else if (y==1) {
JPanel jp = new JPanel();
jTabbedPane1.addTab("AP_"+z,jp);
jp.setName("AP"+z);
APObject APOb = new APObject(jp.getName(), z);
apList.add(APOb);
jList.add(jp);
setLayout(new FlowLayout());
//Add Type of Device Checkbox
String[] apListName = {"APExample1","APExample2"};
JComboBox apListChkBox = new JComboBox(apListName);
jp.add(apListChkBox);
//Add NasID of Device with Label
JLabel apnasIDLabel = new JLabel("AP ID");
String apnasID;
JTextField apnasIDComboBox = new JTextField();
apnasIDComboBox.setColumns(9);
jp.add(apnasIDLabel);
jp.add(apnasIDComboBox);
//SNMP Location
JLabel apLocLabel = new JLabel("Location");
String apLoc;
JTextField apLocComboBox = new JTextField();
apLocComboBox.setColumns(9);
jp.add(apLocLabel);
jp.add(apLocComboBox);
jp.setBorder(BorderFactory.createLineBorder(Color.black));
this.pack();
} else if (y == 2) {
//CREATE CONTROLLER TAB/PANEL
}
}
}
APOBJECT:
public class APObject extends GenericObject {
private int channelScheme;
APObject(String x, int y) {
super(x,y);
}
//ip scheme box/subnet box get/set
//location get/set
//channel scheme get/set
private void setChannelScheme(int x) {
channelScheme = x;
}
private int getChannelScheme() {
return channelScheme;
}
}
GENERICOBJECT:
public class GenericObject {
private int telephone;
private String ipScheme;
private String Location;
public String DName;
public int getTelephone() {
return telephone;
}
protected void setTelephone(int x) {
telephone = x;
}
protected String getipScheme() {
return ipScheme;
}
protected void setipScheme(String x) {
ipScheme = x;
}
protected String getLocation() {
return Location;
}
protected void setLocation(String x) {
Location = x;
}
public GenericObject (String SName, int Tab) {
DName = SName;
int TabNum = Tab;
}
}
I'm having a problem in adding my swf file to my jframe. They say that i should try the JFlashplayer but it is only a trial one. Can you give me some sample code for this?
Here is my flash player adapted from the example on their website. BCFrame is essentially a JInternalFrame. You can have it extend whatever. It will need slight modification to work, but should be strait forward. You can rip out anything that doesnt exist.
Other possible solutions are:
jffmpeg - do a search for it
http://www.humatic.de/htools/dsj/samplecode.php?WebM.java
http://code.google.com/p/gstreamer-java/
http://www.xuggle.com/xuggler/
http://www.theregister.co.uk/2010/08/20/flash_in_java/
package Components.FlashPlayer;
import Components.BCFrame;
import GUI.BCApp.DataTypeEnum;
import Logging.LogRunner;
import Properties.Basic.FlashPlayer_Prop;
import XMLProcessing.Helpers.XMLActionInfoHolder;
import XMLProcessing.XMLUtilities;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
// import the JFlashPlayer package
import com.jpackages.jflashplayer.*;
import java.net.URL;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* This class plays a flash video.
* Create with help from: http://www.jpackages.com/jflashplayer , see the website
* for a larger example of how to do more things with this code. I kind of modified
* this to fit the current needs of the project. This works in conjunction with
* dlls that need to go in the win32 folder. For linux/mac, look into the Apple
* Java Quicktime API
* #author dvargo
*/
public class FlashPlayer extends BCFrame implements FlashPanelListener {
/**
* handle to a FlashPanel instance
*/
FlashPanel flashPanel;
final Label currentFrameLabel = new Label("Frame: N/A");
final JProgressBar progressBar = new JProgressBar();
JButton playButton,stopButton,forwardButton,rewindButton,backButton;
JCheckBox loopCheckBox;
private boolean isMovieSet = false;
FrameMonitorThread fmt;
boolean loop = false;
boolean playOnStart = true;
public enum Actions
{
Loop,
Stop,
Play
}
/**
* Defualt constructor
*/
public FlashPlayer()
{
}
/**
* Sets FlashPlayer to defualt size
* #param x X position for the player
* #param y Y position for the player
* #param mainWindow Reference to the main window
*/
public FlashPlayer(int x, int y, GUI.Window mainWindow) {
this(x, y, 600, 400, mainWindow);
}
/**
* Full consturtor
* #param x X position for this player
* #param y Y position for this player
* #param w Width of the player
* #param h Height of the player
* #param mainWindow reference to the main window
*/
public FlashPlayer(int x, int y, int w, int h, GUI.Window mainWindow) {
super(x, y, w, h, mainWindow);
initComponents();
this.getContentPane().setLayout(new BorderLayout());
createButtons();
addCurrCompSetter(flashPanel,progressBar,currentFrameLabel,playButton,stopButton,forwardButton,rewindButton,loopCheckBox,backButton);
}
#SuppressWarnings("unchecked")
//
private void initComponents() {
videoPanel = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
videoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
javax.swing.GroupLayout videoPanelLayout = new javax.swing.GroupLayout(videoPanel);
videoPanel.setLayout(videoPanelLayout);
videoPanelLayout.setHorizontalGroup(
videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 381, Short.MAX_VALUE)
);
videoPanelLayout.setVerticalGroup(
videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 247, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}//
// Variables declaration - do not modify
private javax.swing.JPanel videoPanel;
// End of variables declaration
/**
* FlashPanelListener event method which receives FSCommand Flash events.
*
* You should use ExternalInterface.call instead of FSCommand
* with the latest ActionScript version. Older ActionScript versions
* will only have access to FSCommand.
*/
public void FSCommand(String command, String arg) {
System.out.println("FlashPlayer (ignoring): FSCommand event received: " + command + " " + arg);
}
private void creatFlashPlayerWorker()
{
// add the FlashPanel to the frame
this.getContentPane().add(flashPanel, BorderLayout.CENTER);
// specify the object for Flash ExternalInterface.call events to search for the called method on
flashPanel.setFlashCallObject(this);
// specify the FlashPanelListener in case a movie is using the older FSCommand event
flashPanel.addFlashPanelListener(this);
// specify variables for a flash movie which are available from the start of the
// movie as long as this is called before the FlashPanel is visible
flashPanel.setVariables("myGreeting=hi&myNumber=1&myVar=good%20job");
isMovieSet = true;
centerAndDisplay();
fmt = new FrameMonitorThread(flashPanel);
fmt.start();
revalidate();
if(!playOnStart)
{
stop();
}
setLoop(loop);
}
/**
* Create a FlashPanel instance and add it to the frame
*/
public void createFlashPanel(String url) {
// install Flash 10 if Flash 6 or greater is not present
//FlashPanel.installFlash("6");
dataSource = dataSource.url;
setData("Path",url.toString());
String flashVersionRequired = "9";
try
{
FlashPanel.setRequiredFlashVersion(flashVersionRequired);
flashPanel = new FlashPanel(new URL(url));//new File(flashFilePath));
}
catch (JFlashLibraryLoadFailedException e)
{
exitError("A required library (DLL) is missing or damaged.");
}
catch(JFlashInvalidFlashException e)
{
exitError("Required version " + flashVersionRequired + " of Flash is not installed. ");
}
catch (Exception e)
{
exitError("Something went wrong!\n" + e.toString());
}
creatFlashPlayerWorker();
}
/**
* Create a FlashPanel instance and add it to the frame
*/
public void createFlashPanel(File file) {
// install Flash 10 if Flash 6 or greater is not present
//FlashPanel.installFlash("6");
//http://samples.mplayerhq.hu/SWF/flash_adpcm_testfiles/stereo_22.swf
dataSource = dataSource.file;
setData("Path",file.getAbsolutePath());
String flashVersionRequired = "9";
try
{
FlashPanel.setRequiredFlashVersion(flashVersionRequired);
flashPanel = new FlashPanel(file);//new File(flashFilePath));
}
catch (JFlashLibraryLoadFailedException e)
{
exitError("A required library (DLL) is missing or damaged.");
}
catch(JFlashInvalidFlashException e)
{
exitError("Required version " + flashVersionRequired + " of Flash is not installed. ");
}
catch (Exception e)
{
exitError("Something went wrong!\n" + e.toString());
}
creatFlashPlayerWorker();
}
public boolean isMovieSet()
{
return isMovieSet;
}
public boolean isPlayOnStart()
{
return playOnStart;
}
public boolean isLoop()
{
return loop;
}
public void setPlayOnStart(boolean dis)
{
playOnStart = dis;
}
public void setIsLoop(boolean dis)
{
loop = dis;
}
/**
* Select a different SWF file at remote url
*/
public void setMovie(URL url)
{
if(!isMovieSet)
{
createFlashPanel(url.toString());
return;
}
setData("Path",url.toString());
dataSource = dataSource.url;
flashPanel.setMovie(url);
}
/**
* Select a different SWF file at remote url
*/
public void setMovie(String url)
{
if(!isMovieSet)
{
createFlashPanel(url);
return;
}
setData("Path",url);
dataSource = dataSource.url;
try
{
flashPanel.setMovie(new URL(url));
revalidate();
}
catch(Exception e)
{
LogRunner.dialogMessage(this.getClass(),"Could not play Flash Movie at " + url);
}
}
/**
* Select a different SWF file on local machine
*/
public void setMovie(File file)
{
setData("Path",file.getAbsolutePath()); //setting this to absolute path might cause a problem
dataSource = dataSource.file;
try
{
if(isMovieSet)
{
flashPanel.setMovie(file);
}
else
{
createFlashPanel(file);
}
}
catch(Exception e)
{
LogRunner.dialogMessage(this.getClass(),"Could not play Flash Movie at " + file);
}
}
/**
* Instruct the flash movie to play.
*/
public void play()
{
flashPanel.play();
}
/**
* Instruct the flash movie to stop playing.
*/
public void stop()
{
flashPanel.stop();
}
/**
* Instruct the flash movie to go back one frame.
* This will also stop the movie if it was playing.
*/
public void rewind()
{
rewind(1);
}
/**
* Instruct the flash movie to go back x number of frames.
* This will also stop the movie if it was playing.
* #param numberOfFrames The number of frames to rewind
*/
public void rewind(int numberOfFrames)
{
for(int i = 0; i < numberOfFrames; i++)
{
flashPanel.back();
}
}
/**
* Instruct the flash movie to go forward 1 frame.
* This will also stop the movie if it was playing.
*/
public void forward()
{
forward(1);
}
/**
* Instruct the flash movie to go forward x number of frame.
* This will also stop the movie if it was playing.
*/
public void forward(int numberOfFrames)
{
for(int i = 0; i < numberOfFrames; i++)
{
flashPanel.forward();
}
}
/**
* Instruct the flash movie to rewind to the first frame.
* This will also stop the movie if it was playing.
*/
public void goBackToBegining()
{
flashPanel.rewind();
}
/**
* Select and set the flash movie background color.
*/
public void backgroundAction(Color c)
{
flashPanel.setBackground(c);
}
/**
* Instruct the flash movie to loop or not.
*/
void setLoop(boolean loop) {
flashPanel.setLoop(loop);
}
/**
* Define some buttons to demonstrate JFlashPlayer functionality
*/
void createButtons() {
JPanel buttonPanel = new JPanel();
buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
playButton = new JButton("Play");
playButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
play();
}
});
buttonPanel.add(playButton);
JButton stopButton = new JButton("Pause");
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
stop();
}
});
buttonPanel.add(stopButton);
backButton = new JButton("Back");
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
goBackToBegining();
}
});
buttonPanel.add(backButton);
forwardButton = new JButton("Forward");
forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
forward();
}
});
//buttonPanel.add(forwardButton);
rewindButton = new JButton("Rewind");
rewindButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
rewind();
}
});
buttonPanel.add(rewindButton);
loopCheckBox = new JCheckBox("Loop");
loopCheckBox.setSelected(true);
loopCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setLoop(loopCheckBox.isSelected());
}
});
progressBar.setVisible(true);
buttonPanel.add(progressBar);
for (int i = 0; i screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
//this.setLocation((screenSize.width - frameSize.width) / 2,
// (screenSize.height - frameSize.height) / 2);
this.setVisible(true);
//this.toFront();
}
#Override
protected void createProperties()
{
properties = new FlashPlayer_Prop(this);
}
#Override
public void action(Enum a)
{
}
#Override
public Enum convertStringToActionEnumValue(String in) {
return null;
}
#Override
public void build(HashMap theDictionary, String filePath, String DataSource, ArrayList actions)
{
if(DataSource.equals(DataTypeEnum.url.toString()))
{
createFlashPanel((String) theDictionary.get("Path"));
setDataSource(DataTypeEnum.url);
}
else
{
String theFile = XMLUtilities.parseFilePath(filePath) + File.separator + (String) theDictionary.get("Path");
createFlashPanel(new File(theFile));
setDataSource(DataTypeEnum.file);
}
playOnStart = Boolean.parseBoolean(theDictionary.get("PlayOnStart"));
loop = Boolean.parseBoolean(theDictionary.get("Loop"));
//add actions to the component
setActions(XMLUtilities.getActions(this, actions));
}
#Override
public Element extractData(Document dom)
{
setData("PlayOnStart",Boolean.toString(playOnStart));
setData("Loop", Boolean.toString(loop));
return super.extractData(dom);
}
#Override
public File[] extractFiles(String filePath)
{
File retVal = new File(getData("Path"));
if(retVal == null)
{
return null;
}
setData("Path","files" + File.separator + retVal.getName());
return new File[]{retVal};
}
#Override
public void drag(File[] theFiles)
{
//if they dragged a one file in
if(theFiles.length == 1)
{
//try and set it as the image of this component
setMovie(new File(theFiles[0].getAbsolutePath()));
}
//they dragged multiple files in
else
{
for(int i = 0; i < theFiles.length; i++)
{
int location = (i * 5) % mainWindow.getComponentContentPane().getHeight();
FlashPlayer temp = new FlashPlayer(location,location , mainWindow);
temp.createFlashPanel(new File(theFiles[i].getAbsolutePath()));
mainWindow.getCurrPage().addComponent(temp);
mainWindow.getCurrPage().loadPage();
}
}
}
#Override
public BCFrame copy(int x, int y) {
try
{
FlashPlayer clone = new FlashPlayer(x,y,this.getWidth(),this.getHeight(),mainWindow);
clone.setTitleBarVisible(this.isTitleBarRemoved());
clone.setActions(this.getActions());
if(dataSource == dataSource.file)
{
clone.setMovie(new File(this.getData("Path")));
}
else
{
clone.setMovie(this.getData("Path"));
}
clone.setPlayOnStart(isPlayOnStart());
clone.setIsLoop(isLoop());
return clone;
}
catch(Exception e)
{
LogRunner.dialogMessage(this.getClass(),"Cant clone this compoenent");
}
return null;
}
/**
* Thread to poll the current frame of the flash movie to be displayed
*/
class FrameMonitorThread extends Thread {
FlashPanel flashPanel;
FrameMonitorThread(FlashPanel fp) {
flashPanel = fp;
}
public void run() {
while (true) {
if (flashPanel != null) {
final long currentFrame = flashPanel.getCurrentFrame();
final long totalFrames = flashPanel.getTotalFrames();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
double cf = currentFrame;
double tf = totalFrames;
double result = cf/tf;
int percent = (int)(100 * result);
try{progressBar.setValue(percent);}catch(Exception e){}
currentFrameLabel.setText("Frame: " + currentFrame + "/" + totalFrames);
}
});
}
try {
Thread.sleep(100);
} catch (Exception e) {
}
}
}
}
/**
* Checks whterer the dlls that flash player needs are in their correct spot
* #return True if all the dlls could be found, false otherwise
*/
public static boolean checkDlls()
{
String systemFolder = "C:\\WINDOWS\\system32\\";
String [] dlls = new String[]{"atl2k.dll","atl98.dll","jflash.dll"};
for(String x : dlls)
{
if(!new File(systemFolder + x).exists())
{
return false;
}
}
return true;
}
}
One option is to embed a web browser, and let that load Flash Player.
See: Embed a web browser within a java application
I have a function which gets a key from the user and generates a Hashtable (on a pattern specified by the key). After creating a Hashtable, I would like to populate a JTable so that each each column represents a key and every rows represents the values associated with the key. I tried everything but couldn't get this work. I'm not creating the table from within the constructor as I need to get input from the user.
See How to Use Tables: Creating a Table Model.
The JTable constructor used by
SimpleTableDemo creates its table
model with code like this:
new AbstractTableModel() {
public String getColumnName(int col) {
return columnNames[col].toString();
}
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int row, int col) {
return rowData[row][col];
}
public boolean isCellEditable(int row, int col)
{ return true; }
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
}
You basically have to wrap your hashtable in the above manner. Here's an example.
package eed3si9n.hashtabletable;
import java.awt.BorderLayout;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.JButton;
import java.awt.Dimension;
public class MainForm extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null; // #jve:decl-index=0:visual-constraint="23,38"
private JScrollPane m_scrollPane = null;
private JTable m_table = null;
private Hashtable<String, String> m_hash = null;
private JButton m_btnAdd = null;
/**
* This is the default constructor
*/
public MainForm() {
super();
initialize();
m_hash = new Hashtable<String, String>();
m_hash.put("Dog", "Bow");
}
private void onButtonPressed() {
m_hash.put("Cow", "Moo");
m_table.revalidate();
}
/**
* This method initializes this
*
* #return void
*/
private void initialize() {
this.setSize(409, 290);
this.setTitle("JFrame");
this.setContentPane(getJContentPane());
}
/**
* This method initializes jContentPane
*
* #return javax.swing.JPanel
*/
private JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.setSize(new Dimension(500, 500));
jContentPane.setPreferredSize(new Dimension(500, 500));
jContentPane.add(getM_scrollPane(), BorderLayout.NORTH);
jContentPane.add(getM_btnAdd(), BorderLayout.SOUTH);
}
return jContentPane;
}
/**
* This method initializes m_scrollPane
*
* #return javax.swing.JScrollPane
*/
private JScrollPane getM_scrollPane() {
if (m_scrollPane == null) {
m_scrollPane = new JScrollPane();
m_scrollPane.setViewportView(getM_table());
}
return m_scrollPane;
}
/**
* This method initializes m_table
*
* #return javax.swing.JTable
*/
private JTable getM_table() {
if (m_table == null) {
m_table = new JTable();
m_table.setModel(new AbstractTableModel(){
private static final long serialVersionUID = 1L;
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return m_hash.size();
}
public String getColumnName(int column) {
if (column == 0) {
return "Animal";
} else {
return "Sound";
}
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return getKey(rowIndex);
} else {
return m_hash.get(getKey(rowIndex));
} // if-else
}
private String getKey(int a_index) {
String retval = "";
Enumeration<String> e = m_hash.keys();
for (int i = 0; i < a_index + 1; i++) {
retval = e.nextElement();
} // for
return retval;
}
});
}
return m_table;
}
/**
* This method initializes m_btnAdd
*
* #return javax.swing.JButton
*/
private JButton getM_btnAdd() {
if (m_btnAdd == null) {
m_btnAdd = new JButton();
m_btnAdd.setPreferredSize(new Dimension(34, 30));
m_btnAdd.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
onButtonPressed();
}
});
}
return m_btnAdd;
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainForm frame = new MainForm();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
});
}
} // #jve:decl-index=0:visual-constraint="10,10"
Firstly, avoid Hashtable, go straight for Map. In this case there two potential standard implementations you mights want: LinkedHashMap can retain the order that the entries were added; TreeMap, a SortedMap/NavigableMap, will sort the results (order of which can be determined by a Comparator. Alternatively you might want a form of Map that fire events or also provides a TableModel.
If you want a one time conversion from the Map to table, then it's pretty straightforward.
public static TableModel toTableModel(Map<?,?> map) {
DefaultTableModel model = new DefaultTableModel(
new Object[] { "Key", "Value" }, 0
);
for (Map.Entry<?,?> entry : map) {
model.addRow(new Object[] { entry.getKey(), entry.getValue() });
}
return model;
}
Then just create the JTable with this pre-populated model.
(Disclaimer: I've not tested or so much as compiled this code.)
To keep the Map and TableModel synchronized is more code. Generally it's best to avoid duplicating state whereever possible. Write a class that exposes itself as both a Map and a TableModel. You could go more disjoint by having a Map that fires events and a TableModel that adapts the Map (although note that Map does not have random access based on index, so you'll need to be iether clever or slow for large maps).
Going the other way, a simpler approach would be to add the data straight to a DefaultTableModel and not using a Map at all.