How to use iText7 to convert HTML to PDF with mixed page orientations while preserving the CSS - itext7

I need to change the page orientation of some parts of a HTML. I followed the accepted answer for this question but the resulting PDF document had neither header nor footer (actually, no style at all).
Here is my first attempt:
package my.awesome.app.html2pdf;
import static com.itextpdf.styledxmlparser.css.media.MediaType.PRINT;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.attach.ITagWorker;
import com.itextpdf.html2pdf.attach.ProcessorContext;
import com.itextpdf.html2pdf.attach.impl.DefaultTagWorkerFactory;
import com.itextpdf.html2pdf.attach.impl.tags.DivTagWorker;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.IPropertyContainer;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Div;
import com.itextpdf.layout.element.IBlockElement;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.renderer.AreaBreakRenderer;
import com.itextpdf.styledxmlparser.css.media.MediaDeviceDescription;
import com.itextpdf.styledxmlparser.node.IElementNode;
#RestController
#RequestMapping("/html2pdf")
public class Html2PdfController {
#PostMapping(produces = MediaType.APPLICATION_PDF_VALUE)
public #ResponseBody byte[] convert(#RequestBody String html) throws IOException {
try (var baos = new ByteArrayOutputStream()) {
var mediaDeviceDescription = new MediaDeviceDescription(PRINT);
var converterProperties = new ConverterProperties();
converterProperties.setMediaDeviceDescription(mediaDeviceDescription);
var pdfDocument = new PdfDocument(new PdfWriter(baos));
converterProperties.setTagWorkerFactory(new CustomTagWorkerFactory(pdfDocument));
var document = new Document(pdfDocument);
var elements = HtmlConverter.convertToElements(html, converterProperties);
for (var element : elements) {
if (element instanceof IBlockElement) {
document.add((IBlockElement) element);
}
}
pdfDocument.close();
return baos.toByteArray();
}
}
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
PdfDocument pdfDocument;
public CustomTagWorkerFactory(PdfDocument pdfDocument) {
this.pdfDocument = pdfDocument;
}
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if ("landscape".equalsIgnoreCase(tag.name())) {
return new LandscapeDivTagWorker(tag, context, pdfDocument);
}
return null;
}
}
private static class LandscapeDivTagWorker extends DivTagWorker {
private PdfDocument pdfDocument;
public LandscapeDivTagWorker(IElementNode tag, ProcessorContext context, PdfDocument pdfDocument) {
super(tag, context);
this.pdfDocument = pdfDocument;
}
#Override
public IPropertyContainer getElementResult() {
IPropertyContainer baseElementResult = super.getElementResult();
if (baseElementResult instanceof Div) {
var div = new Div();
var landscapeAreaBreak = new AreaBreak(new PageSize(PageSize.A4).rotate());
landscapeAreaBreak.setNextRenderer(
new DefaultPageSizeChangingAreaBreakRenderer(landscapeAreaBreak, pdfDocument));
div.add(landscapeAreaBreak);
div.add((IBlockElement) baseElementResult);
var portraitAreaBreak = new AreaBreak(new PageSize(PageSize.A4));
portraitAreaBreak.setNextRenderer(
new DefaultPageSizeChangingAreaBreakRenderer(portraitAreaBreak, pdfDocument));
div.add(portraitAreaBreak);
baseElementResult = div;
}
return baseElementResult;
}
}
private static class DefaultPageSizeChangingAreaBreakRenderer extends AreaBreakRenderer {
private PdfDocument pdfDocument;
private AreaBreak areaBreak;
public DefaultPageSizeChangingAreaBreakRenderer(AreaBreak areaBreak, PdfDocument pdfDocument) {
super(areaBreak);
this.pdfDocument = pdfDocument;
this.areaBreak = areaBreak;
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
pdfDocument.setDefaultPageSize(areaBreak.getPageSize());
return super.layout(layoutContext);
}
}
}
And here is my first result. There is an additional blank page at its end:
After some small changes in the main method:
#PostMapping(produces = MediaType.APPLICATION_PDF_VALUE)
public #ResponseBody byte[] convert(#RequestBody String html) throws IOException {
try (var baos = new ByteArrayOutputStream()) {
var mediaDeviceDescription = new MediaDeviceDescription(PRINT);
var converterProperties = new ConverterProperties();
converterProperties.setMediaDeviceDescription(mediaDeviceDescription);
var pdfDocument = new PdfDocument(new PdfWriter(baos));
converterProperties.setTagWorkerFactory(new CustomTagWorkerFactory(pdfDocument));
var document = HtmlConverter.convertToDocument(html, pdfDocument, converterProperties);
document.close();
pdfDocument.close();
return baos.toByteArray();
}
}
I've got this PDF with nice headers and footers, except for the rotated pages. Also, only the first in a series is in landscape mode:
Actually the landscape pages do have footers, but they are misaligned.
Is there a way to achieve this using iText7 HTML to PDF conversion?

