I am try to print text from text Area using JavaFX Printer(Like in notepad printing feature). I want to print that text without textArea background styles. So I try it with another text area. I wrap its text for avoid x bar overflow. But, I can't find a way to avoid y bar overflow. also I can't hide the background. can some one help or give a subjections for this or any other way. This is my current code. Also I try to hide scroll bars using css. but it did't support. I want to print only the text.
TextArea txtArea = new TextArea("This is some long text..");
public void printText() {
PrinterJob job = PrinterJob.createPrinterJob();
if(job == null) {
System.out.println("Error");
return;
}
boolean proseed = job.showPrintDialog(root.getScene().getWindow());
JobSettings ss1 = job.getJobSettings();
PageLayout pageLayout1 = ss1.getPageLayout();
double pgW1 = pageLayout1.getPrintableWidth();
double pgH1 = pageLayout1.getPrintableHeight();
TextArea tempTxtArea = new TextArea(txtArea.getText());
tempTxtArea.setPrefSize(pgW1, pgH1);
tempTxtArea.setWrapText(true);
tempTxtArea.setId("tempScroolBar");
if(proseed) {
boolean printed = job.printPage(tempTxtArea);
if (printed) {
job.endJob();
} else {
System.out.println("Fail");
}
}
}
this is my css file
#tempScroolBar > .scroll-pane {
-fx-vbar-policy: never;
-fx-hbar-policy: never;
}
Update
I updated my code. But now I have another problem. I changed TextArea to Label and to print all the content(avoid y bar overflow) I want to get number of the pages. But it doesn't return height(always return 0). Then I refer https://stackoverflow.com/a/21075734/13862869 and I set It to the Scene. Without add the label to the new Scene it doesn't give the width. But when I set the label to the Scene only three '.' are print in my document. Can some one help me to solve this...
public void printText() {
PrinterJob job = PrinterJob.createPrinterJob();
if(job == null) {
System.out.println("Error");
return;
}
boolean proseed = job.showPrintDialog(root.getScene().getWindow());
JobSettings ss1 = job.getJobSettings();
PageLayout pageLayout1 = ss1.getPageLayout();
double pgW1 = pageLayout1.getPrintableWidth();
double pgH1 = pageLayout1.getPrintableHeight();
HBox h = new HBox();
Label tempText = new Label();
tempText.setPrefWidth(pgW1);
tempText.setWrapText(true);
tempText.setText(txtArea.getText());
h.getChildren().add(tempText);
Scene s = new Scene(h); // when i remove this line again text can print
tempText.applyCss();
double fullLabelHeight = tempText.prefHeight(-1);
int numberOfPages = (int) Math.ceil(fullLabelHeight/ pgH1);
if(proseed) {
job.printPage(tempText);
job.endJob();
}
}
Related
I want to remove setFixedLeading at the first line on each page (100+)
I read a bit text(more 100 page with help while). And I set padding and margin to 0 but I still have top indent. Why? Help me pls? How delete it?
public static final String DEST = "PDF.pdf";
public static void main(String[] args) throws FileNotFoundException {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
Document doc = new Document(pdfDoc);
doc.setMargins(0,0,0,0);
for (int i = 0; i <20 ; i++) {
Paragraph element = new Paragraph("p " + i);
element.setPadding(0);
element.setMargin(0);
element.setFixedLeading(55);
doc.add(element);
}
doc.close();
}
PDF file:
https://pdfhost.io/v/Byt9LHJcy_PDFpdf.pdf
At the time of element creation you don't know the page it will end up on nor its resultant position. I don't think there is a property that allows you to configure the behavior depending on whether it's the top element on a page (such property would be too custom and tied to a specific workflow).
Fortunately, the layout mechanism is quite flexible and you can implement the desired behavior in a couple of lines of code.
First off, let's not use setFixedLeading and set the top margin for all paragraphs instead:
Document doc = new Document(pdfDocument);
doc.setMargins(0, 0, 0, 0);
for (int i = 0; i < 20; i++) {
Paragraph element = new Paragraph("p " + i);
element.setPadding(0);
element.setMargin(0);
element.setMarginTop(50);
doc.add(element);
}
doc.close();
This does not pretty much change anything in the visual result - it's just another way of doing things.
Now, we need a custom renderer to tweak the behavior of a paragraph if it is rendered at the top of the page. We are going to override layout method and check if the area we are given is located at the top of the page - and if so, we will not apply the top margin:
private static class CustomParagraphRenderer extends ParagraphRenderer {
Document document;
public CustomParagraphRenderer(Paragraph modelElement, Document document) {
super(modelElement);
this.document = document;
}
#Override
public IRenderer getNextRenderer() {
return new ParagraphRenderer((Paragraph) modelElement);
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
if (layoutContext.getArea().getBBox().getTop() == document.getPdfDocument().getDefaultPageSize().getHeight()) {
((Paragraph)getModelElement()).setMarginTop(0);
}
return super.layout(layoutContext);
}
}
Now the only thing we need to do is to set the custom renderer instance to each paragraph in the loop:
element.setNextRenderer(new CustomParagraphRenderer(element, doc));
Visual result:
I am trying to send some text to a printer. I need just the text printed, wrapped at the page margin and flowing to another page if necessary.
Here is a minimal example of what I am doing now:
#FXML
private void print() {
TextArea printArea = new TextArea(textArea.getText());
printArea.setWrapText(true);
printArea.getChildrenUnmodifiable().forEach(node -> node.setStyle("-fx-background-color: transparent"));
printArea.setStyle("-fx-background-color: transparent");
PrinterJob printerJob = PrinterJob.createPrinterJob();
if (printerJob != null && printerJob.showPrintDialog(textArea.getScene().getWindow())) {
if (printerJob.printPage(printArea)) {
printerJob.endJob();
// done printing
} else {
// failed to print
}
} else {
// failed to get printer job or failed to show print dialog
}
}
What ends up printing is a gray background that seems to be the control itself, along with the scrollbar. Am I approaching this the wrong way? I feel like I'm fighting against the API by tweaking and printing a control instead of just sending the text to be printed.
The example image below was taken from my cell phone camera, so the white paper ends up looking a bit light-gray, but you can still see the gray background from the control and the scrollbar.
Instead of a TextArea, print a TextFlow:
private void print() {
TextFlow printArea = new TextFlow(new Text(textArea.getText()));
PrinterJob printerJob = PrinterJob.createPrinterJob();
if (printerJob != null && printerJob.showPrintDialog(textArea.getScene().getWindow())) {
PageLayout pageLayout = printerJob.getJobSettings().getPageLayout();
printArea.setMaxWidth(pageLayout.getPrintableWidth());
if (printerJob.printPage(printArea)) {
printerJob.endJob();
// done printing
} else {
System.out.println("Failed to print");
}
} else {
System.out.println("Canceled");
}
}
Notice that the TextFlow's maxWidth needs to be set using the PrinterJob's page layout, after the print dialog has been shown.
I'm using PDFBox to fill form fields in a pdf using below code:
PDField nameField = form.getField("name");
if(null != nameField){
nameField.setValue(data.get("name")); // data is a hashmap
nameField.setReadonly(true);
}
The problem is, if the text is long it doesn't split to multiple lines, even though I have enabled the "multi-line" option for the field in the pdf. Do I have to do anything from the code as well to enable this?
Thanks.
Remember
Setting the ressources for the fonts to be used into the TextField.
Associating the ressources with the PDAccroform of the PDDocument.
Getting a widget for the PDTextField.
Getting a rectangle for the Widget.
Setting the width and the height of the rectangle of the widget.
It would solve it. In my case, I have a height of 20 for a non multiline text and another of 80 for a multiline textfield.You can see them being the last argument of the PDRectangle constructor. The PDRectangle class is used to specify the position and the dimension of the widget that sets it's rectangle to it. The texfield widget will appear as specified by the PDRectangle.
public static PDTextField addTextField(PDDocument pdDoc,PDAcroForm pda,String value,
String default_value,Boolean multiline,float txtfieldsyposition,float pagesheight)
{
int page = (int) (txtfieldsyposition/pagesheight);
if(page+1> pdDoc.getNumberOfPages())
{
ensurePageCapacity(pdDoc,page+1);//add 1 page to doc if needed
}
PDTextField pdtff = new PDTextField(pda);
PDFont font = new PDType1Font(FontName.TIMES_ROMAN);
String appearance = "/TIMES 10 Tf 0 0 0 rg";
try
{
PDFont font_ = new PDType1Font(FontName.HELVETICA);
PDResources resources = new PDResources();
resources.put(COSName.getPDFName("Helv"), font_);
resources.put(COSName.getPDFName("TIMES"), font);
pda.setDefaultResources(resources);
org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget widget = pdtff.getWidgets().get(0);
PDRectangle rect = null;
if(!multiline)
rect = new PDRectangle(80, (pagesheight - (txtfieldsyposition % pagesheight)), 450, 20);
else
rect = new PDRectangle(80,(pagesheight-(txtfieldsyposition%pagesheight)),450,80);
PDPage pd_page = pdDoc.getPage(page);
System.out.println(pd_page.getBBox().getHeight());
widget.setRectangle(rect);
widget.setPage(pd_page);
PDAppearanceCharacteristicsDictionary fieldAppearance = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fieldAppearance.setBorderColour(new PDColor(new float[]{0,0,0}, PDDeviceRGB.INSTANCE));
fieldAppearance.setBackground(new PDColor(new float[]{255,255,255}, PDDeviceRGB.INSTANCE));
widget.setAppearanceCharacteristics(fieldAppearance);
widget.setPrinted(true);
pd_page.getAnnotations().add(widget);
System.out.println("before appearance " +pdtff.getDefaultAppearance());
pdtff.setDefaultAppearance(appearance);
System.out.println("after appearance "+pdtff.getDefaultAppearance());
if(multiline)
{
pdtff.setMultiline(true);
}
pdtff.setDefaultValue("");
pdtff.setValue(value.replaceAll("\u202F"," "));
pdtff.setPartialName( page +""+(int)txtfieldsyposition);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(IllegalArgumentException e)
{
e.printStackTrace();
}
return pdtff;
}
I want to make all the text in an existing PDF transparent.
Option 1: select all the text, find a color property and change it to "colorless"
Or, if there is no such property
Option 2: Parse the page content Stream and all Form XObjects for that page, detect text blocks (BT/ET), and set the render mode to invisble.
This seems to be a complex operation.
Here is my example file
The following code is generating PDF(example pdf file):
Document document = new Document(new Rectangle(width, height));
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
document.open();
PdfContentByte picCanvas = null;
PdfContentByte txtCanvas = null;
if (isUnderPic) {
txtCanvas = writer.getDirectContentUnder();
picCanvas = writer.getDirectContent();
} else {
txtCanvas = writer.getDirectContent();
picCanvas = writer.getDirectContentUnder();
}
BaseFont bf = null;
if (null != pageList) {
int[] dpi = { 0, 0 };
if (dpiType == 1) {
dpi[0] = 300;
dpi[1] = 300;
} else if (dpiType == 2) {
dpi[0] = 600;
dpi[1] = 600;
}
for (int i = 0; i < pageList.size(); i++) {
PDFPage page = pageList.get(i);
Image pageImage = null;
if (pdfType == 3) {
pageImage = Image.getInstance(page.getBinImage());
} else {
pageImage = Image.getInstance(page.getOriImage());
}
if (pageImage.getWidth() > 0) {
pageImage.scaleAbsolute(page.getWidth(), page.getHeight());
}
pageImage.setAbsolutePosition(0, 0);
picCanvas.addImage(pageImage);
if (pdfType == 2 || pdfType == 3) {
for (PageElement ele : page.getElementList()) {
if (ele.getType().equals(PDFConstant.ElementType.PDF_ELEMENT_CHAR)) {
txtCanvas.beginText();
if (isColor) {
txtCanvas.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
txtCanvas.setColorFill(BaseColor.RED);
} else {
txtCanvas.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_INVISIBLE);
}
String font = ele.getFont();
try {
bf = fonts.get(font);
if (null == bf) {
bf = BaseFont.createFont(font, "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
fonts.put(font, bf);
}
} catch (Exception e) {
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
fonts.put(font, bf);
}
txtCanvas.setFontAndSize(bf, ele.getFontSize());
txtCanvas.setTextMatrix(ele.getPageX(), ele.getPageY(page.getRcInPage()));
txtCanvas.showText(ele.getCode());
txtCanvas.endText();
}
}
}
if (StringUtils.isNotBlank(cutPath)) {
for (PageElement ele : page.getElementList()) {
if (ele.getType().equals(PDFConstant.ElementType.PDF_ELEMENT_PIC) && StringUtils.isNotBlank(ele.getCutPicSrc())) {
ImageTools.cutPic(ele.getRcInImage(), page.getOriImage(), ele.getCutPicSrc(), dpi);
}
}
}
if (pdfType == 3) {
logger.debug("pdfType == 3");
for (PageElement ele : page.getElementList()) {
if (ele.getType().equals(PDFConstant.ElementType.PDF_ELEMENT_PIC) && StringUtils.isNotBlank(ele.getCutPicSrc())) {
if (new File(ele.getCutPicSrc()).exists()) {
Image cutCover = Image.getInstance(ImageTools.drawImage((int) ele.getWidth(), (int) ele.getHeight()));
if (cutCover.getWidth() > 0) {
cutCover.scaleAbsolute(ele.getWidth(), ele.getHeight());
}
cutCover.setAbsolutePosition(ele.getPageX(), ele.getPageY(page.getRcInPage()));
picCanvas.addImage(cutCover);
Image pic = Image.getInstance(ele.getCutPicSrc());
if (pic.getWidth() > 0) {
pic.scaleAbsolute(ele.getWidth(), ele.getHeight());
}
pic.setAbsolutePosition(ele.getPageX(), ele.getPageY(page.getRcInPage()));
picCanvas.addImage(pic);
}
}
}
}
if (i + 1 < pageList.size()) {
document.setPageSize(new Rectangle(pageList.get(i + 1).getWidth(), pageList.get(i + 1).getHeight()));
} else {
document.setPageSize(new Rectangle(pageList.get(i).getWidth(), pageList.get(i).getHeight()));
}
document.newPage();
}
}
document.close();
I've taken a look at your PDF and I see that the PDF is a scanned image. The text isn't really text: it consists of an image. Your question is invalid because it assumes that the text consists of vector data (defined using PDF syntax, such as BT and ET). In reality, the text is a bunch of pixels and any pixel doesn't know whether it belongs to a text glyph or an image. In short: you're using the wrong approach. You are trying to solve a problem using PDF software whereas you should be using a tool that manipulates raster images.
This is the image I extracted from the PDF:
The OP claims that there are two layers: one with an image, one with text. That may very well be true, but the image also contains rasterized text and it is impossible to remove that text from the image by changing the PDF syntax.
You may be able to cover the text if you know the coordinates, but that will largely depend on the accuracy of the OCR operation.
If your requirement is not to cover the text in the image, but the text of the vector layer, it's sufficient to add the syntax that adds the image after the syntax that adds the vector text. If the image is opaque, it will cover all the text. This is done in the RepeatImage example:
PdfReader reader = new PdfReader(src);
// We assume that there's a single large picture on the first page
PdfDictionary page = reader.getPageN(1);
PdfDictionary resources = page.getAsDict(PdfName.RESOURCES);
PdfDictionary xobjects = resources.getAsDict(PdfName.XOBJECT);
PdfName imgName = xobjects.getKeys().iterator().next();
Image img = Image.getInstance((PRIndirectReference)xobjects.getAsIndirectObject(imgName));
img.setAbsolutePosition(0, 0);
img.scaleAbsolute(reader.getPageSize(1));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.getOverContent(1).addImage(img);
stamper.close();
reader.close();
Take a look at the resulting PDF; now you can still select the vector text, but it's no longer visible.
I am writing an application and in that I am using JTextArea to display some text. Now I want to show some clickable URL in text area along with the normal text and I want if user click on the URL then the web page that URL referring to should open in new web browser window.
Use JEditorPane with HTMLEditorKit or JTextPane and set content type to "text/html"
..url referring to should open in new web browser window.
// 1.6+
Desktop.getDesktop().browse(URI);
Here is an example of opening links from JTextArea:
JTextArea jtxa = new JTextArea(25,100);
JScrollPane jsp = new JScrollPane(jtxa);
JPanel jp = new JPanel();
jp.add(jsp);
jp.setSize(100,50);
jtxa.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent me)
{
if(me.getClickCount()==2) //making sure there was a double click
{
int x = me.getX();
int y = me.getY();
int startOffset = jtxa.viewToModel(new Point(x, y));//where on jtextarea click was made
String text = jtxa.getText();
int searchHttp = 0;
int wordEndIndex = 0;
String[] words = text.split("\\s");//spliting the text to words. link will be a single word
for(String word:words)
{
if(word.startsWith("https://") || word.startsWith("http://"))//looking for the word representing the link
{
searchHttp = text.indexOf(word);
wordEndIndex = searchHttp+word.length();
if(startOffset>=searchHttp && startOffset<=wordEndIndex)//after the link word was found, making sure the double click was made on this link
{
try
{
jtxa.select(searchHttp, wordEndIndex);
desk.browse(new URI(word)); //opening the link in browser. Desktop desk = Desktop.getDesktop();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
}
}
});