First line and last line in jtextarea viewport - java

i am looking for a function which gives the viewport starting line and viewport ending line from jtextarea. The below code works fine. But when the number of lines in the jtextarea is too big, say 10,000 lines, response of the cursor becoming very slow. I narrowed down the line which is causing it, it is,
startLine = getRow(topLeft, editorTextArea) - 1; //editorTextArea is jtextarea name
endLine = getRow(bottomRight, editorTextArea);
I am calling the startAndEndLine() on every keyPressEvent
Can someone suggest me a better code, which is efficient?
private void startAndEndLine() {
Rectangle r = editorTextArea.getVisibleRect();
Point topLeft = new Point(r.x, r.y);
Point bottomRight = new Point(r.x + r.width, r.y + r.height);
try {
startLine = getRow(topLeft, editorTextArea) - 1;
endLine = getRow(bottomRight, editorTextArea);
} catch (Exception ex) {
// System.out.println(ex);
}
}
public int getViewToModelPos(Point p, JTextComponent editor) {
int pos = 0;
try {
pos = editor.viewToModel(p);
} catch (Exception ex) {
}
return pos;
}
public int getRow(Point point, JTextComponent editor) {
int pos = getViewToModelPos(point, editor);
int rn = (pos == 0) ? 1 : 0;
try {
int offs = pos;
while (offs > 0) {
offs = Utilities.getRowStart(editor, offs) - 1;
rn++;
}
} catch (BadLocationException e) {
System.out.println(e);
}
return rn;
}

This is based on a solution by JigarJoshi from this question Java: column number and line number of cursor's current position ... You gotta love this site ;)
protected int getLineNumber(int modelPos) throws BadLocationException {
return textArea.getLineOfOffset(modelPos) + 1;
}
Rectangle viewRect = scrollPane.getViewport().getViewRect();
Point startPoint = viewRect.getLocation();
int pos = textArea.viewToModel(startPoint);
try {
int startLine = getLineNumber(pos);
Point endPoint = startPoint;
endPoint.y += viewRect.height;
pos = textArea.viewToModel(endPoint);
int endLine = getLineNumber(pos);
System.out.println(startLine + " - " + endLine);
} catch (BadLocationException exp) {
}
This is not entirely accurate, but gives you a starting point.

Related

Printing a text document using Java

