I have a TableView with a CheckBoxTableCell column.
I would like to catch the selection of the cell and change the Cursor to Cursor.WAIT.
Clicking the cell will cause some db-query to happen, that will take a few seconds. I would like to notify the user that something is going on and the application did not just die.
#FXML
private TableColumn<IOrigin, Boolean> cActive;
#Override
public void initialize(final URL location, final ResourceBundle resources) {
cActive.setCellFactory(tc -> new CheckBoxTableCell<>());
[..]
}
Listening on CheckBoxTableCell#selectedProperty() does not work, it does not fire any change events.
The column cells are bound to a bean property via fxml.
<TableColumn text="Active" editable="true" fx:id="cActive">
<cellValueFactory>
<PropertyValueFactory property="active" />
/cellValueFactory>
</TableColumn>
With the cells show CheckBox in TableView:
Note that the CheckBoxTableCell renders the CheckBox 'live', meaning that the CheckBox is always interactive and can be directly toggled by the user.
This means that it is not necessary that the cell enter its editing state (usually by the user double-clicking on the cell).
A side-effect of this is that the usual editing callbacks (such as on edit commit) will not be called.
If you want to be notified of changes, it is recommended to directly observe the boolean properties that are manipulated by the CheckBox.
Related
I am trying to code a small rpg and I decided to put the basics into an fxml document (MenuBar with their items).
So now I am planning to open a new window when you click on the Menu Items (Character, Inventory & Equipment), so I can display the things there is an extra window. So it makes sense I want to set the title of each menu equivalent to the Text displayed on the MenuItem. Of course, I could just make an extra method for every menu item, but I am searching for a possibility, where I can get the id of the Menu Item, that fired the event, so I can use their getText method to get the tag.
Can somebody help me?
I tried to access the object with "this" and also thought about using an enum to connect the IDs to Objects of the enum MenuName, so I just have to put a switch in my method, thus creating the menu, but that also didn´t work out, cause there I cannot check which of the ids got fired. So for that part of my program, it doesn´t help.
Here´s the code in my controller class
public class Controller {
#FXML
private void menuIsClickedDefault(ActionEvent event) throws Exception {
Stage secondStage = new Stage();
Parent a = FXMLLoader.load(getClass().getResource("menus.fxml"));
secondStage.setTitle(HERES_MY_PROBLEM);
secondStage.setScene(new Scene(a, 646, 400));
secondStage.initModality(Modality.APPLICATION_MODAL);
secondStage.show();
}
}
and these are my fxml objects:
<MenuItem fx:id="stats" mnemonicParsing="false" text="Statistics" />
<MenuItem fx:id="inv" mnemonicParsing="false" text="Inventory" />
<MenuItem fx:id="equip" mnemonicParsing="false" text="Equipment" />
I didnt integrate the method in the objects yet, cause it doesn´t make sense without solving the problem and I know that the rest of the code is working due to a similar method for the settings.
You can call event.getSource() to retrieve the node that triggered the event. You'll need to cast the returned object to the proper type, though.
private void menuIsClickedDefault(ActionEvent event) throws Exception {
Stage secondStage = new Stage();
Parent a = FXMLLoader.load(getClass().getResource("menus.fxml"));
// Get the source of this event and cast it to a MenuItem; then you can
// retrieve its text property
secondStage.setTitle(((MenuItem) event.getSource()).getText());
secondStage.setScene(new Scene(a, 646, 400));
secondStage.initModality(Modality.APPLICATION_MODAL);
secondStage.show();
}
my application consists of a TabPane named tabPane with, lets say, two Tabs: firstTab and secondTab. Whenever firstTab is selected, I want the application to be in FSEM (full-screen exclusive mode, see documentation); otherwise it should be in normal windowed mode.
My usual way of being notified about which Tab is active is either
BooleanBinding isFirstTabActive = tabPane.getSelectionModel().
selectedItemProperty().isEqualTo(firstTab);
or
tabPane.getSelectionModel.selectedItemProperty().addListener(...);
Since stage.fullScreenProperty() is read-only and therefore cannot be binded (as stated in docs), I can not use my first method and do, lets say,
stage.fullScreenProperty().bind(isFirstTabActive) //not working.
Since I am not planning on sigining the application for now and, as the docs state:
Applications can only enter FSEM in response to user input. More specifically, entering is allowed from mouse (Node.mousePressed/mouseReleased/mouseClicked) or keyboard (Node.keyPressed/keyReleased/keyTyped) event handlers.
I can not use the second method either, by doing
tabPane.getSelectionModel.selectedItemProperty().addListener(new ChangeListener<Tab>() {
#Override
public void changed(ObservableValue<? extends Tab> observable, Tab oldValue, Tab newValue) {
stage.setFullScreen(newValue == firstTab);
}
);
because this way the application does not enter FSEM but only emulated fullscreen mode.
I do know that I can enter FSEM by creating EventHandlers which listen to tabPane events. But this way I had to add two EventHandlers for both MouseEvent.MOUSE_CLICKED and KeyEvent.KEY_TYPED, and the EventHandlers would have to explicitly find out whats going on ignoring their Event, like:
tabPane.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
stage.setFullScreen(tabPane.getSelectionModel().getSelectedItem() == firstTab);
}
});
So is this really the way to go here? Or can I do some workaround with the Bindings? Any suggestions here? Thanks.
Our group is working on a Custom Activity Designer around our Email activity. It's a pretty straight forward designer, allow the user to enter settings / creds, but instead of cluttering the activity designer with all the settable options, we thought about putting some settings in a dialog window. (Which opens when you click the button beside the server address box).
Some of our email activity properties are InArguments so we are trying to make use of the ExpressionTextBox to display these values without much luck. The main problem is we aren't sure how to properly set up the binding and the OwnerActivity on the ExpressionTextBox. In the Activity Designer's xaml this is simply done by setting Expression=ModelItem.Property using a converter for the InArgument and setting the OwnerActivity=ModelItem, like this:
<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="{Binding ModelItem.ServerAddress, ConverterParameter=In, Converter={StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="{x:Type system:String}" OwnerActivity="{Binding ModelItem}" Margin="2" MaxLines="1" />
If anyone has any ideas on how we could accomplish this in a dialog, please advise.
Well, this is more a WPF\MVVM question than WF4, really.
When developing custom activities designers you just have to keep one thing in mind: any change made on designer\dialog should be reflected on ModelItem. Either through XAML binding expressions or through code on ModelItem.Properties property.
Now, when and how you do it, there are several answers to that but that's really an implementation detail and depends on how you want to do it.
Lets assume you're showing the dialog on button-beside-the-server-address-box click. And lets also assume you've access to dialog textboxes through their name. At that point, you've access to ModelItem so just set its properties as needed:
private void ButtonNextToServerAddressBox_OnClick(object sender, RoutedEventArgs e)
{
var dialog = new ServerAddressEditor();
var result = dialog.ShowDialog();
if (result ?? false)
{
ModelItem.Properties["Server"].SetValue(new InArgument<string>(dialog.ServerTextBox.Text));
ModelItem.Properties["Port"].SetValue(new InArgument<string>(dialog.PortTextBox.Text));
// ... set all other properties
}
}
Now, if you are using any other pattern, or you want pure MVVM, it can be a little more tricky because of how ModelItem works. But this is a totally fine approach.
I resolved this by creating a property in the dialog's ViewModel to hold the Activity Designer's ModelItem.
public ModelItem OwnerActivity {
get { return _OwnerActivity; }
set { _OwnerActivity = value; }
}
vm.OwnerActivity = this.DataContext.ModelItem;
I then set the Xaml for the Expression Text Box in my dialog to binding to this:
<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="
{Binding Path=OwnerActivity.ServerAddress, ConverterParameter=In, Converter=
{StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="
{x:Type system:String}" OwnerActivity="{Binding OwnerActivity}" Margin="2"
MaxLines="1" />
Because I'm now binding directly to the ModelItem from the Activity Designer, any change made to the ModelItem property from the dialog is ALWAYS committed, even if you choose to Cancel from the dialog. To wire up the Ok/Cancel buttons so they work accordingly, I did the following in the dialog:
// declare a ModelEditingScope to make changes transactional
private ModelEditingScope _editScope;
// add this to the constructor of the dialog to begin transactional edits on the ModelItem
_editScope = editorViewModel.OwnerActivity.BeginEdit();
// ok & cancel button click event to commit or revert the changes.
private void OK_Click(object sender, RoutedEventArgs e)
{
_editScope.Complete();
this.DialogResult = DialogResult.OK;
this.Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
_editScope.Revert();
this.DialogResult = DialogResult.Cancel;
this.Close()
}
I have just started with an ActionBar.TabListener with 3 tabs.
I selected new "Tabbed activity" in Android Studio.
My activity is called test...not the best name but I'm just trying to learn:)
I have a listView in fragment_test.xml that I want to fill with data after a raw sql search.
If I put this code in onCreateView then everytime I click on a tab it will re-write that tab with the same info in the listView.
What I want is to have diffrent information in those tabs.... then I need to know which tab that is clicked. That I did with mViewPager.getCurrentItem() ....Is this right? How can i get the name of the tab instead?
I have also found onTabSelected...should I put my code here? In this case I think I know which tab that is selected but is it really wise to put the code here?
If I do this then listView1 becomes null...why?:
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
listView1 = (ListView)findViewById(R.id.listView2);
listAdapter2 = new ArrayAdapter<String>(context, R.layout.simplerow, testArray);
listAdapter2.notifyDataSetChanged();
listView1.setAdapter(listAdapter2);
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/listView2"
android:layout_centerHorizontal="true" />
If I understand it correctly, you want to load Fragment's ListView according to Tab's selected position.
If that's the case, you should not modify Fragment's ListView in Activity. Instead, pass Tab's selected position to Fragment as an argument from Activity and load ListView in Fragment according to that position.
Problem:
Have tabPane tabs OK.
In the first tab there is a text field. I am able to get focus on this field when starting the application.
After changing the tabs and coming back to the first tab I want focus to be on this textfield (barcodereader should be active in this field) without having to select the field with the mouse.
I am able to catch event from tabs with
tp.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
{ etc
(could not post with code)
and I am able to trigger en event for the first tab.
But field.requestFocus(); does not work. Probably because this method comes before rendering the textfield.
So here is my question:
How do you set focus on a control after clicking tabs in TabPane?
If you handle the mouse release event, it works: (The doFocus enables the requestFocus handling only when a tab selection changed before, otherwise it kicks in every time you click somewhere in the TabPane.)
final SimpleBooleanProperty doFocus = new SimpleBooleanProperty(false);
tabPane.setOnMouseReleased(new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (!doFocus.get()) {
return;
}
doFocus.set(false);
switch (tabPane.selectionModelProperty().getValue().selectedIndexProperty().intValue()) {
case 0: tf1b.requestFocus(); break;
case 1: tf2a.requestFocus(); break;
default: break;
}
}
});
tabPane.selectionModelProperty().getValue().selectedIndexProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) {
doFocus.set(true);
}
});
When the TabPane has focus, one can change tab selection with the cursor keys and there the TextFields also won't get the focus with selection based approach. This probably should be handled too, if you need it.
(Recently I had a similar problem. I noticed, that the TabPane switches tabs immediately when you press the mouse button. My guess would be, that the selection based approach requests focus on the TextField right after mouse down, but the continued mouse down steals the focus back to the TabPane. Or maybe even the single mouse down event which changes selection causes the focus to go back to TabPane. However, my assumptions regarding the reasons may not be correct, as I am a newbie to JavaFX.)
EDIT: That handling certainly is not optimal. For instance, if you change tabs with the keys, the doFocus will be enabled and then clicking anywhere in the TabPane will trigger the requestFocus call. I thought this should be mentioned.
Also, take a look at my solution for setting focus on TextArea, when user changes selected tab(using mouse or keyboard) https://stackoverflow.com/a/19046535/2791746