Reputation: 175
I want to add a gradient background to a JFrame. Within the JFrame, I did not create a JPanel, but rather used the one that is automatically added when the JFrame was created. All the examples I have found online call paintComponent()
on JPanel instances, but as stated, in my case I didn't specifically instantiate one. I know that paintComponent()
needs to be called on a component, and therefore can't be called on the JFrame, so do I need to create and add a JPanel in order to achieve this? I've done it this way with success in the past, but I'm trying to keep my code as streamlines as possible, so I don't want to create a second JPanel if I don't need to. Here's the code I have:
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
JPanel pane;
public Main() {
int WIDTH = 700, HEIGHT = 400;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.GRAY);
setSize(WIDTH, HEIGHT);
setLocationRelativeTo(null);
pane = (JPanel) getContentPane();
pane.setOpaque(false);
pane.setLayout(new BorderLayout());
pane.setBorder(new EmptyBorder(20, 20, 20, 20));
// SOME OTHER STUFF
}
protected void paintComponent(Graphics grphcs) {
Graphics2D g2d = (Graphics2D) grphcs;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0, new Color(255, 195, 225), 0, getHeight(), new Color(139, 207, 236));
g2d.setPaint(gp);
paintComponent(grphcs);
}
}
Any help I can get would be appreciated.
Upvotes: 1
Views: 248
Reputation: 285403
so do I need to create and add a JPanel in order to achieve this?
Yes you do.
but I'm trying to keep my code as streamlines as possible, so I don't want to create a second JPanel if I don't need to.
There's going to be no waste here, since the way to streamline the above code is to get rid of extends JFrame
. There's no need to do this and many reasons not to. You are painting yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
e.g.,
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MainPanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 700;
private static final int PREF_H = 400;
private static final Color GRAD_COLOR_1 = new Color(255, 195, 225);
private static final Color GRAD_COLOR_2 = new Color(139, 207, 236);
public MainPanel() {
setBackground(Color.GRAY);
setSize(WIDTH, HEIGHT);
setLayout(new BorderLayout());
setBorder(new EmptyBorder(20, 20, 20, 20));
// SOME OTHER STUFF
}
// to set the preferred size of the JPanel/GUI
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs); // ** don't forget this.
Graphics2D g2d = (Graphics2D) grphcs;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0, GRAD_COLOR_1, 0, getHeight(), GRAD_COLOR_2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
// create the JFrame when/if needed
JFrame frame = new JFrame("Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
But doesn't it still create unneeded JPanels?
That's worrying about the wrong thing. A single JPanel is created, the contentPane, and this will have no real adverse effect on your program or your use of resources.
My actual class extends JPanel, so when I instantiate that there is one created, plus the default panel which was created when we created the JFrame. Isn't that kind of the same as what I had before, I mean I could have just created a second JPanel and added it to my main class (JFrame) and called paintComponent() on it.
As mentioned above -- don't make mountains out of molehills and don't do premature optimization. If you're worried about abuse of resources in your program, profile it, and then fix problems that have real effects.
What are the advantages of extending JPanel instead of JFrame
I mentioned many of them already -- what about my answer above is confusing specifically?
Upvotes: 3