Alright, I have made a program that makes a text file. The text file is a different size every time the program is ran. I simply just want to add a print button that allows the user to print out the text file to a printer. I made a button with an action listener that brings up my print class. It is almost working except it only prints one page with my text displayed in horizontal columns extremely small. I think my problem has something to do with my printJob setup. Any help would be greatly appreciated.
public class PrintingClass implements Printable {
// Global variables
int[] pageBreaks;
String [] textLines;
static String fileName;
public static void print(String filename){
fileName = filename;
PrintingClass object = new PrintingClass();
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(object);
Boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException {
Font font = new Font("Monospaced", Font.PLAIN, 12);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
if (pageBreaks == null) {
initTextLines();
int linesPerPage = (int)(pf.getImageableHeight()/lineHeight);
System.out.println("Lines per page = " + linesPerPage);
int numBreaks = (textLines.length-1)/linesPerPage;
System.out.println("number of pages = " + numBreaks);
pageBreaks = new int[numBreaks];
for (int b=0; b<numBreaks; b++) {
pageBreaks[b] = (b+1)*linesPerPage;
}
}
if (pageIndex > pageBreaks.length) {
return NO_SUCH_PAGE;
}
/* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
* Since we are drawing text we
*/
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Draw each line that is on this page.
* Increment 'y' position by lineHeight for each line.
*/
int y = 0;
int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex-1];
int end = (pageIndex == pageBreaks.length)
? textLines.length : pageBreaks[pageIndex];
for (int line=start; line<end; line++) {
y += lineHeight;
g.drawString(textLines[line], 0, y);
}
/* tell the caller that this page is part of the printed document */
return PAGE_EXISTS;
}
/**
* This will initialize the textLines[] variable
* and read in my file
* #param fileName
*/
public void initTextLines(){
// Get file size
int fileSize = counter();
// Initialize textLine
textLines = new String[fileSize];
// Read text to set lines
BufferedReader file;
try {
file = new BufferedReader(new FileReader(fileName));
String line = null;
int x = 0;
while((line = file.readLine()) != null){
textLines[x] = line;
x++;
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* This will simply count the size of the file
* and return it
* #return
*/
public int counter(){
int count = 0;
try {
BufferedReader file = new BufferedReader(new FileReader(fileName));
while(file.readLine() != null){
count++;
}
file.close();
} catch (IOException e) {
e.printStackTrace();
}
return count;
}
}
Most of this code comes straight from Javas own tutorial page. Thank you.

java.io.IOException: RandomAccessBuffer already closed, when reading a PDPage

I've created a program to convert a PDF to Excel. The conversion takes a long time (100 page=10 minutes). It runs fine for about 15-20 minutes, after that an error occurs when reading the PDPage.
Is it possible the Java GC "clean" the variable before the programs end?
the code:
private class Search_Text implements Runnable {
private int x, y, width, height;
private PDPage pdPage;
private Object lock;
private ArrayList<Object[]> result;
private PDFTextStripperByArea strip;
public Search_Text(int x, int y, int width, int height, PDPage pdPage, Object lock) throws IOException {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.pdPage = pdPage;
this.lock = lock;
this.result = new ArrayList<>();
this.strip = new PDFTextStripperByArea();
}
#Override
public void run() {
if (height < 10) {
int upper = y;
int bottom = 1;
ArrayList<Object[]> st = new ArrayList<>();
String str = "";
while (upper + bottom <= y + height) {
strip.addRegion("cell", new Rectangle(x, upper, width, bottom));
//System.out.println("prova.Pdf2Excell.log_extract()BEFORE LOCK" + init);
synchronized (lock) {
try {
strip.extractRegions(pdPage);
} catch (IOException ex) {
Logger.getLogger(Pdf2Excell.class.getName()).log(Level.SEVERE, null, ex);
}
}
str = strip.getTextForRegion("cell");
if (!emptyString(str)) {
st.add(new Object[]{str, upper + bottom, upper});
upper += bottom;
bottom = 1;
while (upper + bottom < height + y && !emptyString(str)) {
strip.addRegion("cell", new Rectangle(x, upper, width, bottom));
synchronized (lock) {
try {
strip.extractRegions(pdPage);
} catch (IOException ex) {
Logger.getLogger(Pdf2Excell.class.getName()).log(Level.SEVERE, null, ex);
}
}
str = strip.getTextForRegion("cell");
upper++;
//System.out.println("prova.Pdf2Excell.pdf2EX()DENTRO");
}
} else {
bottom += 1;
//System.out.println("prova.Pdf2Excell.pdf2EX()UPPER;;"+upper+";;BOTTOM;;" + bottom);
}
if (upper == y) {
st.add(new Object[]{"", y + height, upper});
}
result = st;
}
} else {
try {
int half_rec = height / 2;
Rectangle first_rec = new Rectangle(x, y, width, half_rec);
Rectangle last_rec = new Rectangle(x, y + half_rec, width, height - half_rec);
Search_Text first_search = new Search_Text(x, y, width, half_rec, pdPage, lock);
Search_Text last_search = new Search_Text(x, y + half_rec, width, height - half_rec, pdPage, lock);
Thread first = new Thread(first_search);
Thread last = new Thread(last_search);
strip.addRegion("cell", first_rec);
synchronized (lock) {
strip.extractRegions(pdPage);
}
String temp = strip.getTextForRegion("cell");
if (!emptyString(temp)) {
first.start();
}
strip.addRegion("cell", last_rec);
synchronized (lock) {
strip.extractRegions(pdPage);
}
temp = strip.getTextForRegion("cell");
if (!emptyString(temp)) {
last.start();
}
first.join();
last.join();
result = first_search.getResult();
ArrayList<Object[]> temp_res = last_search.getResult();
for (int i = 0; i < temp_res.size(); i++) {
result.add(temp_res.get(i));
}
} catch (InterruptedException | IOException ex) {
Logger.getLogger(Pdf2Excell.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
This is the error message:
Exception in thread "Thread-214418" java.lang.RuntimeException: java.io.IOException: RandomAccessBuffer already closed
at org.apache.pdfbox.pdfparser.PDFStreamParser$1.tryNext(PDFStreamParser.java:198)
at org.apache.pdfbox.pdfparser.PDFStreamParser$1.hasNext(PDFStreamParser.java:205)
at org.apache.pdfbox.util.PDFStreamEngine.processSubStream(PDFStreamEngine.java:255)
at org.apache.pdfbox.util.PDFStreamEngine.processSubStream(PDFStreamEngine.java:235)
at org.apache.pdfbox.util.PDFStreamEngine.processStream(PDFStreamEngine.java:215)
at org.apache.pdfbox.util.PDFTextStripper.processPage(PDFTextStripper.java:458)
at org.apache.pdfbox.util.PDFTextStripperByArea.extractRegions(PDFTextStripperByArea.java:153)
at prova.Pdf2Excell$Search_Text.run(Pdf2Excell.java:954)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: RandomAccessBuffer already closed
at org.apache.pdfbox.io.RandomAccessBuffer.checkClosed(RandomAccessBuffer.java:325)
at org.apache.pdfbox.io.RandomAccessBuffer.seek(RandomAccessBuffer.java:105)
at org.apache.pdfbox.io.RandomAccessFileInputStream.read(RandomAccessFileInputStream.java:96)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:284)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at java.io.PushbackInputStream.read(PushbackInputStream.java:139)
at org.apache.pdfbox.io.PushBackInputStream.read(PushBackInputStream.java:90)
at org.apache.pdfbox.io.PushBackInputStream.peek(PushBackInputStream.java:68)
at org.apache.pdfbox.pdfparser.PDFStreamParser.hasNextSpaceOrReturn(PDFStreamParser.java:560)
at org.apache.pdfbox.pdfparser.PDFStreamParser.parseNextToken(PDFStreamParser.java:408)
at org.apache.pdfbox.pdfparser.PDFStreamParser.parseNextToken(PDFStreamParser.java:374)
at org.apache.pdfbox.pdfparser.PDFStreamParser.access$000(PDFStreamParser.java:49)
at org.apache.pdfbox.pdfparser.PDFStreamParser$1.tryNext(PDFStreamParser.java:193)
... 8 more
PDFBox has been developed for single-threaded use per document while the OP accesses the same document using multiple threads. While this may still work (because it is a read-only use case), proper synchronization is necessary.
This synchronization most likely would have slowed down everything still more. Thus, the solution was to use a different architecture altogether, namely to
take PDFTextStripper, override writeString(String text, List<TextPosition> textPositions), and collect the required information from that List<TextPosition> textPositions. TextPosition contains information on a small piece of text (usually a single letter, I think), including its position.
The result turned out to be
like 4 times faster.

J2ME , Quizz using choiceGroups

I am working on a driving licence project on j2Me wich is including Tests like quizz , well and i am having a problem after parsing the questions and moving them into choiceGroups just like that :
if (questions.length > 0) {
for (int i = 0; i < questions.length; i++) {
ChoiceGroup reponses = new ChoiceGroup("Reponses" + i, Choice.EXCLUSIVE);
reponses.append(questions[i].getReponse1(), null);
reponses.append(questions[i].getReponse2(), null);
reponses.append(questions[i].getReponse3(), null);
pass.append(questions[i].getContenu());
pass.append(reponses);
}
}
} catch (Exception e) {
System.out.println("Exception:" + e.toString());
}
disp.setCurrent(pass);
and the next step is the command who's controlling the choiceGroups to test them if they are like the true answer or not .
so i am blocked here .
if (c == valider) {
int result = 0;
for (int i = 0; i < pass.size(); i++) {
String ch = pass.get(i).getLabel();
System.out.println(ch);
}
}
I don't know how to get the choice from the choicegroup
any help
Actually, I am not sure what totally you want for:
This code will help you get selected items from choicegroup that i did long time before:
//get a selected array in choicegroup
private String[] choiceGroupSelected(ChoiceGroup cg) {
String selectedArray[] = new String[cg.size()];
int k = 0;
for (int i = 0; i < cg.size(); i++) {
if (cg.isSelected(i)) {
selectedArray[k] = cg.getString(i);
k++;
}
}
return selectedArray;
}
That function will help me get all selected items for deleting action below:
private void deleteSpecificItem() {
try {
String temp = null;
int index;
//get ChoiceGroup size
int numbers = cgTrip.size();
String selectedItems[] = choiceGroupSelected(cgTrip);
//
rs = services.RecordStoreManager.openRecordStoreByName("TripRS");
re = rs.enumerateRecords(null, null, true);
String[] tripList = new String[2];
for (int i = 0; i < numbers; i++) {
temp = selectedItems[i];
if (temp != null) {
while (re.hasNextElement()) {
try {
index = re.nextRecordId();
System.out.println("RecordID: " + index);
byte[] byteBuff = rs.getRecord(index);
String source = new String(byteBuff);
tripList = services.StringManager.getItems(source, ";", 2);
String strProcess = tripList[0] + "-" + tripList[1];
//inspect all of items in choicegroup and if they are selecting then compare with record
//If comparison is true then delete this record
if (temp.equals(strProcess)) {
System.out.println("Delete RecordID: " + index);
rs.deleteRecord(index);
re.keepUpdated(true);
break;
}
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
}
}
try {
rs.closeRecordStore();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
rs = null;
re.destroy();
this.LoadTripItem();
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
}
}

Find multiple words in a String and get index of

I have a big String (XML Style) and I provide a text-field for capturing the words to search. All words found should be highlighted.
The problem i have is, that the words can appear multiple times in that String but only the first/or last word is highlighted.
I found out that the problem is that the selectionStart and ending is always the same.
Can u help me ?
public static void searchTextToFind(String textToFind) {
highlighter.removeAllHighlights();
String CurrentText = textPane.getText();
StringReader readtext;
BufferedReader readBuffer;
int i = 0;
int matches = 0;
readtext = new StringReader(CurrentText);
readBuffer = new BufferedReader(readtext);
String line;
try {
i = CurrentText.indexOf(textToFind);
int start = 0;
int end = 0;
Pattern p = Pattern.compile(textToFind);
while ((line = readBuffer.readLine()) != null) {
Matcher m = p.matcher(line);
// indicate all matches on the line
while (m.find()) {
matches++;
while (i >= 0) {
textPane.setSelectionStart(i);
textPane.setSelectionEnd(i + textToFind.length());
i = CurrentText.indexOf(textToFind, i + 1);
start = textPane.getSelectionStart();
end = textPane.getSelectionEnd();
try {
highlighter.addHighlight(start, end,
myHighlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
JOptionPane.showMessageDialog(paneXML,
matches+" matches have been found", "Matched",
JOptionPane.INFORMATION_MESSAGE);
}
You have a LOT of redundant code. Here's a short and sweet solution using String.indexOf
public static void searchTextToFind(String textToFind) {
highlighter.removeAllHighlights();
textToFind = textToFind.toLowerCase(); //STRINGS ARE IMMUTABLE OBJECTS
String currentText = textPane.getText(); //UPPERCASE LOCALS ARE EVIL
currentText = currentText.toLowerCase(); //STRINGS ARE IMMUTABLE OBJECTS
int offset = 0;
for(int index = currentText.indexOf(textToFind, offset); index >= 0; index = currentText.indexOf(textToFind, offset)){
int startIndex = currentText.indexOf(textToFind, offset);
int endIndex = startIndex + textToFind.length() - 1; //this gets you the inclusive endIndex.
textPane.setSelectionStart(startIndex);
textPane.setSelectionEnd(endIndex);
offset = startIndex + 1; //begin the NEXT search at startIndex + 1 so we don't match the same string over and over again
System.out.println(startIndex);
System.out.println(endIndex);
try {
highlighter
.addHighlight(startIndex, endIndex, myHighlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}

Draw multiple shapes using loop - Android Canvas

I am very new to android development and have been trying to draw a square comprised of multiple smaller rectangles of different colours... Like a Mosaic essentially.
Basically at the moment I am reading values from a file which assigns the colour to the smaller Rects. I am using a pair of nested for loops to try to draw the small Rects sequentially, line by line. However when the program finishes there is only one small Rect drawn which is the last one to be drawn and its colour corresponds to the first value read from the file.
Here is some of my code to show you what I mean:
public SnapshotDraw(Context context) {
super(context);
for(int a = 0; a < 63; a++){
for(int b = 0; b < 63; b++){
fileName = PREFIX + "2" + EXTENSION;
try {
bf = new BufferedReader(new FileReader(fileName));
tokens = new StringTokenizer(bf.readLine(), " \n");
weight = Byte.parseByte(tokens.nextToken());
x_scalar = b*MAG;
y_scalar = a*MAG;
mDrawable = new ShapeDrawable(new RectShape());
mDrawable.getPaint().setColor(colour.getColour(weight));
mDrawable.setBounds((X_OFFSET + x_scalar), (Y_OFFSET + y_scalar), ((MAG + X_OFFSET) + x_scalar), ((MAG + Y_OFFSET) + y_scalar));
} catch (FileNotFoundException ex) {
Logger.getLogger(NetworkUtilities.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(NetworkUtilities.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
This except is from a class which extends View and is called inside an onCreate() method in an Activity.
I would appreciate any guidance in this and thanks in advance!!
Cheers.
You are constructing the BufferedReader inside the loops, so bf.readLine() will always return the same line. Try moving bf and tokens (be aware that the use of StringTokenizer is discouraged) out of the loops.
Ok I got it sorted! Here is what I did to solve it:
public SnapshotDraw(Context context) {
super(context);
setFocusable(true);
mBitmap = Bitmap.createBitmap(475, 720, Bitmap.Config.ALPHA_8);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Paint p = new Paint();
float y = 10;
try {
fileName = PREFIX + "2" + EXTENSION;
bf = new BufferedReader(new FileReader(fileName));
for(int a = 0; a < 63; a++){
tokens = bf.readLine().split(" \n");
for(int b = 0; b < 63; b++){
weight = Byte.parseByte(tokens[b]);
x_scalar = b*MAG;
y_scalar = a*MAG;
p.setColor(new Colour().getColour(weight));
canvas.drawRect((X_OFFSET + x_scalar), (Y_OFFSET + y_scalar), ((MAG + X_OFFSET) + x_scalar), ((MAG + Y_OFFSET) + y_scalar), p);
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(NetworkUtilities.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(NetworkUtilities.class.getName()).log(Level.SEVERE, null, ex);
}
canvas.drawBitmap(mBitmap, 10, y, p);
}
Much the same as before but changed the way I draw to the Bitmap. It looks beautiful btw!!

Categories