I am trying to draw a string exactly in the center of a rectangle using JavaFX GraphicsContext2D.
I don't want to use JavaFX components so please do not recommend them.
For example, I stroke a rectangle with attributes: x = 10, y = 10, width = 100, height = 100. Now I want to stroke a text in a way that it comes exactly in the center(horizontally and vertically) of the rectangle. How can I do it?
As #James_D comments, you can use the GraphicsContext methods setTextAlign() and setTextBaseline() to center the fillText() in an arbitrary Rectangle. Starting from this example, I added the following lines in the tooltips loop in order to produce the image shown:
gc.setTextAlign(TextAlignment.CENTER);
gc.setTextBaseline(VPos.CENTER);
gc.setFill(Color.BLACK);
gc.fillText(color.toString(),
bounds.getX() + bounds.getWidth() / 2,
bounds.getY() + bounds.getHeight() / 2);
Related
I have an android game where the canvas is scaled to look the same on all devices using this code:
canvas.scale((float)(getWidth()/(double)WIDTH), (float)(getHeight()/(double)HEIGHT))
where WIDTH and HEIGHT are 1920 and 1080 respectively. My problem is that for all my touch collisions (i.e. a user touching a shape) is handled using Paths and Regions:
public static boolean collided(Path a, Path b) {
Region clip = new Region(0,0,3000, 3000);
Region rA = new Region();
rA.setPath(a, clip);
Region rB = new Region();
rB.setPath(b, clip);
return !rA.quickReject(rB) && rA.op(rB, Region.Op.INTERSECT);
}
Now I also have another scale method (that barely has any effect from what I can tell, but on occasion does have an influence) to scale coordinates and dimensions:
public static double scale(double x) {
return dpToPx(x)/Resources.getSystem().getDisplayMetrics().density;
}
My problem is that with all of this scaling I can't seem to get the mouse to be in the correct position. Here is the code I use to create the mouse Path that handles collision between the mouse and other shapes:
mouse.set(x, y);
mousePath.reset();
mousePath.addRect(mouse.x - 10, mouse.y - 10, mouse.x + 10, mouse.y + 10, Path.Direction.CW);
I draw mousePath to see where the mousePath is and this is the result I get (it is the box in green and where the mouse actually is in the general area of the blue circle)
This is the much more severe point, as it seems the closer I get to (0,0) the closer mousePath gets to being at where the mouse actually is.
So how do I get the mouse to be in the correct location?
After more searching it turns out this question is a duplicate of: https://stackoverflow.com/a/24895485/4188097.
The browser always returns the mouse position in untransformed coordinates. Your drawings have been done in transformed space. If you want to know where your mouse is in transformed space, you can convert untransformed mouse coordinates to transformed coordinates like this:
var mouseXTransformed = (mouseX-panX) / scaleFactor;
var mouseYTransformed = (mouseY-panY) / scaleFactor;
I use the class org.apache.pdfbox.pdmodel.PDPageContentStream for write text into PDF file.
I need to scale the text horizontally.
How can it be done?
do this before drawing your text:
contentStream.transform(Matrix.getScaleInstance(2, 1));
this will enlarge on the x axis. If this effect is to be temporary, don't forget to put your draw commands within saveGraphicsState() and restoreGraphicsState().
Alternatively, use setTextMatrix() with the same parameter. The later one has the advantage that one call replaces the previous.
THIS IS CORRECT CODE:
contentStream.saveGraphicsState();
contentStream.beginText();
contentStream.setFont(currentBaseFont, currentFontSize);
//X HORIZONTAL SCALING
Matrix scaleInstance = Matrix.getScaleInstance(scalaRiga / 100f, 1);
contentStream.transform(scaleInstance);
float rot = (float)((rotazione == 90)?(Math.PI / 2):(Math.PI * 2));
contentStream.setTextMatrix(Matrix.getRotateInstance(rot, x, y));
contentStream.showText(txpDati.getDati());
contentStream.endText();
contentStream.restoreGraphicsState();
THANK YOU TILMAN
FR
I am trying to center a minus sign on the screen using the following code:
text = "-";
textPosition = new Point();
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
paint.setTextAlign(Paint.Align.CENTER);
textPosition.x = (int) (myArea.left + myArea.width() / 2);
textPosition.y = (int) (myArea.top + myArea.height() / 2 + bounds.height() / 2);
canvas.drawText(text, textPosition.x, textPosition.y, paint);
This code works like a charm when "text" is something else (for example a plus sign), but in this case the minus sign is positioned too high on the screen.
EDIT:
Here is the result for four different operators.
And... the funny thing is, that I created my own font to display these operators. So I know, that it should be centered correctly.
PS: Now that I look at it, all off them seem a little off, though the minus-sign is the worst...
Okay, I fixed it. Not by changing the code, but by changing the font. I have now aligned all characters on the baseline and that seems to work.
I try to draw some nested tables in iText as i thought it would be the easiest way to position everything.
So i have multiple tables inside another table who all have background color and/or strokes (via PdfPCellEvents). Unfortunately the strokes of the outer table are overlapping the background of the inner table.
I assume that comes from a wrong order of applying or some wrong set saveState or restoreState in my PdfPCellEvents.
Can anyone explain the right usage of saveState and restoreState to me and give me a hint how to apply backgrounds and strokes the right way?
Here is my code for adding a striped background cell:
PdfPCell scaleBackground = new PdfPCell();
scaleBackground.setBorder(Rectangle.NO_BORDER);
scaleBackground.setVerticalAlignment(Element.ALIGN_TOP);
scaleBackground.setCellEvent(new StripedScaleBackground(max, scaleHeight));
cellLayout method of StripedScaleBackground:
public void cellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] canvases)
{
PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
float llx = rect.getLeft();
float lly = rect.getBottom();
float urx = rect.getRight();
float ury = rect.getTop();
// Light scale lines with padding from left
canvas.setLineWidth(Constants.BORDER_WIDTH_THIN);
canvas.setColorStroke(Colors.LIGHT_GRAY);
float paddingLeft = 22f;
for (int i = 0; i <= this.maxValue; i++)
{
canvas.moveTo(llx + paddingLeft, lly + (this.scaleHeight * (i + 1)));
canvas.lineTo(urx, lly + (this.scaleHeight * (i + 1)));
}
// Vertical line
canvas.moveTo(llx + (((urx - llx) + paddingLeft) / 2), ury);
canvas.lineTo(llx + (((urx - llx) + paddingLeft) / 2), lly);
canvas.stroke();
// Fat line left and right
canvas.moveTo(llx, ury);
canvas.lineTo(llx, lly);
canvas.moveTo(urx, ury);
canvas.lineTo(urx, lly);
canvas.setLineWidth(0.8f);
canvas.setColorStroke(Colors.MEDIUM_GRAY);
canvas.stroke();
canvas.saveState();
canvas.restoreState();
}
The bar charts are tables where each cell has a cell event for gradient and border. The bar charts are added to the scaleBackground PdfPCell of the first piece of code and have following PdfPCellEvents (example of black part of the chart):
public void cellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] canvases)
{
PdfContentByte backgroundCanvas = canvases[PdfPTable.BACKGROUNDCANVAS];
float llx = rect.getLeft();
float lly = rect.getBottom();
float urx = rect.getRight();
float ury = rect.getTop();
// Draw background
// Define shading with direction and color
PdfShading shading = PdfShading.simpleAxial(this.writer,
llx, ury,
llx, lly,
Colors.BAR_CHART_BLACK_LIGHT, Colors.BAR_CHART_BLACK_DARK);
PdfShadingPattern pattern = new PdfShadingPattern(shading);
backgroundCanvas.setShadingFill(pattern);
// Draw shape with defined shading
backgroundCanvas.moveTo(llx, ury);
backgroundCanvas.lineTo(llx, lly);
backgroundCanvas.lineTo(urx, lly);
backgroundCanvas.lineTo(urx, ury);
backgroundCanvas.lineTo(llx, ury);
backgroundCanvas.fill();
backgroundCanvas.saveState();
backgroundCanvas.restoreState();
// Draw border
PdfContentByte lineCanvas = canvases[PdfPTable.LINECANVAS];
float lineWidth = Constants.BORDER_WIDTH_THIN;
lineCanvas.setLineWidth(lineWidth);
lineCanvas.moveTo(llx, ury - lineWidth);
lineCanvas.lineTo(llx, lly);
lineCanvas.lineTo(urx, lly);
lineCanvas.lineTo(urx, ury - lineWidth);
lineCanvas.setColorStroke(BaseColor.BLACK);
lineCanvas.stroke();
lineCanvas.saveState();
lineCanvas.restoreState();
}
This is the order of the different direct content layers:
PdfPtable.BASECANVAS—Anything placed here will be under the table.
PdfPtable.BACKGROUNDCANVAS—This is the layer where the backgrounds are
drawn.
PdfPtable.LINECANVAS—This is the layer where the lines are drawn.
PdfPtable.TEXTCANVAS—This is the layer where the text goes. Anything placed
here will cover the table.
This was taken from the book "iText in Action - Second Edition."
You also ask about saveState() and restoreState(). This is explained in Chapter 2 of the iText 7 tutorial:
First we save the current graphics state with the saveState() method, then we change the state and draw whatever lines or shapes we want to draw, finally, we use the restoreState() method to return to the original graphics state. All the changes that we applied after saveState() will be undone. This is especially interesting if you change multiple values (line width, color,...) or when it's difficult to calculate the reverse change (returning to the original coordinate system).
Your code was too long for me to inspect, but I highly doubt that saveState()/restoreState() would be the cause of your problem.
I would try to avoid nesting tables as much as possible. It is usually much easier (and more efficient) to use colspan and rowspan.
If this doesn't solve your problem, please explain your problem in one sentence.
I am trying to place two words at the center of the image. But the drawString method does not seem to correctly pickup the "x" coodinate. For example I am trying to place the words "setupa" and "asetup" (image width 30). My image width is 106, thus the x-cord value is 38 in both the cases. But in reality asetup is places at 1-2 pixel shift.
It produces just minor difference, but that shows up in my images.
Sample code is follows.
Graphics2D textGraphics;
textGraphics = image.createGraphics();
textGraphics.setColor(fontColor);
textGraphics.setFont(font);
FontRenderContext frc = new FontRenderContext(null, true, true);
TextLayout layout = new TextLayout(label, font, frc);
Rectangle r = layout.getPixelBounds(frc, 0, 0);
textGraphics.drawString(label, ((imageWidth / 2) - (r.width/2)), (imageWidth / 2));
Is they any way around this? or a better way to place the text at the center.
Thanks