I would like to create a table that has a list of dots. I don't know ahead of time how many dots I have, but if they overflow the cell, I want them to wrap, just like text would. My code is something like this:
PdfPTable table = new PdfPTable(1);
table.setTotalWidth(new float[]{80});
table.setLockedWidth(true);
Phrase listOfDots = new Phrase();
for (int i = 0; i < 40; i++) {
listOfDots.add(new Chunk(pdf.correct, 0, 0));
listOfDots.add(new Chunk(" "));
}
table.addCell(listOfDots);
outerCell.addElement(table);
The dots wrap, like I expect, but they don't all have the same size. There are 7 rows of 5 dots each, and all 35 dots have the same size. The last row of 5 dots are roughly half the size of the others.
(I tried to post an image, but I'm not veteran enough on this site.)
Is there a way to make all the images the same size?
Please take a look at the ImagesInChunkInCell example. Instead of a bullet, I took the image of a light bulb. I was able to reproduce the problem you described, but as you can see in list_with_images.pdf, I was able to add one extra line:
Image image = Image.getInstance(IMG);
image.setScaleToFitHeight(false);
PdfPTable table = new PdfPTable(1);
table.setTotalWidth(new float[]{120});
table.setLockedWidth(true);
Phrase listOfDots = new Phrase();
for (int i = 0; i < 40; i++) {
listOfDots.add(new Chunk(image, 0, 0));
listOfDots.add(new Chunk(" "));
}
table.addCell(listOfDots);
The extra line is:
image.setScaleToFitHeight(false);
This prevents that the image is scaled.
Related
As seen above,i used pdfTable as the body part of the page. Now i want to fill the entire body with the border,column,row of the table, if the table does not fill the entire body part.As shown in the picture below.
Thanks very much!
You can sort of cheat to accomplish this if you do it while you are creating the table.
I'll offer a partial solution that takes advantage of one of the complexities tables in PDFs: Tables are just lines in PDFs. They aren't structured content.
You can take advantage of this though- keep track of where you are are drawing vertical lines while rendering the table and simply continue them to the bottom of the page.
Let's create a new cell event. It keeps track of 4 things: left which is the far left x coordinate of the table, right which is the far right x coordinate of the table, xCoordinates which is a set of all the x coordinates we draw vertical lines, and finally cellHeights which is a list off all the cell heights.
class CellMarginEvent implements PdfPCellEvent {
Set<Float> xCoordinates = new HashSet<Float>();
Set<Float> cellHeights = new HashSet<Float>();
Float left = Float.MAX_VALUE;
Float right = Float.MIN_VALUE;
public void cellLayout(PdfPCell pdfPCell, Rectangle rectangle, PdfContentByte[] pdfContentBytes) {
this.xCoordinates.add(rectangle.getLeft());
this.xCoordinates.add(rectangle.getRight());
this.cellHeights.add(rectangle.getHeight());
left = Math.min(left,rectangle.getLeft());
right = Math.max(right, rectangle.getRight());
}
public Set<Float> getxCoordinates() {
return xCoordinates;
}
}
We'll then add all of our cells to the table, but not add the table to the document just yet
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(OUTPUT_FILE));
document.open();
PdfPTable table = new PdfPTable(4);
CellMarginEvent cellMarginEvent = new CellMarginEvent();
for (int aw = 0; aw < 320; aw++) {
PdfPCell cell = new PdfPCell();
cell.addElement(new Paragraph("Cell: " + aw));
cell.setCellEvent(cellMarginEvent);
table.addCell(cell);
}
No we add get top- the top position of our table, and add the table to the document.
float top = writer.getVerticalPosition(false);
document.add(table);
Then we draw the vertical and horizontal lines of the completed table. For the height of each cell I just used the first element in cellHeights.
Set<Float> xCoordinates = cellMarginEvent.getxCoordinates();
//Draw the column lines
PdfContentByte canvas = writer.getDirectContent();
for (Float x : xCoordinates) {
canvas.moveTo(x, top);
canvas.lineTo(x, 0 + document.bottomMargin());
canvas.closePathStroke();
}
Set<Float> cellHeights = cellMarginEvent.cellHeights;
Float cellHeight = (Float)cellHeights.toArray()[0];
float currentPosition = writer.getVerticalPosition(false);
//Draw the row lines
while (currentPosition >= document.bottomMargin()) {
canvas.moveTo(cellMarginEvent.left,currentPosition);
canvas.lineTo(cellMarginEvent.right,currentPosition);
canvas.closePathStroke();
currentPosition -= cellHeight;
}
And finally close the document:
document.close()
Example output:
Note that the only reason I say this is an incomplete examples is because there may be some adjustments you need to make to top in the case of header cells, or there may be custom cell styling (background color, line color, etc) you need to account for yourself.
I'll also note another downfall that I just thought of- in the case of tagged PDFs this solution fails to add tagged table cells, and thus would break compliance if you have that requirement.
so I want to make my Jscrollpane to show Pascals triangle. I have this:
labelPanel= new JPanel();
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
labelPanel.add(lRows[i]);
}
But it's not what I want and I am not sure how to fix that, picture included. Any help?
By default, JPanel uses a flow layout. To get the vertical arrangement you are looking for, you should be able to do this by using a BoxLayout with a vertical orientation on your labelPanel, then add your JLabel rows.
labelPanel= new JPanel();
//set this up to order things vertically
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
//to center your label, just set the X alignment
lRows[i].setAlignmentX(Component.CENTER_ALIGNMENT)
labelPanel.add(lRows[i]);
}
I also threw in a line to center the rows like your picture. Component comes from the java.awt package.
You can read up on the different layout managers available by default in the Java Tutorial
The easiest solution is to rotate the triangle to make it look like:
1 1 1 1 1 1 1
1 2 3 4 5 6
1 3 6 10 15
1 4 10 20
1 5 15
1 6
1
However, if you must print sth like this
I did it this way:
for (int i = 0; i<n; i++){
for (int j = 0; j<Triangle.trojkat[i].length; j++){
sb.append(Triangle.trojkat[i][j]);
len = String.valueOf(Triangle.trojkat[i][j]).length();
while (12-len>0){
sb.append(" ");
len++;
}
//sb.append(" ");
}
TriangleRes[i] = new JLabel(sb.toString(), JLabel.CENTER);
TriangleRes[i].setFont(new Font("Serif",Font.PLAIN,8));
sb = new StringBuilder();
}
Let me explain:
I decided, that I want my triangle print beautifuly for the size smaller that 35. Then I've checked, that the numbers in such a triangle come up to 10 digits. Then, when I added next number to the existing row, I checked it's length and while total length wasn't 12 yet, I add spaces. This lead to the triangle that you have attached on the picture.
If this is for Ph.D Macyna classes, just post a question on a group and I'll respond :)
Use a JTextArea
Give it a monospaced font, i.e., Font.MONOSPACED
Append your lines of text to the JTextArea, similar to how you'd do this in the console.
Put the JTextArea into a JScrollPane
Voilà. You're done.
If you need to use JLabels, then put them in a JPanel that uses GridLayout with enough columns to show your bottom row.
If you did this, you'd be putting empty JLabels in every other cell, so that the cells branch correctly.
I have a table, with one column. Each cell contains a paragraph.
How can I stop paragraphs from splitting across two pages?
PdfPtable table = new PdfPTable(1);
//report must be printed as compat as possible
table.setSplitLate(false);
//I can't set keep together, because table can be larger than page size
//table.setKeepTogether(true);
for (int i = 0; i < 100; i++) {
//Random text. Can contain ~400 chars.
String text = "aaaaaaaaaaaaaaa sssssssssssss ddddddddddd ffffffffff";
Paragraph p = new Paragraph(text);
//That instruction does not work. I don't know why, may be because paragraph printed in cell.
p.setKeepTogether(true);
table.addCell(p);
}
Change
table.setSplitLate(false);
into
table.setSplitLate(true);
This way, your cell will not be split unless the complete cell doesn't fit on a single page.
so I want to make my Jscrollpane to show Pascals triangle. I have this:
labelPanel= new JPanel();
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
labelPanel.add(lRows[i]);
}
But it's not what I want and I am not sure how to fix that, picture included. Any help?
By default, JPanel uses a flow layout. To get the vertical arrangement you are looking for, you should be able to do this by using a BoxLayout with a vertical orientation on your labelPanel, then add your JLabel rows.
labelPanel= new JPanel();
//set this up to order things vertically
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
lRows = new JLabel[n];
for (int i=0;i<n;i++){
lRows[i]=new JLabel(Arrays.toString(tri.tri[i]));
//to center your label, just set the X alignment
lRows[i].setAlignmentX(Component.CENTER_ALIGNMENT)
labelPanel.add(lRows[i]);
}
I also threw in a line to center the rows like your picture. Component comes from the java.awt package.
You can read up on the different layout managers available by default in the Java Tutorial
The easiest solution is to rotate the triangle to make it look like:
1 1 1 1 1 1 1
1 2 3 4 5 6
1 3 6 10 15
1 4 10 20
1 5 15
1 6
1
However, if you must print sth like this
I did it this way:
for (int i = 0; i<n; i++){
for (int j = 0; j<Triangle.trojkat[i].length; j++){
sb.append(Triangle.trojkat[i][j]);
len = String.valueOf(Triangle.trojkat[i][j]).length();
while (12-len>0){
sb.append(" ");
len++;
}
//sb.append(" ");
}
TriangleRes[i] = new JLabel(sb.toString(), JLabel.CENTER);
TriangleRes[i].setFont(new Font("Serif",Font.PLAIN,8));
sb = new StringBuilder();
}
Let me explain:
I decided, that I want my triangle print beautifuly for the size smaller that 35. Then I've checked, that the numbers in such a triangle come up to 10 digits. Then, when I added next number to the existing row, I checked it's length and while total length wasn't 12 yet, I add spaces. This lead to the triangle that you have attached on the picture.
If this is for Ph.D Macyna classes, just post a question on a group and I'll respond :)
Use a JTextArea
Give it a monospaced font, i.e., Font.MONOSPACED
Append your lines of text to the JTextArea, similar to how you'd do this in the console.
Put the JTextArea into a JScrollPane
Voilà. You're done.
If you need to use JLabels, then put them in a JPanel that uses GridLayout with enough columns to show your bottom row.
If you did this, you'd be putting empty JLabels in every other cell, so that the cells branch correctly.
What is the recommended way of printing a text document as a pdf using absolute positioning ?
I am having a table that I have to print. I am also having the data type lengths and starting positions of the columns.
Since the existing table was a character based, there was no problem in its positioning. But even after using a monotype font (Courier, 10) I am not able to properly position the data and last column(s) of each row erroneously skip to the next line.
In order to present my data as close as the character one, I divided the page into different columns(based on its page size) and then add the contents at the desired place. I am adding chunks of data into the paragraph.
paragraph.add(new Chunk(new VerticalPositionMark(), columnNo*ptUnit, false));
I have tried to tweak the page size, font size and margin lengths, but the data is not properly displayed. Have you encountered any such problems ? please do share your thoughts.
Have you tried ColumnText
When i want to write a paragraph and I do know the amount of lines...I do a cycle incrementing (even it says incrementing and is minus is because the pdf is from "south" to "north" (0 - height) the y in a proportion of the fontsize, something like this
//_valueArray is my string[]
//fontSize is the value of the Size of the font...
//1.5 it's just a magic number :) that give me the space line that i need
//cbLocal is the PdfContentByte of the pdf
for (i = 0; i < _valueArray.Length; i++)
{
var p = new Phrase(_valueArray[i], font);
ColumnText.ShowTextAligned(cbLocal, align, p, x, y, 0);
if (i + 1 != _valueArray.Length)
{
y = y - (fontSize*1.5f);
}
}