Is there a way of tracking stages - javafx

I want to track focused node to perform some action after user inactivity on that node. But focused for my application means that there could be only 1 focus node in the entire application (application has numerous Stages and they creation are out of my control. I also cannot force different department of my company to use registry to register stages after they create them).
E.g. I have a property for focused component scene.focusOwnerProperty(), I can track whether Stage is stage.focusedProperty() but I'm searching the way to retrieve all stages.
Do you know the way?

I found a solution. com.sun.javafx.stage.StageHelper.getStages() list all stages.

You can Use Window[] windows = Window.getWindows(); this is part of the Public Api and works fine for me.

Thanks guys for answers. I write a class which provides an easy way to track currently focused Node and "focused" Scene. "Focused" means the focused component from focused Stage. If there are any mistakes in my code I would be grateful for if you notice and inform me.
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.stage.Stage;
import com.sun.javafx.stage.StageHelper;
/**
* Tracks focused component among all {#link Stage}'s. Currently this is singleton but it will make service
* out of it.
*
* #author created: kszymanek on 8 sty 2016 15:19:32
*/
public class GlobalFocusTracker
{
private static final GlobalFocusTracker INSTANCE = new GlobalFocusTracker();
/**
* tracks stage list and each stage and registers {#link #sceneListener} on
* the focused stage
*/
private StagesListener stagesListener;
/**
* tracks scene of the focused stage and registers
* {#link #focusOwnerListener} on it
*/
private SceneListener sceneListener;
private FocusOwnerListener focusOwnerListener;
private ReadOnlyObjectWrapper focusedNodeProperty = new ReadOnlyObjectWrapper();
private ReadOnlyObjectWrapper focusedSceneProperty = new ReadOnlyObjectWrapper();
private GlobalFocusTracker()
{
}
public static GlobalFocusTracker getInstance()
{
return INSTANCE;
}
/**
* #return current {#link Scene} from the currently focused {#link Stage}
*/
public ReadOnlyObjectProperty focusedSceneProperty()
{
init();
return focusedSceneProperty.getReadOnlyProperty();
}
/**
* #return focused node among all stages. There could be one focus owner at
* the time. If end user focuses some other application there would
* be no focus node.
*/
public ReadOnlyObjectProperty focusedNodeProperty()
{
init();
return focusedNodeProperty.getReadOnlyProperty();
}
private void init()
{
if(stagesListener == null)
{
stagesListener = new StagesListener();
sceneListener = new SceneListener();
focusOwnerListener = new FocusOwnerListener();
stagesListener.register();
}
}
private class StagesListener implements ListChangeListener, ChangeListener
{
private ObservableList stages;
#Override
public void onChanged(javafx.collections.ListChangeListener.Change aChange)
{
while(aChange.next())
{
if(aChange.wasRemoved())
{
for(Stage stage : aChange.getRemoved())
{
stage.focusedProperty().removeListener(this);
}
}
if(aChange.wasAdded())
{
for(Stage stage : aChange.getAddedSubList())
{
stage.focusedProperty().addListener(this);
}
}
}
}
#Override
public void changed(ObservableValue aObservable, Boolean aOld, Boolean aNew)
{
Stage focusedStage = null;
for(Stage stage : stages)
{
if(stage.isFocused())
{
focusedStage = stage;
}
}
sceneListener.register(focusedStage);
}
public void register()
{
if(stages == null)
{
stages = StageHelper.getStages();
stages.addListener(this);
for(Stage stage : stages)
{
stage.focusedProperty().addListener(this);
if(stage.isFocused())
{
sceneListener.register(stage);
}
}
}
}
}
private class SceneListener implements ChangeListener
{
private Stage stage;
#Override
public void changed(ObservableValue aObservable, Scene aOld, Scene aNew)
{
focusOwnerListener.register(aNew);
}
/**
* #param aStage is {#code null} protected
*/
public void register(Stage aStage)
{
if(aStage != stage)
{
unregister();
stage = aStage;
if(aStage != null)
{
aStage.sceneProperty().addListener(this);
focusOwnerListener.register(aStage.getScene());
}
}
}
public void unregister()
{
if(stage != null)
{
focusOwnerListener.unregister();
stage.sceneProperty().removeListener(this);
stage = null;
}
}
}
private class FocusOwnerListener implements ChangeListener
{
private Scene scene;
#Override
public void changed(ObservableValue aObservable, Node aOld, Node aNew)
{
focusedNodeProperty.set(aNew);
}
/**
* #param aScene can be {#code null} in such case it is only an equivalent
* of {#link #unregister()}
*/
public void register(Scene aScene)
{
if(scene != aScene)
{
unregister();
scene = aScene;
focusedSceneProperty.set(aScene);
if(aScene != null)
{
focusedNodeProperty.set(aScene.getFocusOwner());
aScene.focusOwnerProperty().addListener(this);
}
}
}
public void unregister()
{
if(scene != null)
{
focusedSceneProperty.set(null);
focusedNodeProperty.set(null);
scene.focusOwnerProperty().removeListener(this);
scene = null;
}
}
}
}

