I need to highlight a set of words inside an existing PDF given specific coordinates that i have already extracted.
I am working with pdfbox by Apache (last version 2.0.8).
There is an example file I can use to such a purpose (AddAnnotations.java inside the pdfbox website) but I think this example was compiled with an older Java version as the following import does not work:
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationHighlight;
Can anyone help me with that? Which is the simplest way to highlight words by using this library?
Here is the code to highlight ALL the words inside a PDF document. Highlighting only a specific set of words can be easily performed modifying this script. Please note this is only a test and further checks are needed for words that terminates in a new line as well as words placed in negative landscape/portrait PDF pages. Optimizing this script is also possible.
This script was built using Apache PDFBox 2.0.8.
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;
public class TestAnnotatePDF extends PDFTextStripper
{
static List<double[]> coordinates;
static ArrayList tokenStream;
public TestAnnotatePDF() throws IOException
{
//data structed containing coordinates information for each token
coordinates = new ArrayList<>();
//List of words extracted from text (considering a whitespace-based tokenization)
tokenStream = new ArrayList();
}
public static void main(String [] args) throws IOException
{
try
{
//Loading an existing document
File file = new File("MyDocument");
PDDocument document = PDDocument.load(file);
//extended PDFTextStripper class
PDFTextStripper stripper = new TestAnnotatePDF();
//Get number of pages
int number_of_pages = document.getDocumentCatalog().getPages().getCount();
//The method writeText will invoke an override version of writeString
Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());
stripper.writeText(document, dummy);
//Print collected information
System.out.println(tokenStream);
System.out.println(tokenStream.size());
System.out.println(coordinates.size());
double page_height;
double page_width;
double width, height, minx, maxx, miny, maxy;
int rotation;
//scan each page and highlitht all the words inside them
for (int page_index = 0; page_index < number_of_pages; page_index++)
{
//get current page
PDPage page = document.getPage(page_index);
//Get annotations for the selected page
List<PDAnnotation> annotations = page.getAnnotations();
//Define a color to use for highlighting text
PDColor red = new PDColor(new float[] { 1, 0, 0 }, PDDeviceRGB.INSTANCE);
//Page height and width
page_height = page.getMediaBox().getHeight();
page_width = page.getMediaBox().getWidth();
//Scan collected coordinates
for (int i=0; i<coordinates.size(); i++)
{
//if the current coordinates are not related to the current
//page, ignore them
if ((int) coordinates.get(i)[4] != (page_index+1))
continue;
else
{
//get rotation of the page...portrait..landscape..
rotation = (int) coordinates.get(i)[7];
//page rotated of 90degrees
if (rotation == 90)
{
height = coordinates.get(i)[5];
width = coordinates.get(i)[6];
width = (page_height * width)/page_width;
//define coordinates of a rectangle
maxx = coordinates.get(i)[1];
minx = coordinates.get(i)[1] - height;
miny = coordinates.get(i)[0];
maxy = coordinates.get(i)[0] + width;
}
else //i should add here the cases -90/-180 degrees
{
height = coordinates.get(i)[5];
minx = coordinates.get(i)[0];
maxx = coordinates.get(i)[2];
miny = page_height - coordinates.get(i)[1];
maxy = page_height - coordinates.get(i)[3] + height;
}
//Add an annotation for each scanned word
PDAnnotationTextMarkup txtMark = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
txtMark.setColor(red);
txtMark.setConstantOpacity((float)0.3); // 30% transparent
PDRectangle position = new PDRectangle();
position.setLowerLeftX((float) minx);
position.setLowerLeftY((float) miny);
position.setUpperRightX((float) maxx);
position.setUpperRightY((float) ((float) maxy+height));
txtMark.setRectangle(position);
float[] quads = new float[8];
quads[0] = position.getLowerLeftX(); // x1
quads[1] = position.getUpperRightY()-2; // y1
quads[2] = position.getUpperRightX(); // x2
quads[3] = quads[1]; // y2
quads[4] = quads[0]; // x3
quads[5] = position.getLowerLeftY()-2; // y3
quads[6] = quads[2]; // x4
quads[7] = quads[5]; // y5
txtMark.setQuadPoints(quads);
txtMark.setContents(tokenStream.get(i).toString());
annotations.add(txtMark);
}
}
}
//Saving the document in a new file
File highlighted_doc = new File("MyDocument_final.pdf");
document.save(highlighted_doc);
document.close();
}
catch(IOException e)
{
System.out.println(e);
}
}
#Override
protected void writeString(String string, List<TextPosition> textPositions) throws IOException
{
String token = "";
int token_length = textPositions.size();
int counter = 1;
double minx = 0,maxx = 0,miny = 0,maxy =0;
double height = 0;
double width = 0;
int rotation = 0;
for (TextPosition text : textPositions)
{
rotation = text.getRotation();
if (text.getHeight() > height)
height = text.getHeight();
if (text.getWidth() > width)
width = text.getWidth();
//if it is the first char of the current word
if (counter == 1)
{
minx = text.getX();
miny = text.getY();
}
//if it is the last char of the current word
if (counter == token_length)
{
maxx = text.getEndX();
maxy = text.getY();
}
token += text;
counter += 1;
}
tokenStream.add(token);
double word_coordinates [] = {minx,miny,maxx,maxy,this.getCurrentPageNo(), height, width, rotation};
coordinates.add(word_coordinates);
}}
Here is the code to highlight specific words inside a PDF document. Please note this is working for highlighting the line of the search text. Highlight specific words in a PDF is still in progress... Any suggestion to highlight specific words on top of this code will be highly appreciated.
This script was built using Apache PDFBox 2.0.8
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
public class PDFhighlightDemo extends PDFTextStripper {
public PDFhighlightDemo() throws IOException {
super();
}
public static void main(String[] args) throws IOException {
PDDocument document = null;
String fileName = "Demo1.pdf";
try {
document = PDDocument.load( new File(fileName) );
PDFTextStripper stripper = new PDFhighlightDemo();
stripper.setSortByPosition( true );
stripper.setStartPage( 0 );
stripper.setEndPage( document.getNumberOfPages() );
Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());
stripper.writeText(document, dummy);
File file1 = new File("FinalPDF.pdf");
document.save(file1);
}
finally {
if( document != null ) {
document.close();
}
}
}
/**
* Override the default functionality of PDFTextStripper.writeString()
*/
#Override
protected void writeString(String string, List<TextPosition> textPositions) throws IOException {
boolean isFound = false;
float posXInit1 = 0,
posXEnd1 = 0,
posYInit1 = 0,
posYEnd1 = 0,
width1 = 0,
height1 = 0,
fontHeight1 = 0;
String[] criteria = {"angular", "prepared"};
for (int i = 0; i < criteria.length; i++) {
if (string.contains(criteria[i])) {
isFound = true;
}
}
if (isFound) {
for(TextPosition textPosition:textPositions) {
posXInit1 = textPositions.get(0).getXDirAdj();
posXEnd1 = textPositions.get(textPositions.size() - 1).getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidth();
posYInit1 = textPositions.get(0).getPageHeight() - textPositions.get(0).getYDirAdj();
posYEnd1 = textPositions.get(0).getPageHeight() - textPositions.get(textPositions.size() - 1).getYDirAdj();
width1 = textPositions.get(0).getWidthDirAdj();
height1 = textPositions.get(0).getHeightDir();
}
float quadPoints[] = {posXInit1, posYEnd1 + height1 + 2, posXEnd1, posYEnd1 + height1 + 2, posXInit1, posYInit1 - 2, posXEnd1, posYEnd1 - 2};
List<PDAnnotation> annotations = document.getPage(this.getCurrentPageNo() - 1).getAnnotations();
PDAnnotationTextMarkup highlight = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
PDRectangle position = new PDRectangle();
position.setLowerLeftX(posXInit1);
position.setLowerLeftY(posYEnd1);
position.setUpperRightX(posXEnd1);
position.setUpperRightY(posYEnd1 + height1);
highlight.setRectangle(position);
// quadPoints is array of x,y coordinates in Z-like order (top-left, top-right, bottom-left,bottom-right)
// of the area to be highlighted
highlight.setQuadPoints(quadPoints);
PDColor yellow = new PDColor(new float[]{1, 1, 1 / 255F}, PDDeviceRGB.INSTANCE);
highlight.setColor(yellow);
annotations.add(highlight);
}
}
}
Highlight specific words in a document using PDFclown.
package com.NLP.demo;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.pdfclown.documents.Page;
import org.pdfclown.documents.contents.ITextString;
import org.pdfclown.documents.contents.TextChar;
import org.pdfclown.documents.interaction.annotations.TextMarkup;
import org.pdfclown.documents.interaction.annotations.TextMarkup.MarkupTypeEnum;
import org.pdfclown.files.SerializationModeEnum;
import org.pdfclown.tools.TextExtractor;
import org.pdfclown.util.math.Interval;
import org.pdfclown.util.math.geom.Quad;
public class PDFCrownDemo {
public static void main() throws IOException {
PDFCrownDemo PDFCrownDemo=new PDFCrownDemo();
PDFCrownDemo.highlighttext();
}
public void highlighttext() throws IOException{
org.pdfclown.files.File file = new org.pdfclown.files.File("src/main/resources/XXX.pdf");
String textRegEx = "Contract";
Pattern pattern = Pattern.compile(textRegEx, Pattern.CASE_INSENSITIVE);
TextExtractor textExtractor = new TextExtractor(true, true);
for(final Page page : file.getDocument().getPages())
{
Map<Rectangle2D,List<ITextString>> textStrings = textExtractor.extract(page);
final Matcher matcher = pattern.matcher(TextExtractor.toString(textStrings));
textExtractor.filter(textStrings,new TextExtractor.IIntervalFilter()
{
#Override
public boolean hasNext()
{return matcher.find();}
#Override
public Interval next()
{return new Interval(matcher.start(), matcher.end());}
#Override
public void process(Interval interval,ITextString match)
{
// Defining the highlight box of the text pattern match...
List highlightQuads = new ArrayList();
{
/*
NOTE: A text pattern match may be split across multiple contiguous lines,
so we have to define a distinct highlight box for each text chunk.
*/
Rectangle2D textBox = null;
for(TextChar textChar : match.getTextChars())
{
Rectangle2D textCharBox = textChar.getBox();
if(textBox == null)
{textBox = (Rectangle2D)textCharBox.clone();}
else
{
if(textCharBox.getY() > textBox.getMaxY())
{
highlightQuads.add(Quad.get(textBox));
textBox = (Rectangle2D)textCharBox.clone();
}
else
{textBox.add(textCharBox);}
}
}
highlightQuads.add(Quad.get(textBox));
}
// Highlight the text pattern match!
new TextMarkup(page,MarkupTypeEnum.Highlight, highlightQuads);
}
#Override
public void remove(
)
{throw new UnsupportedOperationException();}
}
);
}
//file.save(SerializationModeEnum.Incremental);
file.save(new java.io.File("src/main/resources/XXX.pdf"), SerializationModeEnum.Standard);
}
}
Related
I need to set up a simulation of a nuclear power plant in JavaFX. The GUI is working perfectly, but I've got problems with getting the simulation run. I have to use a Timeline (as EventHandler) for this, the handler updates the radiation value in each cell every single tick. The radiation is displayed as a circle on each cell. The higher the radiation, the bigger should the circle be. For this, I made an if-else-statement.
The problem is: The if-statement cannot access the variables from the EventHandler. But this is necessary to update the circle size each tick. I already tried to put the if-statements right into the EventHandler, but then, no circles have been shown anymore on my GUI.
These are the three classes so far:
EDIT: I put the if-statements into the Event Handler, new code below.
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class NuclearPowerPlant extends Application {
private static final int HEIGHT = 50;
private static final int WIDTH = 55;
private static final int CELL_SIZE = 40;
#Override
public void start(Stage stage) {
stage.setScene(new Scene(createContent()));
stage.show();
}
private Parent createContent() {
Pane root = new Pane();
root.setPrefSize((WIDTH - 40) * CELL_SIZE, (HEIGHT - 40) * CELL_SIZE); // Size of displayed window
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
Cell cell = new Cell(x, y);
root.getChildren().add(cell);
}
}
return root;
}
public static void main(String[] args) {
launch(args);
}
}
Cell:
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.util.Duration;
public class Cell extends StackPane {
private static final int CELL_SIZE = 40;
int x;
int y;
private Rectangle cell;
private Circle radiation; // Radiation is displayed as a circle
int circlesize; // Size of the circle (the higher the radiation, the bigger the circle)
double radiationvalue = 5000; // Initializing of the radiation value of all cells at the beginning (air in all cells)
private Text symbol; // For Explosion
double activity;
double reflection;
public Cell(int x, int y) { // Konstruktor fuer die Zelle
setTranslateX(x * CELL_SIZE);
setTranslateY(y * CELL_SIZE);
cell = new Rectangle(CELL_SIZE - 2, CELL_SIZE - 2, Color.BLUE);
cell.setStroke(Color.WHITE);
EventHandler<ActionEvent> handlerUpdateRadiationvalue = event -> {
double newradiationvalue = activity + reflection * 500;
// System.out.println(newradiationvalue);
if (newradiationvalue < 1000) {
this.circlesize = 2;
} else if (newradiationvalue >= 1000 && newradiationvalue < 3000) {
this.circlesize = 5;
} else if (newradiationvalue >= 3000 && newradiationvalue < 5000) {
this.circlesize = 8;
} else if (newradiationvalue >= 5000 && newradiationvalue < 7000) {
this.circlesize = 11;
} else if (newradiationvalue >= 7000 && newradiationvalue < 9000) {
this.circlesize = 14;
} else if (newradiationvalue >= 9000 && newradiationvalue < 10000) {
this.circlesize = 18;
}
// Explosion:
else if (newradiationvalue >= 10000) {
circlesize = 0;
cell.setFill(Color.RED);
symbol = new Text("X");
symbol.setFont(Font.font(38));
}
};
KeyFrame keyframe = new KeyFrame(Duration.seconds(0.02), handlerUpdateRadiationvalue);
Timeline tl = new Timeline();
tl.getKeyFrames().addAll(keyframe);
tl.setCycleCount(Timeline.INDEFINITE);
tl.play();
radiation = new Circle(circlesize, Color.BLACK);
getChildren().add(cell);
if (radiationvalue < 10000) {
getChildren().add(radiation);
} else {
getChildren().add(symbol);
}
// Context Menu for material change:
ContextMenu contextMenu = new ContextMenu();
MenuItem air = new MenuItem("Luft");
air.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
activity = Material.AIR.getActivity();
reflection = Material.AIR.getReflection();
cell.setFill(Color.BLUE);
}
});
MenuItem uranium = new MenuItem("Uran");
uranium.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
activity = Material.URANIUM.getActivity();
reflection = Material.URANIUM.getReflection();
cell.setFill(Color.GREEN);
}
});
MenuItem lead = new MenuItem("Blei");
lead.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
activity = Material.LEAD.getActivity();
reflection = Material.LEAD.getReflection();
cell.setFill(Color.GREY);
}
});
MenuItem ruleblock = new MenuItem("Regelblock");
ruleblock.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
activity = Material.RULEBLOCK.getActivity();
reflection = Material.RULEBLOCK.getReflection();
cell.setFill(Color.YELLOW);
}
});
contextMenu.getItems().addAll(air, uranium, lead, ruleblock);
cell.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
#Override
public void handle(ContextMenuEvent event) {
contextMenu.show(cell, event.getScreenX(), event.getScreenY());
}
});
}
ENUM:
public enum Material {
AIR (0, 0.99),
URANIUM (1, 1.12),
LEAD (0, 0.7),
RULEBLOCK (0, 0.99);
double activity;
double reflection;
private Material(double activity, double reflection) {
this.activity = activity;
this.reflection = reflection;
}
double getActivity() {
return activity;
}
public void setActivity(double activity) {
this.activity = activity;
}
double getReflection() {
return reflection;
}
public void setReflection(double reflection) {
this.reflection = reflection;
}
}
The if statement always links to the global variable "radiationvalue" instead of the updated value in the event handler. If I try to access the 'newradiationvalue' in the if statement, I get an error that no such variable can be found (because the one in the Event Handler is not visible from outside).
Maybe someone can tell me how to access the variables in the event handler from outside the event handler?! And if it's not possible: How do I need to change my program to make this work as I want?
Thanks very much in advance!
Parsing an HTML text constaining <font> tags does not reset the size and family font after </font>
My code works pretty well except after </font>.
Before <font size=9> blablabla.. the text size was 11. I was expecting that after </font> the text size was reset to 11, but it still remains at 9. Same thing for the font family.
Certainly I have misunderstood how to use jsoup. I'd better use CSS, but I don't know how to do.
Thanks for help.
package test;
import java.awt.Color;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.VerticalAlign;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblLayoutType;
public class ReadHtml
{
protected static java.util.Vector<String> contenu = null;
org.apache.xmlbeans.XmlCursor cursor = null;
class WStyle
{
protected String police = "Times New Roman";
protected int taille = 11;
protected Color couleur = Color.black;
protected boolean gras = false;
protected boolean italique = false;
public WStyle() // constructeur
{
super();
}
protected String getPolice() {return police;}
protected int getTaille() {return taille;}
protected Color getCouleur() {return couleur;}
protected boolean getGras() {return gras;}
protected boolean getItalique() {return italique;}
protected void setPolice(String p) {police=p;}
protected void setTaille(int t) {taille=t;}
protected void setCouleur(Color c) {couleur=c;}
protected void setGras(boolean g) {gras=g;}
protected void setItalique(boolean i) {italique=i;}
}
public ReadHtml()
{
super();
contenu = new java.util.Vector<String>();
createWordFile();
}
private XWPFParagraph getTableParagraph(XWPFTableCell cell, String html)
{
cell.removeParagraph(0);
XWPFParagraph paragraph = cell.addParagraph();
paragraph.setSpacingAfterLines(0);
paragraph.setSpacingAfter(0);
Document htmlDocument = Jsoup.parse(html);
Elements htmlParagraphs = htmlDocument.select("p");
for(Element htmlParagraph : htmlParagraphs)
{
System.out.println(htmlParagraph);
ParagraphNodeVisitor nodeVisitor = new ParagraphNodeVisitor(paragraph);
NodeTraversor.traverse(nodeVisitor, htmlParagraph);
}
return paragraph;
}
private void createWordFile()
{
XWPFParagraph para = null;
try
{
XWPFDocument document = new XWPFDocument();
FileOutputStream out = new FileOutputStream(new File("./", "NewTable.docx"));
XWPFTable table = document.createTable();
CTTblLayoutType type = table.getCTTbl().getTblPr().addNewTblLayout();
type.setType(STTblLayoutType.FIXED);
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(1670));
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(6000));
String myTexte = "<html><head</head><body><p><font face=\"Verdana\" size=11>Good Morning</font> <font size=9 face=\"Times\"> " +
"<i><b>how are you today </b></i></font> Not so bad.<br>Thanks";
// first line
XWPFTableRow tableRow= table.getRow(0);
para = getTableParagraph(tableRow.getCell(0), "<p>Row #1, Col. #1");
tableRow .getCell(0).setParagraph(para);
XWPFTableCell cell = tableRow.createCell();
para = getTableParagraph(cell, myTexte); // Row #1, Col. #2
tableRow .getCell(1).setParagraph(para);
// seconde line
tableRow= table.createRow();
para = getTableParagraph(tableRow.getCell(0), "<p>Row #2, Col. #1");
tableRow .getCell(0).setParagraph(para);
para = getTableParagraph(tableRow.getCell(1), "<p>Row #2, Col. #2");
tableRow.getCell(1).setParagraph(para);
document.write(out);
document.close();
out.close();
System.out.println("NewTable.docx written successully");
}
catch (FileNotFoundException e) {System.out.println("File exception --> " + e.toString()); }
catch (IOException e) {System.out.println("I/O exception --> " + e.toString()); }
catch (Exception e) {System.out.println("Other exception --> " + e.toString()); }
}
public class ParagraphNodeVisitor implements NodeVisitor
{
String nodeName;
String fontFace;
String fontType;
boolean needNewRun;
boolean isItalic;
boolean isBold;
boolean isUnderlined;
int fontSize;
String fontColor;
VerticalAlign align = VerticalAlign.BASELINE ;
XWPFParagraph paragraph;
XWPFRun run;
ParagraphNodeVisitor(XWPFParagraph paragraph)
{
this.paragraph = paragraph;
this.run = paragraph.createRun();
this.nodeName = "";
this.needNewRun = false;
this.isItalic = false;
this.isBold = false;
this.isUnderlined = false;
this.fontSize = 11;
this.fontColor = "000000";
this.fontFace="Times";
}
#Override
public void head(Node node, int depth)
{
nodeName = node.nodeName();
needNewRun = false;
if ("#text".equals(nodeName))
{
run.setText(((TextNode)node).text());
needNewRun = true; //after setting the text in the run a new run is needed
}
else if ("i".equals(nodeName)) {isItalic = true;}
else if ("b".equals(nodeName)) {isBold = true;}
else if ("sup".equals(nodeName)){align = VerticalAlign.SUPERSCRIPT ;}
else if ("u".equals(nodeName)) {isUnderlined = true;}
else if ("br".equals(nodeName)) {run.addBreak();}
else if ("p".equals(nodeName)) {run.addBreak();}
else if ("font".equals(nodeName))
{
fontColor = (!"".equals(node.attr("color")))?node.attr("color").substring(1):"000000";
fontSize = (!"".equals(node.attr("size")))?Integer.parseInt(node.attr("size")):11;
fontFace = (!"".equals(node.attr("face")))?node.attr("face"):"Times";
}
if (needNewRun) run = paragraph.createRun();
needNewRun = false;
run.setItalic(isItalic);
run.setBold(isBold);
if (isUnderlined) run.setUnderline(UnderlinePatterns.SINGLE);
else run.setUnderline(UnderlinePatterns.NONE);
run.setColor(fontColor);
run.setFontSize(fontSize);
run.setFontFamily(fontFace);
run.setSubscript(align);
}
#Override
public void tail(Node node, int depth)
{
nodeName = node.nodeName();
System.out.println("Node=" + nodeName);
if ("i".equals(nodeName)) {isItalic = false;}
else if ("b".equals(nodeName)) {isBold = false;}
else if ("u".equals(nodeName)) {isUnderlined = false;}
else if ("sup".equals(nodeName)) {align= VerticalAlign.BASELINE ;}
else if ("font".equals("nodeName"))
{
fontColor = "000000";
fontSize = 11;
fontFace="Times";
System.out.println("Family=" + fontFace + " Taille=" + fontSize);
}
if (needNewRun) run = paragraph.createRun();
needNewRun = false;
run.setItalic(isItalic);
run.setBold(isBold);
if (isUnderlined) run.setUnderline(UnderlinePatterns.SINGLE); else run.setUnderline(UnderlinePatterns.NONE);
run.setColor(fontColor);
run.setFontSize(fontSize);
run.setFontFamily(fontFace);
run.setSubscript(align);
}
}
public static void main(String[] args)
{
new ReadHtml() ;
}
}
Please change the following line in your tail method, from
else if ("font".equals("nodeName"))
to
else if ("font".equals(nodeName))
You've compared two string literals instead of compare a string literal to the variable. Because of the typo the condition is always false, therefore fontSize is never reseted.
is it possible to extract text from an area with PDFbox using just the binaries instead of having to create my own code?
Compile and pack this simple program into a jar
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripperByArea;
public class ExtractText {
// Usage: xxx.jar filepath page x y width height
public static void main(String[] args) throws IOException {
if (args.length != 6) {
System.out.println("Help info");
return;
}
// Parameters
String filepath = args[0];
int page = Integer.parseInt(args[1]);
int x = Integer.parseInt(args[2]);
int y = Integer.parseInt(args[3]);
int width = Integer.parseInt(args[4]);
int height = Integer.parseInt(args[5]);
PDDocument document = PDDocument.load(new File(filepath));
PDFTextStripperByArea textStripper = new PDFTextStripperByArea();
Rectangle2D rect = new java.awt.geom.Rectangle2D.Float(x, y, width, height);
textStripper.addRegion("region", rect);
PDPage docPage = document.getPage(page);
textStripper.extractRegions(docPage);
String textForRegion = textStripper.getTextForRegion("region");
System.out.println(textForRegion);
}
}
Run it from command line, ex:
xxx.jar filepathToPdf pageToExtract x y width height
Add validation code for parameters and some usage info.
Edit
Also add the PDFbox libraries
java -cp "..." -jar xxx.jar filepathToPdf pageToExtract x y width height
This code plots a XYLineChart and a straigth line: by left mouse click and drag anywhere on the graph, XYLine is translated left/right and up down while the black line do not.
I would like to bind the black line and the XYLine so that when I click and drag, both lines move together.
How to accomplish this?
Thanks
import javafx.application.Application;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Node;
import javafx.scene.chart.LineChart;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
public class JavaFXMovePath extends Application {
Path path;
BorderPane pane;
XYChart.Series series1 = new XYChart.Series();
SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
SimpleDoubleProperty rectinitY = new SimpleDoubleProperty();
SimpleDoubleProperty rectX = new SimpleDoubleProperty();
SimpleDoubleProperty rectY = new SimpleDoubleProperty();
#Override
public void start(Stage stage) {
final NumberAxis xAxis = new NumberAxis(1, 12, 1);
final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);
xAxis.setAnimated(false);
yAxis.setAnimated(false);
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
#Override
public String toString(Number object) {
return String.format("%7.5f", object);
}
});
final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
lineChart.setCreateSymbols(false);
lineChart.setAlternativeRowFillVisible(false);
lineChart.setAnimated(false);
lineChart.setLegendVisible(false);
series1.getData().add(new XYChart.Data(1, 0.53185));
series1.getData().add(new XYChart.Data(2, 0.532235));
series1.getData().add(new XYChart.Data(3, 0.53234));
series1.getData().add(new XYChart.Data(4, 0.538765));
series1.getData().add(new XYChart.Data(5, 0.53442));
series1.getData().add(new XYChart.Data(6, 0.534658));
series1.getData().add(new XYChart.Data(7, 0.53023));
series1.getData().add(new XYChart.Data(8, 0.53001));
series1.getData().add(new XYChart.Data(9, 0.53589));
series1.getData().add(new XYChart.Data(10, 0.53476));
pane = new BorderPane();
pane.setCenter(lineChart);
Scene scene = new Scene(pane, 800, 600);
lineChart.getData().addAll(series1);
stage.setScene(scene);
path = new Path();
path.setStrokeWidth(5);
path.setStroke(Color.RED);
scene.setOnMouseClicked(mouseHandler);
scene.setOnMouseDragged(mouseHandler);
scene.setOnMouseEntered(mouseHandler);
scene.setOnMouseExited(mouseHandler);
scene.setOnMouseMoved(mouseHandler);
scene.setOnMousePressed(mouseHandler);
scene.setOnMouseReleased(mouseHandler);
stage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
}
else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED || mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
NumberAxis yAxis = (NumberAxis) lineChart.getYAxis();
NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();
double Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());
double newXlower=xAxis.getLowerBound(), newXupper=xAxis.getUpperBound();
double newYlower=yAxis.getLowerBound(), newYupper=yAxis.getUpperBound();
//double xAxisShift = getSceneShift(xAxis);
//double yAxisShift = getSceneShift(yAxis);
//double yAxisStep=yAxis.getHeight()/(yAxis.getUpperBound()-yAxis.getLowerBound());
double Delta=0.3;
if(mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED){
if(rectinitX.get() < mouseEvent.getX()){
newXlower=xAxis.getLowerBound()-Delta;
newXupper=xAxis.getUpperBound()-Delta;
}
else if(rectinitX.get() > mouseEvent.getX()){
newXlower=xAxis.getLowerBound()+Delta;
newXupper=xAxis.getUpperBound()+Delta;
}
xAxis.setLowerBound( newXlower );
xAxis.setUpperBound( newXupper );
//========== Y-Axis Moving ============================
if(rectinitY.get() < mouseEvent.getY()){
newYlower=yAxis.getLowerBound()+Delta/1000;
newYupper=yAxis.getUpperBound()+Delta/1000;
}
else if(rectinitY.get() > mouseEvent.getY()){
newYlower=yAxis.getLowerBound()-Delta/1000;
newYupper=yAxis.getUpperBound()-Delta/1000;
}
yAxis.setLowerBound(newYlower);
yAxis.setUpperBound(newYupper);
}
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
MoveTo moveTo = new MoveTo();
moveTo.setX(80);
moveTo.setY(80);
LineTo lineTo1 = new LineTo();
lineTo1.setX(80);
lineTo1.setY(80);
LineTo lineTo2 = new LineTo();
lineTo2.setX(200);
lineTo2.setY(200);
path.getElements().add(moveTo);
path.getElements().add(lineTo1);
path.getElements().add(lineTo2);
path.setStrokeWidth(3);
path.setStroke(Color.BLACK);
pane.getChildren().add(path);
}
}
};
//private static double getSceneShift(Node node) {
// double shift = 0;
// do {
// shift += node.getLayoutX();
// node = node.getParent();
// } while (node != null);
// return shift;
//}
public static void main(String[] args) {
launch(args);
}
}
I have a simple game that is in progress. As of right now all I want to do is click the green button and have the fifth and third pieces switch places. The paintComponent is called after the swap in the arraylist is made, but the JPanel is not refreshed to show these changes. When i am running my application I am choosing 4 for the pieces for each side. Thus, the inner green and black pieces should change place. Please help.
Number1.java
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.awt.Container;
public class Number1 {
private static JButton greenButton,blackButton,newGameButton,inputButton;
private static JTextFieldNumber inputField;
static MyActionListen actionListen;
static Number1 myGame;
static JFrame myDialog,myFrame;
static DrawGamePieces gamePanel;
public int piecesPerSide = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
myGame = new Number1();
actionListen = new MyActionListen();
myGame.getStartingTokensValue();
System.out.println(Color.WHITE.toString());
}
private void makeComponents()
{
//Setting up the green button click
greenButton = new JButton("Green");
greenButton.setBounds(40, 0 , 100, 40);
greenButton.setForeground(Color.GREEN);
greenButton.addActionListener(actionListen);
//Setting up the black button click
blackButton = new JButton("Black");
blackButton.setBounds(greenButton.getLocation().x + greenButton.getWidth() + 10
, 0 , 100, 40);
blackButton.setForeground(Color.BLACK);
blackButton.addActionListener(actionListen);
//Setting up the new game button click
newGameButton = new JButton("New Game");
newGameButton.setBounds(blackButton.getLocation().x + blackButton.getWidth() + 10
, 0 , 100, 40);
newGameButton.setForeground(Color.BLUE);
newGameButton.addActionListener(actionListen);
//init gamePanel
gamePanel = new DrawGamePieces(myGame.piecesPerSide,myFrame.getSize().width, myFrame.getSize().height - 40);
gamePanel.setLocation(0, 40);
gamePanel.setBackground(Color.YELLOW);
}
private void makeGameFrame()
{
myFrame = new JFrame();
if(myGame.piecesPerSide <= 10) myFrame.setSize(400, 250);
else myFrame.setSize(600, 250);
myFrame.setLocation(300, 100);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //sets the default close method
myFrame.setTitle("Solitary Game"); //sets the title of the window
Container mainFrameContents = myFrame.getContentPane();//get the content pane to add components to
mainFrameContents.setLayout(null); //allowed setBounds on components to work properly
mainFrameContents.setBackground(Color.YELLOW);
myGame.makeComponents(); //makes all the sub components
//adds all subcomponents to content pane
mainFrameContents.add(greenButton);
mainFrameContents.add(blackButton);
mainFrameContents.add(newGameButton);
mainFrameContents.add(gamePanel);
myFrame.setVisible(true);
}
//gets the starting value of the tokens for the game
private void getStartingTokensValue()
{
myDialog = new JFrame("New Game Information");
myDialog.setSize(450, 150);
myDialog.setLocation(300, 100);
myDialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //sets the default close method
JLabel l = new JLabel("Please Enter the Number of Pieces for each side of the game (1-20)");
l.setBounds((myDialog.getSize().width - 420)/2, 0, 420, 30);
inputField = new JTextFieldNumber("0123456789");
inputField.setBounds((myDialog.getSize().width - 100)/2, 35, 100, 30);
inputButton = new JButton("Submit");
inputButton.setBounds((myDialog.getSize().width - 100)/2, 75, 100, 30);
inputButton.addActionListener(actionListen);
myDialog.setLayout(null);
myDialog.add(inputButton);
myDialog.add(l);
myDialog.add(inputField);
myDialog.setVisible(true);
}
private static class MyActionListen implements ActionListener
{
public void actionPerformed(ActionEvent ap)
{
if(ap.getSource().equals(greenButton)){
System.out.println("Requet to green move");
gamePanel.greenMove();
}else if(ap.getSource().equals(blackButton)){
System.out.println("Requet to black move");
}else if(ap.getSource().equals(newGameButton)){
System.out.println("Requet to start new game");
}else if(ap.getSource().equals(inputButton)){
if(inputField.getText().length()>0)
{
myGame.piecesPerSide = Integer.parseInt(inputField.getText());
if(inputField.checkAllCharacters() && (myGame.piecesPerSide <= 20) && (myGame.piecesPerSide>0))
{
myDialog.dispose();
myGame.makeGameFrame();
}else{
JOptionPane.showMessageDialog(inputField, "Please only type in an integer from 1 to 20");
}
}
}
}
}
}
DrawGamePieces.java
import java.awt.*;
import java.util.ArrayList;
import javax.swing.JPanel;
public class DrawGamePieces extends JPanel{
private ArrayList<GamePiece> gamePieces;
private int ballR = 15;
//paint or repaints the board
protected void paintComponent( Graphics g ){
super.paintComponent(g);
System.out.println("paint components called");
for(int i=0;i<gamePieces.size();i++)
{
GamePiece temp = gamePieces.get(i);
g.setColor(temp.getColor());
g.fillOval(temp.x,temp.y,ballR,ballR);
}
}
//init the game board
public DrawGamePieces(int piecesPerSide,int aWidth,int aHeight){
gamePieces = new ArrayList<GamePiece>();
super.setSize(aWidth, aHeight);
//space between wall and first piece
int blankSpace = (int)((aWidth - (ballR)*(2*piecesPerSide+1))/2);
//initalized the pieces in the arraylist
for(int i=0;i<(2*piecesPerSide+1);i++)
{
GamePiece temp = null;
if(i == 0) temp = new GamePiece(blankSpace,80,Color.GREEN);
if((i < piecesPerSide) && (i != 0)) temp = new GamePiece(ballR+gamePieces.get(i-1).x,80,Color.GREEN);
if(i > piecesPerSide) temp = new GamePiece(ballR+gamePieces.get(i-1).x,80,Color.BLACK);
if(i == piecesPerSide) temp = new GamePiece(ballR+gamePieces.get(i-1).x,80,Color.YELLOW);
gamePieces.add(temp);
}
}
public void greenMove(){
GamePiece temp = gamePieces.get(5);
gamePieces.set(5, gamePieces.get(3));
gamePieces.set(3, temp);
repaint();
}
public void blackMove(){
GamePiece temp = gamePieces.get(5);
gamePieces.set(5, gamePieces.get(3));
gamePieces.set(3, temp);
}
private int pieceMoveable(Color c){
int index = -1, start = 0, end = 0,change = 0;
if(c == Color.GREEN){
start = 0;
end = gamePieces.size();
change = 1;
}else{
start = gamePieces.size();
end = 0;
change = -1;
}
for (int i=start;i<end;i= i+change){
//if(change = )
}
return index;
}
}
GamePiece.java
import java.awt.Color;
import java.awt.Point;
public class GamePiece extends Point{
private Color pieceColor;
public Color getColor(){
return pieceColor;
}
public GamePiece()
{
super();
}
public GamePiece(int x,int y,Color aColor)
{
super(x,y);
pieceColor = aColor;
}
}
Add more printfs to get more information about what is happening. Inside greenMove(), print out the contents of the ArrayList after you do the swap. Do the same inside paintComponent. In the printf, also indicate where these debugging messages are being printed from. In the loop in printComponent, print out the location and color of each piece as you draw it.