I am trying to make some small additions to some old java code that does not support swing. I need to add a small dialog that contains a panel which has a checkbox and a couple text fields. When the user clicks on the checkbox I want to disable or enable the checkboxes. This part seems to work well but the text fields are not properly getting redrawn. When I click the checkbox the fields do not appear to become enabled but if I then click on the panel or the text field you see that they are enabled (the opposite is also true, when I un-check the checkbox the fields still look enabled until you try and click on them and they become ghosted and do not become selected). I use the setEnabled(boolean) to set the status of the fields. I have tried calling repaint and validate on both the fields and the panel after changing the status and this does not seem to work. I have also tried to have the fields request focus and this did not work. Anyone have any other ideas?
//The class that contains all of this is of type Window
//Declaration of the components
private Panel _inputPanel;
private TextField min , max;
//This method adds to two text fields
public void addMinMaxtextFields(String min, String max) {
TextField minField = new TextField(min);
TextField maxField = new TextField(max);
this.min = minField;
this.max = maxField;
this.min.setEnabled(false);
this.max.setEnabled(false);
_inputPanel.add(minField);
_inputPanel.add(maxField);
}
//listener for the checkbox
public void itemStateChanged(ItemEvent e) {
Component[] components = _inputPanel.getComponents();
min.setEnabled(!min.isEnabled());
min.setVisible(true);
min.validate();
min.repaint();
_inputPanel.validate();
_inputPanel.repaint();
this.pack();
this.setSize(this.getWidth(), this.getHeight());
this.validate();
this.repaint();
/* do nothing */
}
You will need to call update(Graphics g) on Panel after setEnabled(boolean) is called.
check :
http://download-llnw.oracle.com/javase/1.4.2/docs/api/java/awt/Container.html#update(java.awt.Graphics)
I tried following code (built from code you provided), Its working fine.
import java.awt.Checkbox;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
public class CheckUI extends Dialog implements ItemListener {
// The class that contains all of this is of type Window
// Declaration of the components
private Panel _inputPanel;
private TextField min, max;
private Checkbox cb;
public CheckUI(Frame owner, boolean modal) {
super(owner, modal);
_inputPanel = new Panel();
this.add(_inputPanel);
addMinMaxtextFields("min", "max");
}
// This method adds to two text fields
public void addMinMaxtextFields(String min, String max) {
cb = new Checkbox();
cb.addItemListener(this);
TextField minField = new TextField(min);
TextField maxField = new TextField(max);
this.min = minField;
this.max = maxField;
this.min.setEnabled(false);
this.max.setEnabled(false);
_inputPanel.add(minField);
_inputPanel.add(maxField);
_inputPanel.add(cb);
}
// listener for the checkbox
public void itemStateChanged(ItemEvent e) {
Component[] components = _inputPanel.getComponents();
min.setEnabled(!min.isEnabled());
min.setVisible(true);
min.validate();
min.repaint();
_inputPanel.validate();
_inputPanel.repaint();
this.pack();
this.setSize(this.getWidth(), this.getHeight());
this.validate();
this.repaint();
/* do nothing */
}
/**
* #param args
*/
public static void main(String[] args) {
Frame parent = new Frame();
parent.setVisible(true);
parent.setExtendedState(Frame.MAXIMIZED_BOTH);
parent.pack();
CheckUI ui = new CheckUI(parent, true);
ui.pack();
ui.setVisible(true);
}
}
Related
I'm beginner in JavaFX.
I need to make one-at-a-time handler for any changes in the check boxes for my TreeView. Now it works like it handles all selected nodes simultaneously.
Thanks for help. Here is my code:
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = new BorderPane();
root.setCenter(initTreeView());
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public TreeView initTreeView() {
TreeView<String> treeView = new TreeView<>();
treeView.setRoot(new CheckBoxTreeItem<>("123"));
treeView.getRoot().addEventHandler(CheckBoxTreeItem.checkBoxSelectionChangedEvent(), event -> System.out.println("hello"));
treeView.setCellFactory(p -> new CheckBoxTreeCell<>());
treeView.getRoot().getChildren().addAll(new CheckBoxTreeItem<>("1"),new CheckBoxTreeItem<>("2"), new CheckBoxTreeItem<>("3"));
treeView.getRoot().getChildren().get(0).getChildren().addAll(new CheckBoxTreeItem<>("4"),new CheckBoxTreeItem<>("5"), new CheckBoxTreeItem<>("6"));
treeView.getRoot().getChildren().get(1).getChildren().addAll(new CheckBoxTreeItem<>("7"),new CheckBoxTreeItem<>("8"), new CheckBoxTreeItem<>("9"));
treeView.getRoot().getChildren().get(2).getChildren().addAll(new CheckBoxTreeItem<>("10"),new CheckBoxTreeItem<>("11"), new CheckBoxTreeItem<>("12"));
return treeView;
}
public static void main(String[] args) {
launch(args);
}
}
Actually it works correctly. Your event handler is called once for every changed checkbox node. Just note that changing subnodes affects parent ones as well, so you get several event handles calls.
Try next code instead which prints the name of the affected checkbox:
treeView.getRoot().addEventHandler(CheckBoxTreeItem.checkBoxSelectionChangedEvent(),
event -> System.out.println("hello " + event.getTreeItem().getValue()));
For example, if you click on checkbox "5" you will get the following log:
hello 5
hello 1
hello 123
because all parent node have changed state as well (from unchecked to intermediate "-" state). If you click "6" after that only one checkbox is affected and output will be:
hello 6
Consider the following example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TestCheckBoxTab extends Application {
public void start (Stage stage) {
HBox root = new HBox();
root.getChildren().addAll(new TextField(), new TextField(), new CheckBox(), new TextField());
stage.setScene(new Scene(root));
stage.show();
}
public static void main (String[] args) {
launch();
}
}
Here you can easily use the TAB and SHIFT+TAB commands to traverse through the different controls, and it works properly.
But if you have the same controls inside table cells in a TableView, the CheckBox breaks the traversal order. This is demonstrated in the following example:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class AlwaysEditableTable extends Application {
public void start(Stage stage) {
TableView<ObservableList<StringProperty>> table = new TableView<>();
table.setEditable(true);
table.getSelectionModel().setCellSelectionEnabled(true);
table.setPrefWidth(505);
// Dummy columns
ObservableList<String> columns = FXCollections.observableArrayList("Column1", "Column2", "Column3", "Column4",
"Column5");
// Dummy data
ObservableList<StringProperty> row1 = FXCollections.observableArrayList(new SimpleStringProperty("Cell1"),
new SimpleStringProperty("Cell2"), new SimpleStringProperty("0"), new SimpleStringProperty("Cell4"),
new SimpleStringProperty("1"));
ObservableList<ObservableList<StringProperty>> data = FXCollections.observableArrayList();
data.add(row1);
for (int i = 0; i < columns.size(); i++) {
final int j = i;
TableColumn<ObservableList<StringProperty>, String> col = new TableColumn<>(columns.get(i));
col.setCellValueFactory(param -> param.getValue().get(j));
col.setPrefWidth(100);
if (i == 2 || i == 4) {
col.setCellFactory(e -> new CheckBoxCell(j));
} else {
col.setCellFactory(e -> new AlwaysEditingCell(j));
}
table.getColumns().add(col);
}
table.setItems(data);
Scene scene = new Scene(table);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
/**
* A cell that contains a text field that is always shown. The text of the
* text field is bound to the underlying data.
*/
public static class AlwaysEditingCell extends TableCell<ObservableList<StringProperty>, String> {
private final TextField textField;
public AlwaysEditingCell(int columnIndex) {
textField = new TextField();
this.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
setGraphic(null);
} else {
setGraphic(textField);
}
});
// The index is not changed until tableData is instantiated, so this
// ensure the we wont get a NullPointerException when we do the
// binding.
this.indexProperty().addListener((obs, oldValue, newValue) -> {
ObservableList<ObservableList<StringProperty>> tableData = getTableView().getItems();
int oldIndex = oldValue.intValue();
if (oldIndex >= 0 && oldIndex < tableData.size()) {
textField.textProperty().unbindBidirectional(tableData.get(oldIndex).get(columnIndex));
}
int newIndex = newValue.intValue();
if (newIndex >= 0 && newIndex < tableData.size()) {
textField.textProperty().bindBidirectional(tableData.get(newIndex).get(columnIndex));
setGraphic(textField);
} else {
setGraphic(null);
}
});
}
}
/**
* A cell containing a checkbox. The checkbox represent the underlying value
* in the cell. If the cell value is 0, the checkbox is unchecked. Checking
* or unchecking the checkbox will change the underlying value.
*/
public static class CheckBoxCell extends TableCell<ObservableList<StringProperty>, String> {
private final CheckBox box;
private ObservableList<ObservableList<StringProperty>> tableData;
public CheckBoxCell(int columnIndex) {
this.box = new CheckBox();
this.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
setGraphic(null);
} else {
setGraphic(box);
}
});
this.indexProperty().addListener((obs, oldValue, newValue) -> {
tableData = getTableView().getItems();
int newIndex = newValue.intValue();
if (newIndex >= 0 && newIndex < tableData.size()) {
// If active value is "1", the check box will be set to
// selected.
box.setSelected(tableData.get(getIndex()).get(columnIndex).equals("1"));
// We add a listener to the selected property. This will
// allow us to execute code every time the check box is
// selected or deselected.
box.selectedProperty().addListener((observable, oldVal, newVal) -> {
if (newVal) {
// If newValue is true the checkBox is selected, and
// we set the corresponding cell value to "1".
tableData.get(getIndex()).get(columnIndex).set("1");
} else {
// Otherwise we set it to "0".
tableData.get(getIndex()).get(columnIndex).set("0");
}
});
setGraphic(box);
} else {
setGraphic(null);
}
});
}
}
}
When pressing TAB while focusing a TextField inside a TableCell, the focus is moved to the next control properly. But if a CheckBox inside a TableCell is focused, the focus is moved to the first Control in the TableView instead of to the next Control. SHIFT+TAB while focusing a CheckBoxwill move the focus to the last control in the TableView. If I add a TextField outside the TableView, SHIFT+TAB while focusing a CheckBox will actually focus that TextField, while TAB behaviour still at least keeps the focus inside the TableView. The CheckBox somehow breaks the traversal order.
This is strange to me since TextField and CheckBox seems to have the same TAB functionality implemented, due to the fact the traversal order is correct in the first example. Something I guess is inherited from the Control class.
Does anybody know anything about this? I tried to look for some kind of EventFilter or listener for the TAB and SHIFT+TAB commands inside the source code of Control, TextField, CheckBox, TextInputControl and even in the Scene source, but I couldn't find it anywhere.
I also tried implementing my own TAB functionality for the CheckBox cell, which ended up raising another issue.
I was struggling a lot with the same issue. I finally avoided it by setting:
checkBox.setFocusTraversable(false);
and
this.setFocusTraversable(false);
on my own implementation of BooleanCell.
The table traverses over editable fields and the Checkbox is always enabled in my implementation. But setting the Checkbox disabled means you have to double click on it to change the value. That would be weird behaviour.
I am creating a tree structure in RCP application. I want to able to create a pop up menu. I have been able to create a dummy menu item.
final Menu treeMenu = new Menu(check.getShell(), SWT.POP_UP);
MenuItem item = new MenuItem(treeMenu, SWT.PUSH);
item.setText("Open");
item.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
System.out.println("CAme in Open");
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
check.setMenu(treeMenu);
this menu however does not recognize the node details. I want something that can obtain information about the node which we have opened context menu on.
If you are using a TreeViewer (or TableViewer) just get the current selection:
IStructuredSelection sel = (IStructuredSelection)treeViewer.getSelection();
Object selectedElement = sel.getFirstElement();
For a Tree use:
TreeItem [] selectedItems = tree.getSelection();
I'm using GXT 3.0 and have a Grid with multiple checkboxes each row. These checkboxes reflect certain properties of my row data and checkin/unchecking does not implies selecting/unselecting the particular row. How can I add a listener to each checkbox and perform some action upon clicking it?
I override the handlesSelection() method to capture the check/uncheck event
CheckBoxCell checkCol = new CheckBoxCell() {
#Override
public boolean handlesSelection() {
//TODO:
return true;
}
};
Add some CheckBoxSelectionModel for each checkbox
IdentityValueProvider<Stock> identity = new IdentityValueProvider<Stock>();
SpecialRowClickCheckBoxSelectionModel<Stock> sm =
new SpecialRowClickCheckBoxSelectionModel<Stock>(identity);
public class SpecialRowClickCheckBoxSelectionModel<M>
extends CheckBoxSelectionModel<M> {
public SpecialRowClickCheckBoxSelectionModel(
IdentityValueProvider<M> identity) {
super(identity);
}
#Override
protected void handleRowClick(RowClickEvent event) {
M model = listStore.get(event.getRowIndex());
//TODO
}
}
I have created a register form (not using the designer).
On the form I have created numerous text fields as well as a button with ...
Button btnRegister = new Button();
btnRegister.setName("btnRegister");
btnRegister.setText("Register");
btnRegister.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frmRegister_btnRegister(f);
}
});
f.addComponent(btnRegister);
My question is how do I reference the textfields in the function being called from the button action listener. Specifically I am trying to set up arguments to use for a network call using addArgument. When I used the designer I used find(ComponentName) but that is not available anymore.
private void frmRegister_btnRegister(Form f) {
// register new user
ConnectionRequest r = new ConnectionRequest();
r.setUrl(sUrlWebSvc);
r.setPost(true);
r.addArgument("Rest", "1"); // restaurant code
r.addArgument("Req", "Register"); // R = register
//r.addArgument("first_name", findTxtUsertName(c).getText());
// show spinning dialog while connecting
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
r.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueueAndWait(r);
//System.out.println(r.getResponseData());
}
Assuming its defined just above this line:
Button btnRegister = new Button();
As:
TextField txt =....
Just change it to:
final TextField txt =....
And then you can pass it (or its getText() string value) to:
btnRegister.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frmRegister_btnRegister(f, txt);
}
});
Naturally you will need to update the signature of frmRegister_btnRegister to accept a text field or a string.