issues with putting a JPanel in a JScrollPanel - java

im working on a project where i am drawing an image on a JPanel and then putting that panel inside a JScrollPane. The panel itself will vary in size sometimes being smaller than the screen, sometimes larger. When it is larger the scrollpane doesn't seem to have any scroll bars appearing. Im sure im messing something up that is simple but i can't seem to figure it out.
Any help would be greatly appreaciated.
public void createGI(theTicket[] ticketArray){
JFrame ticketReportFrame = new JFrame();
ticketReportFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel ticketReport = new drawTurnoverReport(ticketArray , notes, tapes, turnover);
ticketReport.setBackground(Color.WHITE);
ticketReport.setLayout(new BorderLayout());
JScrollPane ticketReportHolder = new JScrollPane(ticketReport);
ticketReportFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
ticketReportFrame.pack();
ticketReportHolder.setWheelScrollingEnabled(true);
ticketReportFrame.add(ticketReportHolder);
ticketReportFrame.setVisible(true);
ticketReportFrame.setResizable(false);
}
this is just a small portion of drawTurnoverReport to try and help show what i am doing.
public class drawTurnoverReport extends JPanel{
public drawTurnoverReport(theTicket[] tickets, String[] n, String[] t, String[] to){
ticArray = tickets;
notes = n;
tapes = t;
turnover = to;
formalDate = mt.formalDate;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent( g );
Graphics2D g2 = (Graphics2D) g;
//set fonts
Font tahomaB = new Font("tahoma", Font.BOLD, 15);
Font tahomaP = new Font("tahoma", Font.PLAIN, 15);
//draw heading
g2.setColor(Color.BLACK);
g2.setFont(tahomaB);
Rectangle2D rec = g2.getFontMetrics().getStringBounds("Turnover / Activity Log", g2);
int stringW = (int) rec.getWidth();
int prevStringH = (int) rec.getHeight();
g2.drawString("Turnover / Activity Log", x-(stringW / 2) , 50);
g2.setFont(tahomaP);
rec = g2.getFontMetrics().getStringBounds("Date: " + formalDate, g2);
stringW = (int) rec.getWidth();
verticalPlace = 50 + prevStringH;
g2.drawString("Date: " + formalDate, x-(stringW / 2) , verticalPlace);
prevStringH = (int) rec.getHeight();
verticalPlace += prevStringH;
g2.setFont(tahomaB);
rec = g2.getFontMetrics().getStringBounds("Service Manager Tickets", g2);
stringW = (int) rec.getWidth();
g2.drawString("Service Manager Tickets", x-(stringW / 2) , verticalPlace);
verticalPlace +=2;
g2.drawLine(((int)rec.getMinX()+ x)-(stringW / 2 +2), verticalPlace,
((int)rec.getMaxX()+x)-(stringW / 2), verticalPlace);
verticalPlace += 40;
//draw table headers
verticalUnderHeader = verticalPlace;
g2.drawLine(50, verticalPlace, w-50, verticalPlace);
rec = g2.getFontMetrics().getStringBounds(ticArray[0].getTicketNum(), g2);
stringW = (int) rec.getWidth();
rec = g2.getFontMetrics().getStringBounds("Ticket #", g2);
temp = (int) rec.getWidth();
g2.drawString("Ticket #", ((stringW+65+50)/2-(temp/2)), verticalPlace+17);
horzPlace = stringW + 65;
CNCxA = horzPlace;
rec = g2.getFontMetrics().getStringBounds("Customer Name", g2);
stringW = (int) rec.getWidth();
widthCNC = (horzPlace + stringW + 30)-horzPlace;
g2.drawString("Customer Name", horzPlace + 15, verticalPlace+17);
horzPlace = horzPlace + stringW + 30;
CNCxB = horzPlace;
temp = w-horzPlace+30;
DCx = temp;
widthDC = temp - horzPlace;
rec = g2.getFontMetrics().getStringBounds("Description", g2);
stringW = (int) rec.getWidth();
g2.drawString("Description", (horzPlace+temp)/2-(stringW/2), verticalPlace+17);
rec = g2.getFontMetrics().getStringBounds("Status", g2);
stringW = (int) rec.getWidth();
g2.drawString("Status", (temp+(w-50))/2-(stringW/2), verticalPlace+17);
verticalPlace += 20;
g2.drawLine(50, verticalPlace, w-50, verticalPlace);
verticalPlaceTemp = verticalPlace + 20;
}
}