Related

JavaFx-14 resizeColumnToFitContent method

JavaFx-14 put this method in the TableColumnHeader, rather than in the Skin. How does one find a TableColumnHeader from a TableColumn and a TableView?
Don't know if you still need this, but if anyone else is interested, this is how I surpassed the problem in java, based on David Goodenough's scala code above.
The class for the TableSkin
import javafx.scene.control.TableColumnBase;
import javafx.scene.control.TableView;
import javafx.scene.control.skin.NestedTableColumnHeader;
import javafx.scene.control.skin.TableColumnHeader;
import javafx.scene.control.skin.TableHeaderRow;
import javafx.scene.control.skin.TableViewSkin;
import java.util.ArrayList;
import java.util.List;
public class CustomTableViewSkin extends TableViewSkin<Track> {
private List<CustomTableColumnHeader> columnHeadersList = new ArrayList<>();
private class CustomTableColumnHeader extends TableColumnHeader {
/**
* Creates a new TableColumnHeader instance to visually represent the given
* {#link TableColumnBase} instance.
*
* #param tc The table column to be visually represented by this instance.
*/
public CustomTableColumnHeader(TableColumnBase tc) {
super(tc);
}
public void resizeColumnToFitContent() {
super.resizeColumnToFitContent(-1);
}
}
public CustomTableViewSkin(TableView<Track> tableView) {
super(tableView);
}
#Override
protected TableHeaderRow createTableHeaderRow() {
return new TableHeaderRow(this) {
#Override
protected NestedTableColumnHeader createRootHeader() {
return new NestedTableColumnHeader(null) {
#Override
protected TableColumnHeader createTableColumnHeader(TableColumnBase col) {
CustomTableColumnHeader columnHeader = new CustomTableColumnHeader(col);
if (columnHeadersList == null) {
columnHeadersList = new ArrayList<>();
}
columnHeadersList.add(columnHeader);
return columnHeader;
}
};
}
};
}
public void resizeColumnToFit() {
if (!columnHeadersList.isEmpty()) {
for (CustomTableColumnHeader columnHeader : columnHeadersList) {
columnHeader.resizeColumnToFitContent();
}
}
}
}
And the class for the TableView
import javafx.scene.control.TableView;
public class CustomTableView extends TableView<Foo> {
private final CustomTableViewSkin thisSkin;
public CustomTableView() {
super();
setSkin(thisSkin = new CustomTableViewSkin(this));
}
public void resizeColumnsToFitContent() {
if (thisSkin != null && getSkin() == thisSkin) {
thisSkin.resizeColumnToFit();
}
}
}
Well this code is Scala not Java, but for the record the code below works:-
skin = new TableViewSkin(this) {
override protected def createTableHeaderRow:TableHeaderRow = {
new TableHeaderRow(this) {
override protected def createRootHeader:NestedTableColumnHeader = {
new NestedTableColumnHeader(null) {
override protected def createTableColumnHeader(col:TableColumnBase[_,_]) = {
val tableColumnHeader = new MyTableColumnHeader(col)
if(col == null || col.getColumns.isEmpty || col == getTableColumn) tableColumnHeader else new NestedTableColumnHeader(col)
}
}
}
}
}
}
private class MyTableColumnHeader(tc:TableColumnBase[_,_]) extends TableColumnHeader(tc) {
def resizeCol():Double = {
resizeColumnToFitContent(-1)
width.value
}
}
and then when I want to use it I use kleopatra's suggestion and:-
val w = columns.map { col =>
// To find the TableColumnHeader we can use column.getStyleableNode as suggested by kleopatra on StackOverflow:-
// you get the header from coumn.getStyleableNode (took a moment, had to check if it's really implemented) – kleopatra Jul 1 at 20:46
col.getStyleableNode() match {
case mtch:MyTableColumnHeader => mtch.resizeCol
case _ => col.width.get
}
}.sum
This is a hack'ish way of getting the TableColumnHeader:
public TableColumnHeader getTableColumnHeader(TableView<?> table, int index) {
return (TableColumnHeader) table.queryAccessibleAttribute(AccessibleAttribute.COLUMN_AT_INDEX, index);
}
Or, as #kleopatra suggested, for a non-hack'ish approach you can do:
public TableColumnHeader getTableColumnHeader(TableView<?> table, int index) {
return (TableColumnHeader) table.getColumns().get(index).getStyleableNode();
}
Make sure that the TableView is part of the scene graph.
However, the resizeColumnToFitContent method is protected and you won't be able to access it.