Related

Is this ClassCastException a HtmlUnit bug?

I'm new to htmlunit (2.23) and I can't get this test to work:
I'm getting this ClassCastException thrown out of HtmlUnit and I don't know if it is a bug, or if I am doing something wrong.
java.lang.ClassCastException: com.gargoylesoftware.htmlunit.TextPage cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlPage
at com.gargoylesoftware.htmlunit.WebClient.makeWebResponseForJavaScriptUrl(WebClient.java:1241)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:375)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:304)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:451)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:436)
at org.wyttenbach.dale.mlec.OutageTest.test(OutageTest.java:46)
...
The code
import java.awt.Desktop;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.JavaScriptPage;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.TextPage;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class OutageTest {
private static final String SITE_URL = "https://ebill.mlecmn.net/woViewer/";
private static final String OUTAGE_MAP_URL = SITE_URL + "mapviewer.html?config=Outage+Web+Map";
#Test
public void test() throws FailingHttpStatusCodeException, MalformedURLException, IOException {
try (final WebClient webClient = new WebClient()) {
webClient.waitForBackgroundJavaScript(20000);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setUseInsecureSSL(true);
Map<String, Page> urls = new HashMap<String, Page>();
LinkedList<String> urlsToVisit = new LinkedList<String>();
urlsToVisit.add(OUTAGE_MAP_URL);
while (!urlsToVisit.isEmpty()) {
String url = urlsToVisit.remove();
if (urls.containsKey(url)) {
continue;
}
Page page = webClient.getPage(url);
urls.put(url, page);
if (page instanceof HtmlPage) {
HtmlPage page2 = (HtmlPage) page;
System.err.println("================================================================");
System.err.println(page2.asXml());
System.err.println("================================================================");
Assert.assertFalse("Outage in Nordland township: " + url, page2.asText().contains("Nordland"));
urlsToVisit.addAll(extractLinks(page2));
} else if (page instanceof JavaScriptPage) {
JavaScriptPage page2 = (JavaScriptPage) page;
Assert.assertFalse("Outage in Nordland township: " + url, page2.getContent().contains("Nordland"));
} else if (page instanceof TextPage) {
TextPage page2 = (TextPage) page;
Assert.assertFalse("Outage in Nordland township: " + url, page2.getContent().contains("Nordland"));
} else {
System.err.println(String.format("%s => %s", url, page.getClass().getName()));
}
}
} catch (AssertionError e) {
reportOutage();
throw e;
}
}
private Collection<String> extractLinks(HtmlPage page) {
List<String> links = new ArrayList<String>();
for (DomElement x : page.getElementsByTagName("script")) {
String src = x.getAttribute("src");
if (!src.contains(":")) {
src = SITE_URL + src;
System.err.println("script src="+src);
}
links.add(src);
}
for (DomElement x : page.getElementsByTagName("link")) {
String href = x.getAttribute("href");
if (!href.contains(":")) {
href = SITE_URL + href;
System.err.println("link href="+href);
}
links.add(href);
}
// Causes ClassCastException com.gargoylesoftware.htmlunit.TextPage cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlPage
//at com.gargoylesoftware.htmlunit.WebClient.makeWebResponseForJavaScriptUrl(WebClient.java:1241)
for (DomElement x : page.getElementsByTagName("iframe")) {
String src = x.getAttribute("src");
if (!src.contains(":")) {
src = SITE_URL + src;
System.err.println("iframe src="+src);
}
links.add(src);
}
return links;
}
private void reportOutage() {
try {
Desktop.getDesktop().browse(new URI(OUTAGE_MAP_URL));
} catch (Exception e) {
e.printStackTrace();
}
}
}
More or less yes - but i have to do a more deeper analysis.
But there is some hope for you ;-)
Your code tries to extract urls from a given web page. During the process you are adding the url 'javascript:""' to your list of urls to be processes. This url results in this class cast exception. If you do not add this url to the list, the test is working (at least for me).