From the sounds of things, the drawTurnoverReport component isn't providing enough size hint information to the scroll pane.
JScrollPane will use the components preferredSize to determine if it needs to display scroll bars or not.
Ensure you are overriding the getPreferredSize method and return an appropriate size of the component.
For example:
Add an Background image to a Panel
Having images as background of JPanel
This assumes that you are performing some kind of custom painting and not using something like JLabel to render the image, which would then suggest you have a layout issue somewhere...but without the source for drawTurnoverReport, it's impossible to know...

Related

GUI elements on different screens with same resolution but different size

I wrote a little Java program for a friend of mine, we have the same resolution ( 1920 * 1080 ), but his Screen in general is smaller than mine. To solve the problem I gave the GUI elements percentual coordinates, which works perfectly until I use fonts. The Font will be the same size, like mine which is like the code expects. The Bounds for a JButton for example says where to start where to end, but a font measured in points, so each inch has 72 points, a Font with 30 will always be half an inch. (Compare to the Images)
How can I fix this, I found nothing that could solve the problem in my eyes?
Image Before:
https://ibb.co/HXf0pt4
Image After:
https://ibb.co/1sbKyts
public class DrawMenu extends JLabel{
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int sw = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int sh = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
g.setFont(new Font("TimesRoman", Font.PLAIN, (int)Math.round(sw * 0.0078)));
g.drawString("Termine die nächsten 0 bis 7 Tage", (int)Math.round(sw * 0.026), (int)Math.round(sh * 0.176));
g.drawString("Termine die nächsten 8 bis 14 Tage", (int)Math.round(sw * 0.182), (int)Math.round(sh * 0.176));
repaint();
}
}
public class Gui {
static JFrame jfCounter, jfMenu, jfTask;
static DrawCounter drawc;
static DrawMenu drawm;
static DrawTask drawt;
static JButton kEnde, kNC, kA, kL, kEsc1, kEsc2, kEsc3, kEsc4, kEsc5, kLG, kLB, kAS, kEnter, kJFsw1, kJFsw2, kJFsw3,
kJFsw4, ko[] = new JButton[6], kSettings, ktw, ktla, ktle, ktlb, ktnt;
static JTextArea taAusgabe, taAusgabedw, taAusgabenw, taze, tabe, tati;
static JFormattedTextField nfTag, nfMonat, nfJahr, nfTagA, nfMonatA, nfJahrA;
static JTextField tfAnlass, tfkLBestimmt, tfAnlassA, tfAnlassAS, tfKonsole, tfKonsoleT, tfsettings[] = new JTextField[12], tftw,
tftis, tftlbs, tftnct, tftnci;
public Gui() {
int sw = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int sh = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
System.out.println(sw + " " + sh);
// JFrame Settings
jfCounter = new JFrame();
jfCounter.setSize(sw, sh);
jfCounter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfCounter.setLocationRelativeTo(null);
jfCounter.setExtendedState(JFrame.MAXIMIZED_BOTH);
jfCounter.setTitle("Tageszähler");
jfMenu = new JFrame();
jfMenu.setSize(sw, sh);
jfMenu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfMenu.setLocationRelativeTo(null);
jfMenu.setExtendedState(JFrame.MAXIMIZED_BOTH);
jfMenu.setTitle("Menü");
jfTask = new JFrame();
jfTask.setSize(sw, sh);
jfTask.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfTask.setLocationRelativeTo(null);
jfTask.setExtendedState(JFrame.MAXIMIZED_BOTH);
jfTask.setTitle("Task");
// JButtons
Border bor = BorderFactory.createLineBorder(Color.BLACK, 1);
Border boresc = BorderFactory.createLineBorder(Color.RED, 3);
kEnde = new JButton("Ende");
kEnde.addActionListener(new ActionHandler());
kEnde.setBounds((int) Math.round(sw * 0.026), (int) Math.round(sh * 0.509), (int) Math.round(sw * 0.195),
(int) Math.round(sh * 0.028));
kEnde.setBorder(bor);
jfCounter.add(kEnde);
kNC = new JButton("Neuer Counter");
kNC.addActionListener(new ActionHandler());
kNC.setBounds((int) Math.round(sw * 0.026), (int) Math.round(sh * 0.028), (int) Math.round(sw * 0.078),
(int) Math.round(sh * 0.028));
kNC.setBorder(bor);
jfCounter.add(kNC);
// JLabel / Draw
drawc = new DrawCounter();
drawc.setBounds(0, 0, sw, sh);
drawc.setVisible(true);
jfCounter.add(drawc);
drawm = new DrawMenu();
drawm.setBounds(0, 0, sw, sh);
drawm.setVisible(true);
jfMenu.add(drawm);
drawt = new DrawTask();
drawt.setBounds(0, 0, sw, sh);
drawt.setVisible(true);
jfTask.add(drawt);
// JFrame Final Visible
Gui.getJfMenu().setVisible(true);
}

how to set high quality of jlabel text

I'm trying write some mechanism to creating mems. After the image is painted with text, the text quality is very low. I dont know what I'm doing wrong. Here is my following draw method:
private BufferedImage generateImage(File file) throws IOException {
Image image = ImageIO.read(file);
final int imgWidth = image.getWidth(null);
final int imgHeight = image.getHeight(null);
int labelHeight = (imgHeight / 2);
int labelWidth = (imgWidth - 25);
int xMargin = ((imgWidth - labelWidth) / 2);
int yMargin = (imgHeight - (labelHeight + 10));
Font font = new Font("Arial Black", Font.BOLD, 42);
String upperText = this.doggle.getUppertext().toUpperCase();
String bottomText = this.doggle.getBottomtext().toUpperCase();
ImagePanel background = new ImagePanel(image);
background.setSize(imgWidth, imgHeight);
ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
String absoluteDiskPath = servletContext.getRealPath("/resources/images/logo.png");
BufferedImage imageLogo = ImageIO.read(new File(absoluteDiskPath));
ImageIcon icon = new ImageIcon(imageLogo);
JLabel imageLogoPanel = new JLabel ();
imageLogoPanel.setIcon(icon);
imageLogoPanel.setSize(imageLogo.getWidth(), imageLogo.getHeight());
imageLogoPanel.setVerticalAlignment(SwingConstants.BOTTOM);
JLabel textUpper = new JLabel();
textUpper.setText(upperText);
textUpper.setVerticalAlignment(SwingConstants.TOP);
textUpper.setSize(labelWidth, labelHeight);
textUpper.setPreferredSize(new Dimension(labelWidth, (imgHeight / 2)));
textUpper.setFont(font);
textUpper.setForeground(Color.decode("#" + this.doggle.getUppercolor()));
JLabel textUpperShadow = new JLabel(upperText, JLabel.CENTER);
textUpperShadow.setVerticalAlignment(SwingConstants.TOP);
textUpperShadow.setSize(labelWidth, labelHeight);
textUpperShadow.setPreferredSize(new Dimension(labelWidth, (imgHeight / 2)));
textUpperShadow.setFont(font);
textUpperShadow.setForeground(Color.BLACK);
JLabel textLower = new JLabel(bottomText, JLabel.CENTER);
textLower.setVerticalAlignment(SwingConstants.BOTTOM);
textLower.setSize(labelWidth, labelHeight);
textLower.setPreferredSize(new Dimension(labelWidth, (imgHeight / 2)));
textLower.setFont(font);
textLower.setForeground(Color.decode("#" + this.doggle.getBottomcolor()));
JLabel textLowerShadow = new JLabel(bottomText, JLabel.CENTER);
textLowerShadow.setVerticalAlignment(SwingConstants.BOTTOM);
textLowerShadow.setSize(labelWidth, labelHeight);
textLowerShadow.setPreferredSize(new Dimension(labelWidth, (imgHeight / 2)));
textLowerShadow.setFont(font);
textLowerShadow.setForeground(Color.BLACK);
background.add(textUpper);
background.add(textUpperShadow);
background.add(textLower);
background.add(textLowerShadow);
background.add(imageLogoPanel);
textUpper.setLocation(xMargin, 5);
textUpperShadow.setLocation((xMargin + 2), 7);
textLower.setLocation(xMargin, yMargin - 16);
textLowerShadow.setLocation((xMargin + 2), ((yMargin - 16) + 2));
imageLogoPanel.setLocation((xMargin - 5), ((yMargin * 2) - 8));
BufferedImage img = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
background.printAll(g2d);
g2d.dispose();
return img;
}
And here is a some part of the image (The text at the top is the actual text and bottom text is what it should look like)
What can I do to improve the visual quality of my text? I Will be grateful for help.

paintComponent problems displaying

I am having a terrible time trying to display the triangles that I am trying to draw. I have looked over the web and and many of the options that I have found I implemented that haven't fixed my display issue. My button panel displays perfectly but my JPanel for drawing either isn't being used or isn't being drawn on. Any help that you guys can give would be great I've been staring for a few days and haven't had any luck. I have more code to implement but I want to get the bare-bones of my code running before I add too much. Here's my code thanks for any help ahead of time.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import javax.swing.*;
public class RotateAndShiftTriangles extends JPanel{
int rWidth, rHeight, centerX, centerY, prevMove = -1, maxX, maxY;
float pixelSize;
double radians;
static Point2D pA, pB, pC;
//Default constructor
RotateAndShiftTriangles(){
rWidth = Integer.parseInt(JOptionPane.showInputDialog("Enter the rWidth of the panel: "));
rHeight = Integer.parseInt(JOptionPane.showInputDialog("Enter the rHeight of the panel: "));
}
// main method of the program that all it really does is call the create method
public static void main(String [] argv){
RotateAndShiftTriangles tri = new RotateAndShiftTriangles();
tri.create();
}
public void create(){
// Initializing graphics
JFrame win = new JFrame();
Dimension d = new Dimension(800, 600);
maxX = d.width - 1;
maxY = d.height - 1;
pixelSize = Math.max(rWidth/maxX, rHeight/maxY);
centerX = maxX/2; centerY = maxY/2;
win.setSize(d);
win.setMinimumSize(d);
win.setPreferredSize(d);
win.getContentPane().setLayout(new BorderLayout());
Point2D centerPoint = new Point2D.Double(centerX, centerY);
JPanel draw = new JPanel();
JPanel buttonPanel = new JPanel();
JButton shiftButton = new JButton("Shift");
JButton rotateButton = new JButton("Rotate");
JButton shiftandRotateButton = new JButton("Shift and Rotate");
JButton resetButton = new JButton("Reset");
JButton backButton = new JButton("Back");
// setting layout
win.add(this);
win.add(draw, BorderLayout.CENTER);
buttonPanel.add(shiftButton);
buttonPanel.add(rotateButton);
buttonPanel.add(shiftandRotateButton);
buttonPanel.add(resetButton);
buttonPanel.add(backButton);
win.add(buttonPanel, BorderLayout.SOUTH);
win.pack();
win.setLocationRelativeTo(win.getParent());
// makes window visible and sets the default closing operations
win.setVisible(true);
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
// Page 19 mappings to take the logical coords and change them to ints.
int iX(float x){
return Math.round(centerX + x/pixelSize);
}
int iY(float y){
return Math.round(centerY - y/pixelSize);
}
// Standard paintComponent method
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.blue);
g.drawRect(0, 0, maxX, maxY);
float side = 0.95F * pixelSize, sideHalf = 0.5F * side,
h = sideHalf * (float)Math.sqrt(3), xA, yA, xB, yB, xC, yC, xA1, yA1, xB1, yB1, xC1, yC1, p, q;
q = 0.05F;
p = 1 - q;
xA = centerX - sideHalf;
yA = centerY - 0.5F * h;
xB = centerX + sideHalf;
yB = yA;
xC = centerX;
yC = centerY + 0.5F * h;
pA.setLocation(xA, yA);
pB.setLocation(xB, yB);
pC.setLocation(xC, yC);
for (int i=0; i<50; i++)
{
g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB));
g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC));
g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA));
xA1 = p * xA + q * xB;
yA1 = p * yA + q * yB;
xB1 = p * xB + q * xC;
yB1 = p * yB + q * yC;
xC1 = p * xC + q * xA;
yC1 = p * yC + q * yA;
xA = xA1; xB = xB1; xC = xC1;
yA = yA1; yB = yB1; yC = yC1;
}
}
}
win.add(this);
win.add(draw, BorderLayout.CENTER);
You add your triangle panel to the window. When you don't specify a constraint it will default to BorderLayout.CENTER.
Then you add the "draw" component, which replaces your panel since only one component can be added to the "CENTER".
Try adding your triangle panel to the BorderLayout.NORTH. However, when you do this you will also need to override the getPreferredSize() method of your triangle panel, otherwise the preferred size will be (0, 0) and there will be nothing to paint.
Read the section from the Swing tutorial on Custom Painting for more information and examples that do this.
Edit:
Taking a second look at your code, I'm not even sure why you created the "draw" panel. You don't add any components to it. So just get rid of the "draw" panel and let your "triangle" panel display in the BordeLayout.CENTER, but you still need to implement the getPreferredSize() method otherwise the pack() method will ignore the "triangle" panel.