how to get a tab through the tab's attribute text in TabPane in javafx?

I want get a tab through the tab's attribute text, but I cannot find a native method. So I writed a class to implement the purpose.
Question:
- I want to know if there is a native method for that purpose?
- Is there a better implementation?
Thanks!
```
package pre.huangjs.tabpane;
import javafx.collections.ListChangeListener;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import java.util.HashMap;
import java.util.List;
/**
* Created by huangjs on 2018/4/9.
*/
public class TabPaneExpansion {
private TabPane tabPane;
private HashMap<String, Tab> tabsMap;
public TabPane getTabPane() {
return tabPane;
}
public void setTabPane(TabPane tabPane) {
this.tabPane = tabPane;
}
public TabPaneExpansion() {
this.tabPane = new TabPane();
this.tabsMap = new HashMap<>();
initial();
}
public TabPaneExpansion(TabPane tabPane) {
this.tabPane = tabPane;
this.tabsMap = new HashMap<>();
initial();
}
private void initial() {
tabPane.getTabs().addListener(new ListChangeListener<Tab>() {
#Override
public void onChanged(Change<? extends Tab> c) {
while (c.next()) {
// if elements were added into list, the elements's text
// and the elements themselves need to be added into HashMap
if (c.wasAdded()) {
List<? extends Tab> addedTabs = c.getAddedSubList();
for (Tab tab : addedTabs) {
tabsMap.put(tab.getText(), tab);
}
}
// if elements were removed from list, the elements's text
// and the elements themselves need to be removed from HashMap
if(c.wasRemoved()){
List<? extends Tab> removedTabs = c.getRemoved();
for(Tab tab : removedTabs){
tabsMap.remove(tab.getText());
}
}
}
}
});
}
public boolean addTab(Tab tab) {
return this.tabPane.getTabs().add(tab);
}
public boolean addTabs(Tab... tabs) {
return this.tabPane.getTabs().addAll(tabs);
}
public boolean removeTab(String text){
return this.tabPane.getTabs().remove(getTabByText(text));
}
public Tab getTabByText(String text) {
return tabsMap.get(text);
}
}
```

Tab changing in Android Studio

