I'm new to Java and I'm playing around with a simple GUI example. After having received a good answer to my last question, I tried to take it one step further and to scale the shape with the frame size (with fixed aspect ratio). Indeed, when I change the window size, the shape scales with it. However, the shape never fills the frame to a maximum, there is always quite a lot of space at the right and bottom margins. Here's the code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class DrawTest2 {
class DrawingPanel extends JPanel {
private Rectangle2D shape;
private JFrame frame;
public DrawingPanel(Rectangle2D shape, JFrame frame) {
this.shape = shape;
this.frame = frame;
}
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
double scaleFactor = calcScaleFactor();
AffineTransform oldAt = g2D.getTransform();
AffineTransform tx1 = new AffineTransform();
tx1.scale(scaleFactor, scaleFactor);
super.paintComponent(g2D);
g2D.setTransform(tx1);
g2D.transform(AffineTransform.getTranslateInstance(3, 3));
g2D.setColor(new Color(31, 21, 1));
g2D.fill(shape);
g2D.draw(shape);
g2D.setTransform(oldAt);
}
@Override
public Dimension getPreferredSize() {
Dimension dimension = new Dimension((int)shape.getWidth(), (int)shape.getHeight());
System.out.println("Dimension: " + dimension); // 2000 x 500
return dimension;
}
private double calcScaleFactor() {
double maxX = shape.getMaxX();
double maxY = shape.getMaxY();
double widthPanel = frame.getContentPane().getSize().getWidth();
double heightPanel = frame.getContentPane().getSize().getHeight();
double minFactor;
if (widthPanel < maxX || heightPanel < maxY) {
double factorX = widthPanel/maxX;
double factorY = heightPanel/maxY;
minFactor = factorX < factorY ? factorX : factorY;
} else {
minFactor = 1.0;
}
System.out.println("widthPanel: " + widthPanel); // 1283
System.out.println("heightPanel: " + heightPanel); // 500
System.out.println("widthFrame: " + frame.getSize().getWidth()); // 1297
System.out.println("heightFrame: " + frame.getSize().getHeight()); // 537
System.out.println("maxX: " + maxX); // 2000
System.out.println("maxY: " + maxY); // 500
System.out.println("minFactor:" + minFactor); // 0.6415
return minFactor;
}
}
public void draw() {
JFrame frame = new JFrame();
Rectangle2D shape = new Rectangle2D.Float();
shape.setRect(0, 0, 2000, 500);
final DrawingPanel drawing = new DrawingPanel(shape, frame);
frame.getContentPane().add(drawing, BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
public class DrawMain {
public static void main(String[] args) {
DrawTest2 test = new DrawTest2();
test.draw();
}
}
The scaling factor seems to be ok (2000 * 0.6415 = 1283). My guess is that although the calculation itself is right, I apply the scaling factor at the wrong place. Any help with this will be appreciated.
EDIT: Here is a screenshot of the window that I get to make the problem clearer:
EDIT2: Here is the updated code (slightly renamed):
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class DrawTest2 {
class DrawingPanel extends JPanel {
private Rectangle2D shape;
public DrawingPanel(Rectangle2D shape) {
this.shape = shape;
}
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
double scaleFactor = calcScaleFactor();
AffineTransform oldAt = g2D.getTransform();
AffineTransform tx1 = new AffineTransform();
tx1.scale(scaleFactor, scaleFactor);
super.paintComponent(g2D);
g2D.setTransform(tx1);
g2D.setColor(new Color(31, 21, 1));
g2D.fill(shape);
g2D.draw(shape);
g2D.setTransform(oldAt);
}
@Override
public Dimension getPreferredSize() {
Dimension dimension = new Dimension((int)shape.getWidth(), (int)shape.getHeight());
return dimension;
}
private double calcScaleFactor() {
double maxX = shape.getMaxX();
double maxY = shape.getMaxY();
double widthPanel = getWidth();
double heightPanel = getHeight();
double minFactor;
double factorX = widthPanel/maxX;
double factorY = heightPanel/maxY;
minFactor = factorX < factorY ? factorX : factorY;
return minFactor;
}
}
public void draw() {
JFrame frame = new JFrame();
Rectangle2D shape = new Rectangle2D.Float();
shape.setRect(0, 0, 800, 500);
final DrawingPanel drawing = new DrawingPanel(shape);
frame.getContentPane().add(drawing, BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
DrawTest2 test = new DrawTest2();
test.draw();
}
}
This is what the result looks like with shape.setRect(0, 0, 2000, 500)
:
This is what the result looks like with shape.setRect(0, 0, 800, 500)
:
If I replace return minFactor
by return 1.0
(and stay with shape.setRect(0, 0, 2000, 500)
), I get this result:
If I replace return minFactor
by return 0.9
(and stay with shape.setRect(0, 0, 2000, 500)
), I get this result:
If I replace return minFactor
by return 0.9
and change to shape.setRect(0, 0, 3000, 500)
, I get the same visible result as with return 1.0
and shape.setRect(0, 0, 2000, 500)
.