How to calculate max fitting font size for Label?

I have a Canvas that contains a Label. I want to set font size of this label according to the Canvas size.
How we can do this?
EDIT: "contains" means, Canvas and Label bounds are same.
EDIT2: I have this for Swing, but I couldn't convert it to SWT;
Font labelFont = label.getFont();
String labelText = label.getText();
int stringWidth = label.getFontMetrics(labelFont).stringWidth(labelText);
int componentWidth = label.getWidth();
double widthRatio = (double)componentWidth / (double)stringWidth;
int newFontSize = (int)(labelFont.getSize() * widthRatio);
int componentHeight = label.getHeight();
int fontSizeToUse = Math.min(newFontSize, componentHeight);
EDIT3:
This is my font size calculator class for label
public class FitFontSize {
public static int Calculate(Label l) {
Point size = l.getSize();
FontData[] fontData = l.getFont().getFontData();
GC gc = new GC(l);
int stringWidth = gc.stringExtent(l.getText()).x;
double widthRatio = (double) size.x / (double) stringWidth;
int newFontSize = (int) (fontData[0].getHeight() * widthRatio);
int componentHeight = size.y;
System.out.println(newFontSize + " " + componentHeight);
return Math.min(newFontSize, componentHeight);
}
}
and this is my Label at the top of the window. I want its font size according the volume of Layer size.
Label l = new Label(shell, SWT.NONE);
l.setText("TITLE HERE");
l.setBounds(0,0,shell.getClientArea().width, (shell.getClientArea().height * 10 )/ 100);
l.setFont(new Font(display, "Tahoma", 16,SWT.BOLD));
l.setFont(new Font(display, "Tahoma", FitFontSize.Calculate(l),SWT.BOLD));
I have just ported the code above.
You can get the extent (length) of a String in SWT with the method GC.stringExtent(); and you need the Class FontData to get the font height and font width of the Label.
Label label = new Label(parent, SWT.BORDER);
label.setSize(50, 30);
label.setText("String");
// Get the label size and the font data
Point size = label.getSize();
FontData[] fontData = label.getFont().getFontData();
GC gc = new GC(label);
int stringWidth = gc.stringExtent(label.getText()).x;
// Note: In original answer was ...size.x + (double)..., must be / not +
double widthRatio = (double) size.x / (double) stringWidth;
int newFontSize = (int) (fontData[0].getHeight() * widthRatio);
int componentHeight = size.y;
int fontsizeToUse = Math.min(newFontSize, componentHeight);
// set the font
fontData[0].setHeight(fontsizeToUse);
label.setFont(new Font(Display.getCurrent(), fontData[0]));
gc.dispose();
Sources:
Stackoverflow: Change just the font size in SWT
Eclipse API: GC