I am new to Android Programming and Android studio.
Basically, I am creating a Memo App by Android Studio, created a Tabbed Activity(Action Bar Tabs(with viewpager)), then created 4 Fragment class and layout, all codes generated automatically by Android Studio.
But I get stuck in Tab changing......
package com.example.user.memoapp;
import java.util.Locale;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentPagerAdapter;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
static ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the four
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below)
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 4 total pages.
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
case 3:
return getString(R.string.title_section4).toUpperCase(l);
}
return null;
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public int mPage;
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_all, container, false);
return rootView;
}
}
}
I tried to change getItem() to something Like this:
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below)
//return PlaceholderFragment.newInstance(position + 1);
switch(position){
case 0:
return new All();
case 1:
return new Urgent();
case 2:
return new Late();
case 3:
return new Done();
default:
return null;
}
}
But it dont even work, said "Unfortunately, MemoApp has stopped".
Here are the codes of the 4 fragment class, they are all generated by Android Studio, are basically the same....
All.java:
package com.example.user.memoapp;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link All.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link All#newInstance} factory method to
* create an instance of this fragment.
*/
public class All extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment all.
*/
// TODO: Rename and change types and number of parameters
public static All newInstance(String param1, String param2) {
All fragment = new All();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public All() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_all, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
Urgent.java
package com.example.user.memoapp;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Urgent.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Urgent#newInstance} factory method to
* create an instance of this fragment.
*/
public class Urgent extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment Urgent.
*/
// TODO: Rename and change types and number of parameters
public static Urgent newInstance(String param1, String param2) {
Urgent fragment = new Urgent();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public Urgent() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_urgent, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
Late.java,
package com.example.user.memoapp;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Late.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Late#newInstance} factory method to
* create an instance of this fragment.
*/
public class Late extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment Late.
*/
// TODO: Rename and change types and number of parameters
public static Late newInstance(String param1, String param2) {
Late fragment = new Late();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public Late() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_late, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
Done.java:
package com.example.user.memoapp;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Done.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Done#newInstance} factory method to
* create an instance of this fragment.
*/
public class Done extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment Done.
*/
// TODO: Rename and change types and number of parameters
public static Done newInstance(String param1, String param2) {
Done fragment = new Done();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public Done() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_done, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
Sorry for extremely long boring coding...
As the logcat says, you are assigning your MainActivity to All.mListener, which is an OnFragmentInteractionListener, but MainActivity does not implement this interface
So you need to make MainActivity implement OnFragmentInteractionListener:
public class MainActivity extends ActionBarActivity implements
ActionBar.TabListener, OnFragmentInteractionListener {
// ... all your Activity code ...
#Override
public void onFragmentInteraction(Uri uri) {
// ... implement communication here ...
}
}
This will prevent the app from crashing, but still you will need to implement communication between Fragments and Activity. Change the parameters required by onFragmentInteraction() if you need to send something else, or remove the interface and any reference of mListener if you don't need that kind of communication.
Good luck!

JavaFX tableview hiding a selected row

In my JavaFX application I am trying to hide the selected rows in the tableview. I used CSS as below.
.hideRow
{
-fx-cell-size: 0px;
-fx-border-width: 0;
}
I used the below row factory for the achieving the same.
import java.util.Collections;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.util.Callback;
/
**
* This is the table view row style factory class. * This class is responsible
* for performing style changes for enable,disable,hide and un hide of the rows.
*
* #param <T>
*/
public class StyleChangingRowFactory<T> implements
Callback<TableView<T>, TableRow<T>> {
private TableRow rowSelected;
private final String styleClass;
private final ObservableList<Integer> styledRowIndices;
private final Callback<TableView<T>, TableRow<T>> baseFactory;
/**
* Construct a <code>StyleChangingRowFactory</code>, specifying the name of
* the style class that will be applied to rows determined by
* <code>getStyledRowIndices</code> and a base factory to create the
* <code>TableRow</code>. If <code>baseFactory</code> is <code>null</code>,
* default table rows will be created.
*
* #param styleClass The name of the style class that will be applied to
* specified rows.
* #param baseFactory A factory for creating the rows. If null, default
* <code>TableRow<T></code>s will be created using the default
* <code>TableRow</code> constructor.
*/
public StyleChangingRowFactory(String styleClass, Callback<TableView<T>, TableRow<T>> baseFactory) {
this.styleClass = styleClass;
this.baseFactory = baseFactory;
this.styledRowIndices = FXCollections.observableArrayList();
}
/**
* Construct a <code>StyleChangingRowFactory</code>, which applies
* <code>styleClass</code> to the rows determined by
* <code>getStyledRowIndices</code>, and using default
* <code>TableRow</code>s.
*
* #param styleClass
*/
public StyleChangingRowFactory(String styleClass) {
this(styleClass, null);
}
#Override
public TableRow<T> call(final TableView<T> tableView) {
final TableRow<T> row;
if (baseFactory == null) {
row = new TableRow<>();
} else {
row = baseFactory.call(tableView);
}
row.setOnDragEntered(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent t) {
tableView.getSelectionModel().clearSelection();
tableView.getSelectionModel().selectRange(rowSelected.getIndex(), row.getIndex());
}
});
row.setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
rowSelected = row;
Dragboard db = row.getTableView().startDragAndDrop(TransferMode.LINK);
ClipboardContent content = new ClipboardContent();
content.put(DataFormat.PLAIN_TEXT, "XData");
db.setContent(content);
tableView.getSelectionModel().clearSelection();
t.consume();
}
});
row.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
rowSelected = row;
final int index = row.getIndex();
if (event.getButton() == MouseButton.SECONDARY && index >= 0 && !tableView.getSelectionModel().isSelected(index)) {
tableView.getSelectionModel().clearSelection();
}
}
});
row.indexProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> obs,
Number oldValue, Number newValue) {
updateStyleClass(row);
}
});
styledRowIndices.addListener(new ListChangeListener<Integer>() {
#Override
public void onChanged(Change<? extends Integer> change) {
updateStyleClass(row);
tableView.getColumns().get(0).setVisible(false);
tableView.getColumns().get(0).setVisible(true);
}
});
return row;
}
/**
*
* #return The list of indices of the rows to which <code>styleClass</code>
* will be applied. Changes to the content of this list will result in the
* style class being immediately updated on rows whose indices are either
* added to or removed from this list.
*/
public ObservableList<Integer> getStyledRowIndices() {
return styledRowIndices;
}
private void updateStyleClass(TableRow<T> row) {
final ObservableList<String> rowStyleClasses = row.getStyleClass();
if (styledRowIndices.contains(row.getIndex())) {
if (!rowStyleClasses.contains(styleClass)) {
rowStyleClasses.add(styleClass);
}
} else {
// remove all occurrences of styleClass:
rowStyleClasses.removeAll(Collections.singletonList(styleClass));
}
}
}
I declared the row factory as
StyleChangingRowFactory rowFactory = new StyleChangingRowFactory<>("hideRow");
I have two pop up menus in my table, they are hide and unhide.
In my controller I used the below methods with implementation for those menus.
private void hidePressed() {
rowFactory.getHiddenRowIndices().addAll(cfiTableView.getSelectionModel().getSelectedIndices());
}
private void unHidePressed() {
rowFactory.getHiddenRowIndices().removeAll(cfiTableView.getSelectionModel().getSelectedIndices());
}
The problem is when I hide the selected row(s). It is also hiding some other rows in the table view. Please help me to solve this issue.