Get row from selected cell in TableView in JavaFX when setCellSelectionEnabled(true)

I have the following code which works great when I have standard row selection (always single, never multi).
//This is needed to set the X & Y coordinates of the stage for edit.
myTable.setRowFactory(tableView -> {
TableRow<MyDTO> row = new TableRow<MyDTO>();
row.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
lastSelectedRow.set(row);
}
});
return row ;
});
I am using the row to get the bounds in parent so that when a user selects to edit that row, I can pop a modal window up under the row for them to edit this.
However, my table is also editable for the common fields where there is no look up needed, etc. In that case I want to edit in the table. All this is working, however to make it more user friendly, I want to have cell selection turned on, but when I do that, the row.selectedProptery() listener doesn't fire.
How can I accomplish that, without trying to listen to the selectedProperty() of each cell?
Thanks
I don't think there's a way to do this without registering a listener with the selection property of each cell, via a cell factory on each table column.
However, this isn't too difficult, and can be done both generically (i.e. with the same code no matter the type of the table column) and also respecting any other cell factory behavior you need. Here is a SSCCE:
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
public class SelectedTableCellTracking extends Application {
private final ObjectProperty<TableCell<?,?>> selectedCell = new SimpleObjectProperty<>();
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
TableColumn<Item, String> itemCol = column("Item", Item::nameProperty);
TableColumn<Item, Number> valueCol = column("Value", Item::valueProperty);
table.getColumns().add(itemCol);
table.getColumns().add(valueCol);
Random rng = new Random();
for (int i = 1 ; i <= 100; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(1000)));
}
table.getSelectionModel().setCellSelectionEnabled(true);
Rectangle highlight = new Rectangle();
highlight.setManaged(false);
highlight.setHeight(12);
highlight.setFill(Color.CORAL);
StackPane root = new StackPane(table, highlight);
selectedCell.addListener((obs, oldCell, newCell) -> {
if (newCell == null) {
highlight.setVisible(false);
} else {
highlight.setVisible(true);
highlight.setX(newCell.localToScene(newCell.getBoundsInLocal()).getMinX());
highlight.setWidth(newCell.getWidth());
highlight.setY(newCell.localToScene(newCell.getBoundsInLocal()).getMaxY());
}
});
table.getColumns().forEach(this::addCellSelectionListenerToColumn);
Scene scene = new Scene(root, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> void addCellSelectionListenerToColumn(TableColumn<S,T> col) {
Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = col.getCellFactory();
col.setCellFactory(tc -> {
TableCell<S,T> cell = currentCellFactory.call(tc);
cell.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
if (isNowSelected) {
selectedCell.set(cell);
}
});
return cell ;
});
}
private static <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}

XY Scatter AndroidPlot

