Multiple and Repetitive AsyncTask in Android - android-asynctask

I have two asynctask working with each other. I'm using them for creating Restaurant menu. First web service gets menu's titles from database. Second web service gets items of title from database. I get title data in my first asynctask and item data in my second asynctask.
For example, I have ten menu titles. There are eight items for each title. I execute first asynctask and get all of menu titles. I want to call second asynctask in first asynctask's onPostExecute for get this title's item and add TextView. I have to wait finished every second task for add item respectively.
In short, I need call first AsyncTask and wait finish it. Then send request to second AsyncTask in First AsyncTask. I have to wait every request to finish. How can I wait ?
Here is the my code.
First AsyncTask
public class BaslikDoldurAS extends AsyncTask<String,String[][],String[][]>{
int ParamID;
public BaslikDoldurAS(String ParamID){
this.ParamID=Integer.parseInt(ParamID);
}
#Override
protected String[][] doInBackground(String... params) {
BaslikDoldur(ParamID);
return sonuc;
}
protected void onPostExecute(String[][] sonuc){
for(int i=0;i<baslikCount;i++){
MenuDoldurAS kontrol = new MenuDoldurAS(firma_id,sonuc[2][i]);
kontrol.execute();
}
}
}
my function which is used in first asyncTask
private String[][] BaslikDoldur(Integer ParamID){
PropertyInfo id = new PropertyInfo();
id.name= "id";
id.setValue(ParamID);
id.type = PropertyInfo.INTEGER_CLASS;
SoapObject request = new SoapObject(NAMESPACE, "BaslikDoldur");
request.addProperty(id);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut=request;
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(MenuURL);
androidHttpTransport.debug = true;
try {
androidHttpTransport.call("http://tempuri.org/BaslikDoldur", envelope);
SoapObject response = (SoapObject) envelope.getResponse();
sonuc[2]=new String[response.getPropertyCount()]; //baslik
baslikCount=response.getPropertyCount();
for(int i=0;i<response.getPropertyCount();i++){
Object property = response.getProperty(i);
if(property instanceof SoapObject){
SoapObject menu = (SoapObject) property;
sonuc[2][i] = menu.getProperty("menu_baslik").toString();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return sonuc;
}
Second AsyncTask
public class MenuDoldurAS extends AsyncTask<String,String[][],String[][]>{
int ParamID;
String Baslik;
public MenuDoldurAS(String ParamID,String Baslik){
this.ParamID=Integer.parseInt(ParamID);
this.Baslik=Baslik;
}
#Override
protected String[][] doInBackground(String... params) {
MenuDoldur(ParamID,Baslik);
return sonuc;
}
protected void onPostExecute(String[][] sonuc){
for(int i=0;i<count;i++){
String baslik="";
if(!baslik.equals(sonuc[2][i])){
baslik=sonuc[2][i];
TextView basliktxt = new TextView(Urun.this);
basliktxt.setText(sonuc[2][i]);
basliktxt.setTextSize(20);
basliktxt.setTextColor(Color.RED);
basliktxt.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
urunLayout.addView(basliktxt);
}
else{
TextView aciklamatxt = new TextView(Urun.this);
aciklamatxt.setText(sonuc[3][i]);
aciklamatxt.setTextColor(Color.parseColor("#0c0c7c"));
aciklamatxt.setTextSize(17);
aciklamatxt.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
urunLayout.addView(aciklamatxt);
}
}
}
}
my function which is used in second asyncTask
private String[][] MenuDoldur(Integer ParamID,String Baslik){
PropertyInfo id = new PropertyInfo();
id.name= "id";
id.setValue(ParamID);
id.type = PropertyInfo.INTEGER_CLASS;
PropertyInfo baslik = new PropertyInfo();
baslik.name= "baslik";
baslik.setValue(Baslik);
baslik.type = PropertyInfo.STRING_CLASS;
SoapObject request = new SoapObject(NAMESPACE, "MenuDoldur");
request.addProperty(id);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut=request;
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(MenuURL);
androidHttpTransport.debug = true;
try {
androidHttpTransport.call("http://tempuri.org/MenuDoldur", envelope);
SoapObject response = (SoapObject) envelope.getResponse();
sonuc[3]=new String[response.getPropertyCount()]; //aciklama ve fiyat
count = response.getPropertyCount();
for(int i=0;i<response.getPropertyCount();i++){
Object property = response.getProperty(i);
if(property instanceof SoapObject){
SoapObject menu = (SoapObject) property;
sonuc[3][i] = menu.getProperty("menu_aciklama").toString() + " - " + menu.getProperty("menu_fiyat").toString();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return sonuc;
}

If you want to wait until all AsyncTasks are done before proceeding, why don't you just put all of you work in doInBackground of the first AsyncTask?
Or you don't want to do this because you want to run the 10 "second tasks" in parallel? (Which, incidentally you're not doing anyway, because you're not using the THREAD_POOL Executor for your tasks.) If this is the case then why not just do something like
// variable accessible to both tasks
ArrayList<AsyncTask> mRunningTasks = new ArrayList<AsyncTask>();
// AsyncTask1
protected void onPostExecute(String[][] sonuc){
for(int i=0;i<baslikCount;i++){
MenuDoldurAS kontrol = new MenuDoldurAS(firma_id,sonuc[2][i]);
mRunningTasks.add(kontrol);
}
for (AsyncTask task : mRunningTasks) {
task.execute();
}
}
// AsyncTask2
protected void onPostExecute(...) {
boolean allComplete = true;
for (AsyncTask task : mRunningTasks) {
if (!task.getStatus().equals(AsyncTask.Status.FINISHED)) {
allComplete = false;
break;
}
}
if (allComplete) {
//do whatever
mRunningTasks.clear();
}
}

Related

how to set javafx Togglebutton in javafx Tableview to correct image based on boolean from sqlite database(JDBC)

I am working on a program that is going to allow users to select/add sounds as favorites
via a toggle button with an image in a javafx tableview tablecell and set the status of the sound in the database(the updating of the favorite status in the database works) however the updating of the image only partially works.
when pressing the toggle button the image updates correctly as does the database
initial loading
first 10 records before any favorite selection
after button is pressed
database
but the problem comes when I stop and restart the program because I wind up with none of the buttons selected (sound id 5 should be)
here is the code for the database data loading
public void getSounds() {
soundFilelist.removeAll(soundFilelist);
try {
Connection conn = DriverManager.getConnection("jdbc:sqlite:Sphere.db");
// add where userId = VerifiedUserId or something simular//
String sql = "SELECT * FROM Sounds Where userId = ? ";
PreparedStatement ps;
ResultSet rs;
ps = conn.prepareStatement(sql);
ps.setInt(1 , User.getUserId());
rs = ps.executeQuery();
while (rs.next()) {
int favoriteStatus;
soundFilelist.add(new Sound(
rs.getInt("SoundId") ,
rs.getString("SoundName") ,
rs.getString("soundPath") ,
rs.getLong("soundDurration") ,
favoriteStatus = rs.getInt("Favorite")));
System.out.println(favoriteStatus);
if(favoriteStatus == 0){
setFavoritesTableButton(0);
}else if(favoriteStatus == 1){
setFavoritesTableButton(1);
}
}
soundBrowser.setItems(soundFilelist);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
the addButtoncell code
(favorite column 2) modified from https://riptutorial.com/javafx/example/27946/add-button-to-tableview
private void addButtonToTable() {
Callback<TableColumn<Sound, Void>, TableCell<Sound, Void>> cellFactory = new Callback<TableColumn<Sound, Void>, TableCell<Sound, Void>>() {
#Override
public TableCell<Sound, Void> call(final TableColumn<Sound, Void> param) {
favoritecell = new TableCell<>() {
private final ToggleButton btn = new ToggleButton();
private Image favoritesImage = new Image("SoundSphere/RegularSizeFavoritesImage.png");
private Image favoriteslPressedImage = new Image("SoundSphere/RegularSizeFavoriteslPressedImage.png");
private ImageView tableViewFavorites = new ImageView();
{
tableViewFavorites.setFitWidth(20);
tableViewFavorites.setFitHeight(20);
btn.setAlignment(Pos.CENTER);
// favoritecell.setAlignment(Pos.CENTER);
btn.setGraphic(tableViewFavorites);
btn.setOnAction((new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
if ((btn.isSelected())) {
Sound sound = getTableView().getItems().get(getIndex());
sound.setSoundId(soundIdColumn.getCellData(sound));
System.out.println("selected SID: "+ sound.getSoundId());
int selectedSoundId2 = sound.getSoundId();
tableViewFavorites.setImage(favoriteslPressedImage);
tableviewFavoriteButtonIsPressed = false;
//addFavorite();
System.out.println("buttonselectedId"+ selectedSoundId);
addFavorite2(selectedSoundId2);
}else{
Sound sound = getTableView().getItems().get(getIndex());
sound.setSoundId(soundIdColumn.getCellData(sound));
int selectedSoundId2 = sound.getSoundId();
tableViewFavorites.setImage(favoritesImage);
tableviewFavoriteButtonIsPressed = true;
removeFavorite2(selectedSoundId2);
}
}
private void removeFavorite2(int selectedSoundId2) {
try{
Connection conn = DriverManager.getConnection("jdbc:sqlite:Sphere.db");
String sql = "UPDATE Sounds " +
"SET Favorite = ?"+
// "soundName = ?"+
"Where soundId = ? AND userId = ?";
PreparedStatement ps;
ps = conn.prepareStatement(sql);
ps.setInt(1,0);
ps.setInt(2 , selectedSoundId2);
ps.setInt(3 , User.getUserId());
ps.executeUpdate();
System.out.println("Data has been removed");
}catch(Exception e){
System.out.println("we have a problem with add favorite 2");
e.printStackTrace();
}
}
}));
}
private void addFavorite2(int favoriteSoundId) {
try{
Connection conn = DriverManager.getConnection("jdbc:sqlite:Sphere.db");
String sql = "UPDATE Sounds " +
"SET Favorite = ?"+
// "soundName = ?"+
"Where soundId = ? AND userId = ?";
PreparedStatement ps;
ps = conn.prepareStatement(sql);
ps.setInt(1,1);
ps.setInt(2 , favoriteSoundId);
System.out.println(favoriteSoundId);
ps.setInt(3 , User.getUserId());
ps.executeUpdate();
System.out.println("Data has been inserted");
}catch(Exception e){
System.out.println("we have a problem with add favorite 2");
e.printStackTrace();
}
}
#Override
public void updateItem(Void item , boolean empty) {
super.updateItem(item , empty);
if (btn.isSelected() || dbFavorite) {
tableViewFavorites.setImage(tableFavoriteslPressedImage);
setGraphic(btn);
} if (!btn.isSelected() || !dbFavorite) {
tableViewFavorites.setImage(favoritesImage);
setGraphic(btn);
}
}
};
return favoritecell;
}
};
favoritesColumn2.setCellFactory(cellFactory);
soundBrowser.getColumns().add(favoritesColumn2);
}
public boolean setFavoritesTableButton(int favoriteStatus){
if(favoriteStatus == 1) {
dbFavorite = true;
}else if(favoriteStatus == 0){
dbFavorite = false;
}
return dbFavorite;
}
relevant Intializable code
soundNameColumn.setCellValueFactory(new PropertyValueFactory<>("soundName"));
soundPathColumn.setCellValueFactory(new PropertyValueFactory<>("soundPath"));
soundDurationColumn.setCellValueFactory(new PropertyValueFactory<>("soundDurration"));
favoritesColumn.setCellValueFactory(new PropertyValueFactory<>("Favorite"));
addButtonToTable();
getSounds();
I have tried setting the state of the toggle button in the get sounds method and various Booleans but none of my attempts have worked.
thank you for your time and any help
Thomas Gustafson

Adding reminder to event fails in Android

I have a method which adds an reminder to an event, but it fails:
FATAL EXCEPTION: main
android.database.sqlite.SQLiteException
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:184)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:420)
at android.content.ContentResolver.insert(ContentResolver.java:864)
at de.appwege.droid.medwege.navigationdrawer.TerminFragment.insertReminder(TerminFragment.java:848)
The method in question:
public long insertReminder(long eventID, int minutes){
ContentResolver cr = getActivity().getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.MINUTES, minutes);
values.put(CalendarContract.Reminders.EVENT_ID, eventID);
values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri uri = cr.insert(CalendarContract.Reminders.CONTENT_URI, values);
return Long.valueOf(uri.getLastPathSegment());
}
What I am missing here? both eventID and minutes are defined...
Recently, I also faced same issue. Finally, I found the solution.
First of all, you have to find all logged in gmail id from the device and then select any one gmail account and find its calendar id. After that you have to pass that id to the event query like this....
values.put(Events.CALENDAR_ID, calendarId);
at last call you function
public long insertReminder(long eventID, int minutes){
ContentResolver cr = getActivity().getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.MINUTES, minutes);
values.put(CalendarContract.Reminders.EVENT_ID, eventID);
values.put(CalendarContract.Reminders.METHOD,
CalendarContract.Reminders.METHOD_ALERT);
Uri uri = cr.insert(CalendarContract.Reminders.CONTENT_URI, values);
return Long.valueOf(uri.getLastPathSegment());
}
See below method for finding email id's...
public static Hashtable listCalendarId(Context context) {
try {
if (haveCalendarReadWritePermissions((Activity) context)) {
String projection[] = {"_id", "calendar_displayName"};
Uri calendars;
calendars = Uri.parse("content://com.android.calendar/calendars");
ContentResolver contentResolver = c.getContentResolver();
Cursor managedCursor = contentResolver.query(calendars, projection, null, null, null);
if (managedCursor.moveToFirst()) {
String calName;
String calID;
int cont = 0;
int nameCol = managedCursor.getColumnIndex(projection[1]);
int idCol = managedCursor.getColumnIndex(projection[0]);
Hashtable<String, String> calendarIdTable = new Hashtable<>();
do {
calName = managedCursor.getString(nameCol);
calID = managedCursor.getString(idCol);
Log.v(TAG, "CalendarName:" + calName + " ,id:" + calID);
calendarIdTable.put(calName, calID);
cont++;
} while (managedCursor.moveToNext());
managedCursor.close();
return calendarIdTable;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

Vala GTK+. Issue with customized widget

I need to create a gtk.Entry which accepts only numbers. but I can't overwrite the key_press_event event in an heredited class. It only works if I use the original Entry by means of connect function.
What am I doing wrong?
using Gtk;
public class NumberEntry : Entry {
public void NumberEntry(){
add_events (Gdk.EventMask.KEY_PRESS_MASK);
}
//With customized event left entry editing is not possible
public override bool key_press_event (Gdk.EventKey event) {
string numbers = "0123456789.";
if (numbers.contains(event.str)){
return false;
} else {
return true;
}
}
}
public class Application : Window {
public Application () {
// Window
this.title = "Entry Issue";
this.window_position = Gtk.WindowPosition.CENTER;
this.destroy.connect (Gtk.main_quit);
this.set_default_size (350, 70);
Grid grid = new Grid();
grid.set_row_spacing(8);
grid.set_column_spacing(8);
Label label_1 = new Label ("Customized Entry, useless:");
grid.attach (label_1,0,0,1,1);
//Customized Entry:
NumberEntry numberEntry = new NumberEntry ();
grid.attach(numberEntry, 1, 0, 1, 1);
Label label_2 = new Label ("Working only numbers Entry:");
grid.attach (label_2,0,1,1,1);
//Normal Entry
Entry entry = new Entry();
grid.attach(entry, 1, 1, 1, 1);
this.add(grid);
//With normal Entry this event works well:
entry.key_press_event.connect ((event) => {
string numbers = "0123456789.";
if (numbers.contains(event.str)){
return false;
} else {
return true;
}
});
}
}
public static int main (string[] args) {
Gtk.init (ref args);
Application app = new Application ();
app.show_all ();
Gtk.main ();
return 0;
}
The key_press_event of the superclass is no longer being called. You need to call the base class and return true when you have consumed the key.
public override bool key_press_event (Gdk.EventKey event) {
string numbers = "0123456789.";
if (numbers.contains(event.str)){
return base.key_press_event (event);
} else {
return true;
}
}
If you return false in a signal, this can be passed to an alternate handler, but only if you use connect and not override the signal method.

JavaFX: ConcurrentModificationException while adding TreeItem objects in TreeView, in a seperate thread

I have the following code
public void start(Stage primaryStage) {
BorderPane border_pane = new BorderPane();
TreeView tree = addTreeView(); //TreeView on the LEFT
border_pane.setLeft(tree);
/* more stuff added to the border_pane here... */
Scene scene = new Scene(border_pane, 900, 700);
scene.setFill(Color.GHOSTWHITE);
primaryStage.setTitle("PlugControl v0.1e");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
With addTreeView being a function that reads data off an SQL DB and adds around ~35 TreeItems, based on that data. The addition of TreeItems to treeItemRoot is done in a seperate thread. NOTE: treeItemRoot is declared in the main class, and is null before here.
public TreeView addTreeView() { //Our treeView is positioned on the LEFT
treeItemRoot = new PlugTreeItem<>("Active Plugs", new ImageView(new Image(getClass().getResourceAsStream("graphics/plugicon.png"))), new Plug()); //Root of the tree, contains a dummy Plug object.
selectedTreeItem = treeItemRoot;
treeItemRoot.setExpanded(true); //always expand it
selectedTreeItem.getPlugItem()
.getSIHUid().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue
) {
System.err.println("changed " + oldValue + "->" + newValue);
}
}
);
TreeView<String> treeView = new TreeView<>(treeItemRoot); //Build the tree with our root node.
final Task task;
task = new Task<Void>() {
#Override
protected Void call() throws Exception {
//=========== SQL STUFF BEGINS HERE ============================
Statement sta = null;
ResultSet result_set = null;
Connection conn = null;
try {
try {
System.err.println("Loading JDBC driver...");
Class.forName("com.mysql.jdbc.Driver");
System.err.println("Driver loaded!");
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot find JDBC driver in the classpath!", e);
}
System.err.println("Connecting to database...");
conn = DriverManager.getConnection("[DB link here]", "[username]", "[password]"); //Username is PlugControl, pw is woof
System.err.println("Connected to Database!");
sta = conn.createStatement();
String sql_query = "SELECT * FROM pwnodes INNER JOIN pwcomports ON pwnodes.NetworkID = pwcomports.NetworkID WHERE pwnodes.connection = 'on' ORDER BY pwnodes.Location";
result_set = sta.executeQuery(sql_query);
System.err.println("SQL query successfuly executed!");
int count = 0;
while (result_set.next()) {
Plug pl = null; //MARKER: We might need to do switch (result_set.getString("Server")) for SIHU1 and SIHU2.
count++;
pl = new Plug(result_set.getString("SIHUid"), result_set.getString("sensorID"), result_set.getString("Location"), result_set.getString("Appliance"), result_set.getString("Type"), result_set.getString("connection"), result_set.getString("Server"), result_set.getString("ServerIP"));
PlugTreeItem<String> pti = new PlugTreeItem(pl.getSIHUid().getValue() + " " + pl.getLocation() + " " + pl.getAppliance(), new ImageView(new Image(getClass().getResourceAsStream("graphics/smiley.png"))), pl); //icon does not work in children
treeItemRoot.getChildren().add(pti); //CONCURRENCY ERRORS HERE
}
System.err.println("ALERT SQL QUERY RESULTS: " + count);
} catch (SQLException e) //linked try clause # line 50
{
throw new RuntimeException("Cannot connect the database!", e);
} finally { // Time to wrap things up, by closing all open SQL procs.
try {
if (sta != null) {
sta.close();
}
if (result_set != null) {
result_set.close();
}
if (conn != null) {
System.err.println("Closing the connection.");
conn.close();
}
} catch (SQLException e) //We might as well ignore this, but just in case.
{
throw new RuntimeException("Error while closing up statement, result set and connection!", e);
}
}
//============== SQL STUFF ENDS HERE ===========================
System.err.println("Finished");
return null;
}
};
new Thread(task).start(); //Run the task!
treeView.getSelectionModel()
.selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue
) {
selectedTreeItem = (PlugTreeItem<String>) newValue;
System.err.println("DEBUG: Selection plug SIHUid: " + selectedTreeItem.getPlugItem().print()); //MARKER: REMOVE
updateTextFields(); //Update TextAreas.
if (!"DUMMY".equals(selectedTreeItem.getPlugItem().getSIHUid().getValue())) {
buttonOn.setDisable(false);
buttonOff.setDisable(false);
} else {
buttonOn.setDisable(true);
buttonOff.setDisable(true);
}
}
}
);
return treeView;
}
Once every 5-6 runs I receive a ConcurrentModificationException because I think the Thread task() doesn't manage to finish before addTreeView's returned TreeView is added to the border_pane, and maybe it begins iterating through it while it's still having items added to it?
Executing C:\Users\74\Documents\NetBeansProjects\PlugControl_v0.5\dist\run1559674105\PlugControl.jar using platform C:\Program Files\Java\jdk1.7.0_25\jre/bin/java
Loading JDBC driver...
Driver loaded!
Connecting to database...
Connected to Database!
SQL query successfuly executed!
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at com.sun.javafx.collections.ObservableListWrapper$ObservableListIterator.next(ObservableListWrapper.java:681)
at javafx.scene.control.TreeItem.updateExpandedDescendentCount(TreeItem.java:788)
at javafx.scene.control.TreeItem.getExpandedDescendentCount(TreeItem.java:777)
at javafx.scene.control.TreeView.getExpandedDescendantCount(TreeView.java:864)
at javafx.scene.control.TreeView.updateTreeItemCount(TreeView.java:873)
at javafx.scene.control.TreeView.impl_getTreeItemCount(TreeView.java:533)
at com.sun.javafx.scene.control.skin.TreeViewSkin.getItemCount(TreeViewSkin.java:207)
at com.sun.javafx.scene.control.skin.TreeViewSkin.updateItemCount(TreeViewSkin.java:220)
at com.sun.javafx.scene.control.skin.TreeViewSkin.handleControlPropertyChanged(TreeViewSkin.java:135)
at com.sun.javafx.scene.control.skin.SkinBase$3.changed(SkinBase.java:282)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:107)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.IntegerPropertyBase.fireValueChangedEvent(IntegerPropertyBase.java:123)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:130)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:163)
at javafx.scene.control.TreeView.setTreeItemCount(TreeView.java:515)
at javafx.scene.control.TreeView.updateTreeItemCount(TreeView.java:876)
at javafx.scene.control.TreeView.impl_getTreeItemCount(TreeView.java:533)
at javafx.scene.control.TreeCell.updateItem(TreeCell.java:391)
at javafx.scene.control.TreeCell.access$000(TreeCell.java:67)
at javafx.scene.control.TreeCell$1.invalidated(TreeCell.java:95)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:195)
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:161)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:130)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:163)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:112)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1596)
at com.sun.javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:1049)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1005)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellCount(VirtualFlow.java:206)
at com.sun.javafx.scene.control.skin.TreeViewSkin.updateItemCount(TreeViewSkin.java:225)
at com.sun.javafx.scene.control.skin.TreeViewSkin.handleControlPropertyChanged(TreeViewSkin.java:135)
at com.sun.javafx.scene.control.skin.SkinBase$3.changed(SkinBase.java:282)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:107)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.IntegerPropertyBase.fireValueChangedEvent(IntegerPropertyBase.java:123)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:130)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:163)
at javafx.scene.control.TreeView.setTreeItemCount(TreeView.java:515)
at javafx.scene.control.TreeView.updateTreeItemCount(TreeView.java:876)
at javafx.scene.control.TreeView.impl_getTreeItemCount(TreeView.java:533)
at javafx.scene.control.TreeCell.updateItem(TreeCell.java:391)
at javafx.scene.control.TreeCell.access$000(TreeCell.java:67)
at javafx.scene.control.TreeCell$1.invalidated(TreeCell.java:95)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:195)
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:161)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:130)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:163)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:112)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1596)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1500)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1523)
at com.sun.javafx.scene.control.skin.VirtualFlow$3.call(VirtualFlow.java:478)
at com.sun.javafx.scene.control.skin.VirtualFlow$3.call(VirtualFlow.java:476)
at com.sun.javafx.scene.control.skin.PositionMapper.computeViewportOffset(PositionMapper.java:143)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1001)
at javafx.scene.Parent.layout(Parent.java:1018)
at javafx.scene.Parent.layout(Parent.java:1028)
at javafx.scene.Parent.layout(Parent.java:1028)
at javafx.scene.Parent.layout(Parent.java:1028)
at javafx.scene.Scene.layoutDirtyRoots(Scene.java:516)
at javafx.scene.Scene.doLayoutPass(Scene.java:487)
at javafx.scene.Scene.access$3900(Scene.java:170)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2203)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:363)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:460)
at com.sun.javafx.tk.quantum.QuantumToolkit$9.run(QuantumToolkit.java:329)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:724)
ALERT SQL QUERY RESULTS: 35
Closing the connection.
Finished
Any help/advice on dealing with the issue, guys? The exception doesn't point me towards a place in my code, and so far I'm working on hunches.}
EDIT: For reference, PlugTreeItem is just a TreeItem<> that also carries a Plug with it, Plug being a class of mine that holds a few String values. Nothing special.
public class PlugTreeItem<T> extends TreeItem{ \* code *\}
I would suggest you to make a List<Plug> inside your while loop rather than making individual object and adding it to the tree, because all operations on javafx controls must be done on javafx thread and not on task thread !
Create a list outside the Thread body
List<Plug> listOfPlugs = new ArrayList<Plug>();
Then, in the while loop, you can write
int count = 0;
while (result_set.next()) {
Plug pl = null;
count++;
pl = new Plug(result_set.getString("SIHUid"),
result_set.getString("sensorID"), result_set.getString("Location"),
result_set.getString("Appliance"), result_set.getString("Type"),
result_set.getString("connection"), result_set.getString("Server"),
result_set.getString("ServerIP"));
listOfPlugs.add(p1);
}
Later, after you start the thread you can make the following code
new Thread(task).start();
task.setOnSucceeded(new EventHandler<WorkerStateEvent>()
{
#Override
public void handle(WorkerStateEvent workerStateEvent) {
for(Plug p1 : listOfPlugs)
{
PlugTreeItem<String> pti = new PlugTreeItem(pl.getSIHUid().getValue()
+ " " + pl.getLocation() + " " + pl.getAppliance(),
new ImageView(new Image(
getClass().getResourceAsStream("graphics/smiley.png"))), pl);
treeItemRoot.getChildren().add(pti);
}
}
I don't see you syncing on the javafx application thread which is required when coming from another one

Updating a datatable in Wicket

We are developing a new application in Wicket and have run into a small problem.
What we do:
1) create a new SortableDataProvider
2) create a new DefaultDataTablePagingInBottom
3) create a new WebMarkupContainer
4) add the DefaultDataTablePagingInBottom to the WebMarkupContainer
5) create a new AjaxCheckBox
6) in the onUpdate of the AjaxCheckBox, add the WebMarkupContainer to the AjaxRequestTarget
7) set the SortableDataProvider to a new SortableDataProvider (with the updated query)
8) DefaultDataTablePagingInBottom.replaceWith(new DefaultDataTablePagingInBottom - with the new provider).
What happends:
1) Click the checkbox -> nothing happends.
2) Click it again -> crash: "Last cause: This method can only be called on a component that has already been added to its parent.
WicketMessage: Method onRequest of interface org.apache.wicket.behavior.IBehaviorListener targeted at org.apache.wicket.ajax.markup.html.form.AjaxCheckBox$1#1a2fefd on component [ [Component id = checkBox]] threw an exception"
3) Click back in the browser -> the list i filtered with the new provider.
Any ideas?
---EDIT---
Here's some code.
1) In the constructor of the WebPage:
model = new Model(projectPlannerService);
provider = new SortableProjectDataProvider(model, (WebSession) getSession(), isChecked);
table = new DefaultDataTablePagingInBottom("table", columns, provider, 50);
listContainer = new WebMarkupContainer("wmc");
listContainer.add(table);
add(listContainer.setOutputMarkupId(true));
/*
* checkbox för filtrering
*/
AjaxCheckBox checkBox = new AjaxCheckBox("checkBox", new Model()) {
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(listContainer, "wmc");
isChecked = !isChecked;
provider = new SortableProjectDataProvider(model, (WebSession) getSession(), isChecked);
updateTable();
}
};
add(checkBox);
2) In updateTable():
table.replaceWith(new DefaultDataTablePagingInBottom("table", columns, provider, 50));
3) The SortableProjectDataProvider:
// Constructor
public SortableProjectDataProvider(IModel<?> model, WebSession webSession, boolean isChecked) {
this.model = model;
this.projectPlannerService = (ProjectPlannerService) model.getObject();
this.webSession = webSession;
setSort("customer", SortOrder.ASCENDING);
System.out.println("ischecked:" + isChecked);
if(!isChecked)
list = ((ProjectPlannerService) model.getObject()).findAllProjects();
else
list = ((ProjectPlannerService) model.getObject()).findAllActiveProjects();
System.out.println("size: " + list.size());
comparator = new ProjectComparator();
}
public Iterator<Project> iterator(int first, int count) {
Collections.sort(list, comparator);
if (first > list.size()) {
first = 0;
}
if (first + count > list.size()) {
return list.subList(first, list.size()).iterator();
} else {
return list.subList(first, first + count).iterator();
}
}
public IModel<Project> model(Project object) {
return new DetachableProjectModel((Project) object);
}
public int size() {
return list.size();
}
private class DetachableProjectModel extends LoadableDetachableModel {
private Long id;
#SpringBean
ProjectPlannerService projectPlannerService;
public DetachableProjectModel(Long id) {
Injector.get().inject(this);
if (id == null) {
throw new IllegalArgumentException();
}
this.id = id;
}
public DetachableProjectModel(Project project) {
this(project.getPk());
Injector.get().inject(this);
}
public int hashCode() {
return id.hashCode();
}
public boolean equals(final Object obj) {
if (obj == this) {
return true;
} else if (obj == null) {
return false;
} else if (obj instanceof DetachableProjectModel) {
DetachableProjectModel other = (DetachableProjectModel) obj;
return other.id == this.id;
}
return false;
}
protected Object load() {
return ((ProjectPlannerService) model.getObject()).findProjectById(id);
}
}
}
wicket:extend
-input wicket:id="checkBox" type="checkbox"- Show active -/input-
-div wicket:id="wmc"-
-table wicket:id="table"--/table-
-/div-
-/wicket:extend-
Thanks in advance!
/Andreas
By replacing the instance of your SortableProjectDataProvider with a new one you are making your life difficult. Instead of using the boolean isChecked in the constructor you could use an IModel<Boolean>. Assign the same instance of that model to your data provider and the check-box and you are done. No need to replace anything in onUpdate, add your listContainer to the AjaxRequestTarget and everything should just work...
e.g.
...
private IModel<Boolean> isCheckedModel = new Model<Boolean>(Boolean.FALSE);
...
provider = new SortableProjectDataProvider(model, (WebSession) getSession(), isCheckedModel);
...
AjaxCheckBox checkBox = new AjaxCheckBox("checkBox", isCheckedModel) {
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(listContainer);
}
};
...
It is almost never a good idea to replace such things with new ones in Wicket. Encapsulate what changes in a model and change / replace the model's object. Every object that has a reference to that model can see the updated value or change it as needed.
Hope this helps.
Try this:
Wrong: target.add(listContainer, "wmc");
Right: target.add(listContainer);
Wrong; table.replaceWith(new DefaultDataTablePagingInBottom("table", columns, provider, 50));
Right: DefaultDataTablePagingInBottom tmp = new DefaultDataTablePagingInBottom("table", columns, provider, 50);
table.replaceWith(tmp);
table = tmp;
(You replace the DefaultDataTablePagingInBottom but not your reference.)
//olle

Resources