Combining Fragments and ActionBar in Android level < 13. Is there a feasible way?

I would like to write my project in the lowest possible Android version for my reqs, which is 11.
But I need Fragment.attach and ActionBars.
Since level 11 does not include Fragment.attach I import the support package for v4.
But now the problem is that the TabListerner for the ActionTab does not use the v4 Fragment but rather the level 11 Fragment. Casting won't work.
Do I really need to switch to level 13 or is there a feasible solution to implement all this in level 11.
Here is the code:
import android.app.ActionBar;
import android.app.Activity;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.Fragment;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.os.Bundle;
import android.support.v4.app.Fragment;
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public static class TabListener<T extends android.support.v4.app.Fragment> /* to make sure it take the Fragment from the support package! */
implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
/**
* Constructor used each time a new tab is created.
*
* #param activity
* The host Activity, used to instantiate the fragment
* #param tag
* The identifier tag for the fragment
* #param clz
* The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab,
android.support.v4.app.FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
/* these are NOT the implementation of the TabListener above, since the use the
*
* the FragmentTransactionof the support package and not of level 11
*
*/
public void onTabUnselected(Tab tab,
android.support.v4.app.FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab,
android.support.v4.app.FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
/* these are added since they belong to the above definition of TabListener
*
* unfortunately the use the FragmentTransaction of level 11, not the one of the support package!
*
*/
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
}
}
}
im using ActionBarCompat and Fragments on Api Ver 8.0 , the only diference with your code its that im using ft.replace instead of ft.add and a ViewPager on the xml to show the fragments, it runs ok so far ..
import android.app.Activity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
public final class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
/** Constructor used each time a new tab is created.
* #param activity The host Activity, used to instantiate the fragment
* #param tag The identifier tag for the fragment
* #param clz The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.replace(R.id.pager, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.replace(R.id.pager, mFragment, mTag);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.remove(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
Not sure if you still need this, but we use ActionBarSherlock and it sounds like it could help you as well:
http://actionbarsherlock.com/

Resources