Attempting to use AndroidPlot to create an XY scatter plot, encountering a problem... whereby the plot only draws points from left to right, a scrolling chart essentially.
Example... say I have the following co-ordinates, (0,1), (1,0), (0,-1), (-1,0) I would expect to see a diamond shape (if all the points were joined by a line)
I've used the AndroidPlot library successfully before so am somewhat familiar with the methods available.
Is there any examples for a scatter plot using the AndroidPlot library?
Hope I'm making sense here..
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import pl.flex_it.androidplot.XYSeries;
import com.androidplot.series.XYSeries;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
import android.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Temp extends Fragment {
private static XYPlot xyPlot;
private XYSeriesShimmer series;
private LineAndPointFormatter series1Format;
private ArrayList<Number> ALdata1, ALdata2;
private int Adata1[], Adata2[];
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_test, container, false);
// Import plot from the layout
xyPlot = (XYPlot) rootView.findViewById(R.id.xyPlot);
xyPlot.setDomainBoundaries(-2, 2, BoundaryMode.FIXED); // freeze the domain boundary:
xyPlot.setRangeBoundaries(-2, 2, BoundaryMode.FIXED);
ALdata1 = new ArrayList<Number>();
ALdata2 = new ArrayList<Number>();
ALdata1.clear();
ALdata2.clear();
Adata1 = new int[]{0,1,0,-1};
Adata2 = new int[]{1,0,-1,0};
series = new XYSeriesShimmer(ALdata1, ALdata2, 0, "Sightings in USA");
series1Format = new LineAndPointFormatter(Color.TRANSPARENT, Color.BLACK, null); // line color, point color, fill color
xyPlot.addSeries(series, series1Format);
plotDataMethod();
return rootView;
}
private void plotDataMethod() {
for(int i=0; i<Adata1.length; i++){
ALdata1.add(Adata1[i]);
ALdata2.add(Adata2[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
series.updateData(ALdata1, ALdata2);
xyPlot.redraw();
}
}
}
EDIT:
package pl.flex_it.androidplot;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.androidplot.series.XYSeries;
public class XYSeriesShimmer implements XYSeries {
private List<Number> dataX;
private List<Number> dataY;
private int seriesIndex;
private String title;
public XYSeriesShimmer(List<Number> datasource, int seriesIndex, String title) {
this.dataY = datasource;
this.seriesIndex = seriesIndex;
this.title = title;
}
public XYSeriesShimmer(List<Number> datasourceX, List<Number> datasourceY, int seriesIndex, String title) {
this.dataX = datasourceX;
this.dataY = datasourceY;
this.seriesIndex = seriesIndex;
this.title = title;
}
#Override
public String getTitle() {
return title;
}
#Override
public int size() {
return dataY.size();
}
#Override
public Number getY(int index) {
return dataY.get(index);
}
#Override
public Number getX(int index) {
return index;
}
public void updateData(List<Number> datasourceX){ //dont need to use this cause, the reference is only stored, modifying the datasource externally will cause this to be updated as well
this.dataY=datasourceX;
}
public void updateData(List<Number> datasourceX, List<Number> datasourceY){ //dont need to use this cause, the reference is only stored, modifying the datasource externally will cause this to be updated as well
this.dataX=datasourceX;
this.dataY=datasourceY;
}
}
This looks like it could be the problem - in XYSeriesShimmer:
#Override
public Number getX(int index) {
return index;
}
This is always going to return i, which means each element's x value is 1 larger than the previous...exactly what you are experiencing. Try changing it to this:
#Override
public Number getX(int index) {
return dataX.get(i);
}

How to Customize my ListView by adding an image on left

I just would to customize my ListView with an image on the left
package com.project.test;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.R.id;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class ContactUs extends ListActivity {
// Progress Dialog
private ProgressDialog pDialog;
// Creating JSON Parser object
JSONParser jParser = new JSONParser();
ListView list;
LazyAdapter adapter;
ArrayList<HashMap<String, String>> contactsList;
// url to get all contacts list
private static String url_all_contacts = "http://10.0.2.2/test/get_all_staff.php";
// JSON Node names
private static final String TAG_SUCCESS = "success";
private static final String TAG_CONTACT = "contacts";
private static final String TAG_PID = "pid";
private static final String TAG_NAME = "name";
private static final String TAG_IMAGE = "image";
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
// contacts JSONArray
JSONArray contacts = null;
ImageView img = (ImageView)findViewById(R.id.image);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.all_staff);
// Hashmap for ListView
contactsList = new ArrayList<HashMap<String, String>>();
// Loading contacts in Background Thread
new LoadAllcontacts().execute();
//list = getListView();
// Get listview
//ListView lv = getListView();
// on seleting single product
// launching Edit Product Screen
/*
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String pid = ((TextView) view.findViewById(R.id.pid)).getText()
.toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(),
GetAllStaffDetails.class);
// sending pid to next activity
in.putExtra(TAG_PID, pid);
// starting new activity and expecting some response back
startActivityForResult(in, 100);
}
});
*/
}
// Response from Edit Product Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// if result code 100
if (resultCode == 100) {
// if result code 100 is received
// means user edited/deleted product
// reload this screen again
Intent intent = getIntent();
finish();
startActivity(intent);
}
}
/**
* Background Async Task to Load all product by making HTTP Request
* */
class LoadAllcontacts extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ContactUs.this);
pDialog.setMessage("Loading contacts. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All contacts from url
* */
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_contacts, "GET",
params);
// Check your log cat for JSON reponse
Log.d("All contacts: ", json.toString());
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// contacts found
// Getting Array of contacts
contacts = json.getJSONArray(TAG_CONTACT);
// looping through All contacts
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
// Storing each json item in variable
String id = c.getString(TAG_PID);
String name = c.getString(TAG_NAME);
String image = c.getString(TAG_IMAGE);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_PID, id);
map.put(TAG_NAME, name);
// adding HashList to ArrayList
contactsList.add(map);
}
//list = (ListView)findViewById(id.list);
//list.setAdapter(contactsList);
} else {
// no contacts found
// Launch Add New product Activity
Intent i = new Intent(getApplicationContext(),
NewProductActivity.class);
// Closing all previous activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all contacts
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
//adapter=new LazyAdapter(this, contactsList);
ListAdapter adapter = new SimpleAdapter(ContactUs.this,
contactsList, R.layout.list_row, new String[] {
TAG_PID, TAG_NAME }, new int[] { R.id.pid,
R.id.name });
// updating listview
setListAdapter(adapter);
}
});
}
}
}
This is the code am using right now, but I had some difficulties in how to retrieve an image from data base using JSON then insert the image to the ListView. So any help please ??
Provide more details if you wonna get answer.
From which field you wonna get image? This is an url, filesystem ref or may be base64 data, or...
In your layout (R.layout.list_row) you should have an ImageView into which you can set any kind of Drawable object to be displayed.
And remove runOnUiThread call, because in onPostExecute you already on UI thread.

