Why shouldn't you extend JFrame and other components?
Generally speaking, extending the component tends to be done strictly to use the component. This severely limits your options in unnecessary ways in terms of design, so that your classes can't extend different classes, you can't hide the JFrame's methods causing it to be more difficult to maintain and easier to trigger unexpected bugs when using the class.
Typically the intention is strictly to use the class to draw a frame, and composition is preferred over inheritance.
That being said, subclassing should be fine when you intend your subclass to add project-specific functionality to the Frame (such as convenience methods and the like) where the subclass would be used instead of the Frame itself, but used as a frame in general, not as a view of a specific frame in the application.
Extends JFrame vs. creating it inside the program
Thoughts:
- Avoid extending JFrame as it ties your GUI to being, well a JFrame. If instead you concentrate on creating JPanels instead, then you have the freedom to use these JPanels anywhere needed -- in a JFrame, or JDialog, or JApplet, or inside of another JPanel, or swapped with other JPanels via a CardLayout.
- Avoid inheritance in general, especially of complex classes. This will prevent pernicious errors, such as inadvertent method overrides (try creating a JFrame or JPanel that has a
getX()
andgetY()
method to see what I mean!). - Avoid inheritance of complex classes if you are using an IDE: If you override a complex class, when you call methods on objects of these classes, you will have many, too many, choices of methods offered to you.
- Encapsulation is good, is and allows for creation of safer code. Expose only that which needs to be exposed, and control that exposure as much as possible.
Extending from JFrame
It makes no difference unless you have another class called JFrame
and are importing it instead of javax.swing.JFrame
.
That said, as Andrew Thompson said, you shouldn't extend JFrame
, you should use an instance.
how to extend JFrame in a class that already extends Thread
Instead of extending either JFrame or Thread, use composition, it is a lot less limiting:
public class MyApplication {
JFrame applicationFrame;
Thread someThread;
MyApplication() {
SwingUtilities.invokeLater(new Runnable() {
@Override void run() {
applicationFrame = new JFrame();
// some more GUI initialization.
applicationFrame.setVisible(true);
}
});
someThread = new Thread(new Runnable() {
@Override void run() {
// do my work.
}
});
someThread.start();
}
public static void main(String... args) {
new MyApplication();
}
}
Rescale a drawing in Java (JFrame)
There are bascially two different approaches for this:
- You can "scale the whole
Graphics
" - You can scale the actual shapes
The difference may be subtle in some cases, but can be important: When you scale the whole Graphics
, then everything will be scaled. Particularly, when you scale it about 2.0
, and then draw a line with a width of 1.0
, the line will be drawn 2 pixels wide. Whether or not this is desired depends on the application case.
In order to scale the actual shapes, you can not use the drawRect
method. Instead you will have to create Shape
instances that represent the geometric shapes. You can then create scaled versions of these shapes with AffineTransform#createTransformedShape
.
Here is an example that compares both approaches (and corrects some of the other issues that have been in your code). In both cases, the same rectangle with an original size of (10,13) is painted, scaled by a factor of 5.0.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ScalingDrawnObjects
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ScalingDrawnObjectsPanel p = new ScalingDrawnObjectsPanel();
f.getContentPane().add(p);
f.setSize(600,400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class ScalingDrawnObjectsPanel extends JPanel
{
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
Shape rectangle = new Rectangle2D.Double(2, 2, 10, 13);
g.setColor(Color.RED);
drawWithScaledGraphics(g, rectangle);
g.translate(100, 0);
drawScaledObject(g, rectangle);
}
private static void drawWithScaledGraphics(Graphics2D g, Shape shape)
{
AffineTransform oldAt = g.getTransform();
g.scale(5.0, 5.0);
g.draw(shape);
g.setTransform(oldAt);
}
private static void drawScaledObject(Graphics2D g, Shape shape)
{
AffineTransform at = AffineTransform.getScaleInstance(5.0, 5.0);
g.draw(at.createTransformedShape(shape));
}
}
EDIT In response to the comment
The code that I posted is not "complicated". It is as compilcated as it has to be, but not more. You should not extend JFrame
and you should not override paint
. You should create the GUI on the EDT. You should ...
However, you should not use code like the following, but maybe this is what you're looking for
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.Dimension;
public class Stretch extends JFrame {
int originalHeight = 600;
int originalWidth = 600;
public Stretch() {
super("Stretch");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(originalWidth, originalHeight);
}
public static void main(String[] args) {
Stretch s = new Stretch();
s.setVisible(true);
}
public void paint(Graphics g) {
Dimension size = this.getBounds().getSize();
int rectWidth = 100;
int rectHeight = 130;
g.setColor(Color.white);
g.fillRect(0, 0, size.width, size.height);
g.setColor(Color.black);
int w = rectWidth + size.width - originalWidth;
int h = rectHeight + size.height - originalHeight;
double sx = (double)w / rectWidth;
double sy = (double)h / rectHeight;
double s = Math.min(sx, sy);
int fw = (int)(s * rectWidth);
int fh = (int)(s * rectHeight);
g.drawRect(100, 100, fw, fh);
}
}
Related Topics
How to Obtain Mouse Click Coordinates Outside My Window in Java
Selenium Switch Focus to Tab, Which Opened After Clicking Link
Cast Double to Integer in Java
Open a Link in Browser with Java Button
Missing Artifact Com.Sun:Tools:Jar
What's the Difference Between Spring Data's Mongotemplate and Mongorepository
Java: Method to Get Position of a Match in a String
Java.Util.Date Format Ssssss: If Not Microseconds What Are the Last 3 Digits
How to Setsize of Image Using Rescaleop
Declaring an Unsigned Int in Java
Convert an Integer to an Array of Digits
Instanceof - Incompatible Conditional Operand Types
How to Configure Jackson in Wildfly
In Java, When Should I Create a Checked Exception, and When Should It Be a Runtime Exception