Java (AWT): fitting text in a box

I have an application that extends a Frame. Then, it'll display a few lines of text using:
Font f = new Font("Arial", Font.PLAIN, 10);
g.setFont(f);
g.drawString("Test|great Yes ^.", x, y + 10);
Now what happens is that the text doesn't fit in the box around. E.g. I'm expecting the text to fit in [x,y]-[x+width, y+10] (don't care about the width) but it falls somewhat below the y+10 line. Now for most characters ('T', 'e', etc.) this fits but '|' and 'g' don't! They go below the y+10-line. It seems you can't use: draw at y + characterHeight. But what does work?
To see what I mean, here's some sample code:
import java.awt.*;
public class test extends Frame
{
public test()
{
/* retrieve max window size */
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
GraphicsConfiguration [] gc = gs[0].getConfigurations();
Rectangle r = gc[0].getBounds();
setSize(r.width, r.height);
setVisible(true);
}
public void paint(Graphics g)
{
final int windowWidth = getSize().width;
final int windowHeight = getSize().height;
g.setColor(Color.BLUE);
g.fillRect(0, 0, windowWidth, windowHeight);
g.setColor(Color.WHITE);
g.fillRect(0, 100, windowWidth, 110);
int textHeight = 100;
Font f = new Font("Arial", Font.PLAIN, textHeight);
g.setFont(f);
g.setColor(Color.BLACK);
g.drawString("Test|great Yes ^.", 10, 100 + textHeight);
}
public void guiLoop()
{
for(;;) { try { Thread.sleep(1000); } catch(Exception e) { } }
}
public static void main(String [] args)
{
new test().guiLoop();
}
}
I tried the following code as well:
public void paint(Graphics g)
{
final int windowWidth = getSize().width;
final int windowHeight = getSize().height;
g.setColor(Color.BLUE);
g.fillRect(0, 0, windowWidth, windowHeight);
g.setColor(Color.WHITE);
g.fillRect(0, 100, windowWidth, 110);
int textHeight = 100;
String str = "Test|great Yes ^.";
Font f = new Font("Arial", Font.PLAIN, textHeight);
Rectangle2D boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
f = f.deriveFont((float)(textHeight * (textHeight / boundingRectangle.getHeight())));
boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
g.drawString(str, 10, 100 + (int)boundingRectangle.getHeight());
g.setFont(f);
g.setColor(Color.BLACK);
g.drawString(str, 10, 100 + textHeight);
}
This is somewhat better: the text is smaller so it might fit, but there's still the problem that the y-position is incorrect.
All help is appreciated!
What about using FontMetrics? You can obtain it from Graphics object with g.getFontMetrics().
Than you can retrieve max descent or ascent or directly height (using getHeight), so your implementation will be font-indipendent and it should work fine.. check documentation here!
EDIT (to explain comments):
there is no a direct way to tell to a string to draw itself in a manner that can fit a box. You have to do it by yourself.. like start from a max font size and check if width fits the box, otherwise decrement size and try again. For height you should FIRST decide (or obtain) max font height, then you can set how many pixel should the box be.
I think I solved it somewhat:
boundingBoxHeight: height of box in which the text should fit
yOffset where to start drawing the font
Font f = new Font("Arial", Font.PLAIN, boundingBoxHeight);
g.setFont(f);
FontMetrics fm = g.getFontMetrics();
double shrink = ((double)textHeight / (double)fm.getHeight());
double newSize = (double)textHeight * shrink;
double newAsc = (double)fm.getAscent() * shrink;
int yOffset = (int)newAsc - fm.getLeading();
f = f.deriveFont((float)newSize);
g.setFont(f);
g.drawString(str, 10, 100 + yOffset);
There's quite a bit of whitespace above the text though.

Categories