How to populate TableView data on the other screen TextField in JavaFX 2.0

I am having problem in populating data from a table in one screen to a Text Field in the other screen. I have two classes FirstClass containing a textbox and a button. On pressing a button a second window is opened containing a Table of values. As the user double clicks a row the value of the second column of the row should be inserted into the textbox of the FirstClass. Code of both the classes is attached. Thanking you in anticipation.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FirstClass extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage primaryStage) {
primaryStage.setTitle("First Class");
GridPane gridpane = new GridPane();
gridpane.setPadding(new Insets(5));
gridpane.setHgap(5);
gridpane.setVgap(5);
final TextField userNameFld = new TextField();
gridpane.add(userNameFld, 1, 1);
Button btn = new Button();
btn.setText("Show Table");
gridpane.add(btn, 1, 3);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
String a = TableClass.showDialog(primaryStage, true, "Table Window" );
userNameFld.setText(a);
}
});
StackPane root = new StackPane();
Scene scene =new Scene(root, 300, 250);
root.getChildren().addAll(gridpane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class TableClass extends Stage {
private static TableClass dialog;
private static String value = "";
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private Person(String fName, String lName) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
private TableView<Person> table = new TableView<Person>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("JACK", "BROWN"),
new Person("JOHN", "VIANNEYS"),
new Person("MICHAEL", "NELSON"),
new Person("WILLIAM", " CAREY")
);
public TableClass(Stage owner, boolean modality, String title) {
super();
initOwner(owner);
Modality m = modality ? Modality.APPLICATION_MODAL : Modality.NONE;
initModality(m);
setOpacity(1);
setTitle(title);
StackPane root = new StackPane();
Scene scene = new Scene(root, 750, 750);
setScene(scene);
GridPane gridpane = new GridPane();
gridpane.setPadding(new Insets(5));
gridpane.setHgap(5);
gridpane.setVgap(5);
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person,String>("firstName")
);
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(200);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person,String>("lastName")
);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol);
table.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
if (me.getClickCount() >= 2) {
String srr = table.getItems().get (table.getSelectionModel().getSelectedIndex()).getLastName();
value = srr;
dialog.hide();
}
}
});
gridpane.add(table, 1, 5,1,20 );
root.getChildren().add(gridpane);
}
public static String showDialog(Stage stg, Boolean a , String title){
dialog = new TableClass( stg,a, title);
dialog.show();
return value;
}
}
The quick and easy way (but it introduces coupling between the 2 classes) would be to pass userNameFld to your showDialog method and make it a member of TableClass. You can then change its value from the TableClass class.
A better way would be to bind the value of userNameFld to value.

Resources