Im trying to draw a simple rectangle on a frame with some scrollbars and textfields(just testing) but the paintComponent its not showing, ive seen some similar cases here but i cant manage to make it work, any help please?
package appletdeslizadores;
import java.awt.*;
import javax.swing.*;
public class frame extends JPanel {
JFrame f1;
JPanel p1, p2;
JLabel lbl1, lbl2, lbl3;
JTextField txtfld1, txtfld2, txtfld3;
JScrollBar sbar1, sbar2, sbar3;
public frame() {
f1 = new JFrame("Applet ScrollBars");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setSize(380, 350);
f1.setLayout(new FlowLayout());
p1 = new JPanel(new GridLayout(3,3,10,10));
lbl1 = new JLabel("Scroll Bar 1");
lbl2 = new JLabel("Scroll Bar 2");
lbl3 = new JLabel("Scroll Bar 3");
sbar1 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar2 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar3 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
txtfld1 = new JTextField(3);
txtfld1.setText(String.valueOf(sbar1.getValue()));
txtfld1.setEditable(false);
txtfld2 = new JTextField(3);
txtfld2.setText(String.valueOf(sbar2.getValue()));
txtfld2.setEditable(false);
txtfld3 = new JTextField(3);
txtfld3.setText(String.valueOf(sbar3.getValue()));
txtfld3.setEditable(false);
p1.add(lbl1);
p1.add(lbl2);
p1.add(lbl3);
p1.add(sbar1);
p1.add(sbar2);
p1.add(sbar3);
p1.add(txtfld1);
p1.add(txtfld2);
p1.add(txtfld3);
f1.add(p1);
f1.setVisible(true);
}
public void paintComponent(Graphics2D g) {
g.drawRect(50,50,70,100);
g.setColor(Color.red);
}
public static void main(String[] args) {
new frame();
}
}
Problem
You're not sticking to conventions. This is causing problems small mistakes. Your frame class is actually a JPanel, not a JFrame.
There are two main problems: You never added the panel to the frame, and the paintComponent() method has a Graphics object, not a Graphics2D object as a parameter.
The changes to your code are at the bottom of this answer.
Solution
Stick to conventions. (You should also rename your class to a more appropriate name, but that is your choice.) Add the #Override annotation to your paintComponent() method since you wish to override this method from the original JPanel. If it crashes because of the annotation, it means you are not overriding correctly.
Change the paintComponent() parameter from Graphics2D to Graphics.
Add the JPanel to the JFrame.
Make sure you call setPreferredSize() on your JPanel and specify a size.
Call pack() on the JFrame right before making it visible so the layout manager can place everything accordingly.
Now I'm sure by the end of all this you are still not going to be happy with what you see because the code still needs some work, but at least this should give you a boost into the right direction. Also, you may want to call setColor() before drawing the rectangle. ;)
Hope this helped.
Code
public class frame extends JPanel {
JFrame f1;
JPanel p1, p2;
JLabel lbl1, lbl2, lbl3;
JTextField txtfld1, txtfld2, txtfld3;
JScrollBar sbar1, sbar2, sbar3;
public frame() {
f1 = new JFrame("Applet ScrollBars");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setSize(380, 350);
f1.setLayout(new FlowLayout());
p1 = new JPanel(new GridLayout(3,3,10,10));
lbl1 = new JLabel("Scroll Bar 1");
lbl2 = new JLabel("Scroll Bar 2");
lbl3 = new JLabel("Scroll Bar 3");
sbar1 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar2 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar3 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
txtfld1 = new JTextField(3);
txtfld1.setText(String.valueOf(sbar1.getValue()));
txtfld1.setEditable(false);
txtfld2 = new JTextField(3);
txtfld2.setText(String.valueOf(sbar2.getValue()));
txtfld2.setEditable(false);
txtfld3 = new JTextField(3);
txtfld3.setText(String.valueOf(sbar3.getValue()));
txtfld3.setEditable(false);
p1.add(lbl1);
p1.add(lbl2);
p1.add(lbl3);
p1.add(sbar1);
p1.add(sbar2);
p1.add(sbar3);
p1.add(txtfld1);
p1.add(txtfld2);
p1.add(txtfld3);
f1.add(p1);
setPreferredSize(new Dimension(512, 512));
f1.add(this);
f1.pack();
f1.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
g.drawRect(50,50,70,100);
g.setColor(Color.red);
}
public static void main(String[] args) {
new frame();
}
}
Related
I am solving an activity with the following statement: Create an application to display in a JDialog window eight JPanel components. Each panel should be colored in one of the eight colors in figure 1.
Figure 1
On each panel should be written the word that translates the meaning of the color. Use font size 18. Each panel should be colored using a color from Table 1, specifying the amount of each RGB (Red, Green, Blue) component that corresponds to the meaning of the color. Use the java.awt.Color class. Should be implementing just a single paintComponent method to paint the 8 panels and write the meaning of each color.
Table 1
The problem is that my JPanel does not appear in JDialog. And I have no idea how to make it appear.
Follows the code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SigCoresGUI extends JDialog {
private static final long serialVersionUID = 1L;
private Color[] cores = { new Color(255, 255, 255), new Color(249, 206, 137), new Color(255, 128, 0),
new Color(255, 0, 0), new Color(244, 102, 174), new Color(5, 120, 203), new Color(116, 186, 160),
new Color(0, 0, 0) };
private String[] sig = { "Paz", "Energia", "Criatividade", "Paixão", "Ternura", "Tranquilidade", "Harmonia",
"Elegância" };
private Font font = new Font("Arial", Font.BOLD, 18);
public SigCoresGUI() {
super();
Desenha desenha = new Desenha();
add(desenha);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setLocationByPlatform(true);
setLayout(new GridLayout(8, 8));
setSize(400, 500);
setVisible(true);
}
public class Desenha extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public void paintComponents(Graphics g) {
super.paintComponents(g);
for (int i = 0; i < 8; i++) {
JPanel panel = new JPanel();
panel.setBackground(cores[i]);
panel.setFont(font);
JLabel label = new JLabel(sig[i]);
label.setFont(font);
if (i > 0)
label.setForeground(Color.WHITE);
panel.add(label);
add(panel);
}
}
}
}
Never add or remove components from a container (here your JPanel) within a painting method. Painting methods should be for painting and painting only, not for changing the component structure of a container. Understand that you do not have direct control over when or even if a painting method is called, and it can be called many times -- adding many unnecessary components to the container -- and you also never want to slow painting down.
You are overriding paintComponents, a method that (per the API)
Paints each of the components in this container
and since the JPanel has no components to begin with, the method is likely never called.
Instead, add your components in the SigCoresGUI constructor.
Also:
Avoid using setSize(...)
Instead pack() the JDialog before displaying it to let the components and containers size themselves using their preferred sizes.
So this will work although I don't know what layout you're looking for:
import java.awt.*;
import javax.swing.*;
public class SigCoresGUI extends JDialog {
private static final long serialVersionUID = 1L;
private Color[] cores = { new Color(255, 255, 255), new Color(249, 206, 137), new Color(255, 128, 0),
new Color(255, 0, 0), new Color(244, 102, 174), new Color(5, 120, 203), new Color(116, 186, 160),
new Color(0, 0, 0) };
private String[] sig = { "Paz", "Energia", "Criatividade", "Paixão", "Ternura", "Tranquilidade", "Harmonia",
"Elegância" };
private Font font = new Font("Arial", Font.BOLD, 18);
public SigCoresGUI() {
super();
Desenha desenha = new Desenha();
add(desenha);
pack();
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setLocationByPlatform(true);
// setLayout(new GridLayout(8, 8));
// setSize(400, 500);
setVisible(true);
}
public class Desenha extends JPanel {
private static final long serialVersionUID = 1L;
public Desenha() {
setLayout(new GridLayout(0, 1));
for (int i = 0; i < 8; i++) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(cores[i]);
panel.setFont(font);
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JLabel label = new JLabel(sig[i]);
label.setFont(font);
if (i > 0)
label.setForeground(Color.WHITE);
panel.add(label);
add(panel);
}
}
//#Override
//public void paintComponents(Graphics g) {
// super.paintComponents(g);
//}
}
public static void main(String[] args) {
new SigCoresGUI();
}
}
I already looked up this problem and found several threads. Tried all the solutions and none of them helped. I am trying to show a cross where my mouse is placed, the x and the y coordinate of my current mouse position is supposed to be shown in the top left and top right corner. In order to achieve this, I used two JLabels.
Maybe I am overlooking something?
I played around with the standard Text I set in the Labels, positioning, different Layouts for my frame and panel - nothing helps.
The following code should be good enough to get an understanding, I dont think it would be helpful if I left out something.
Fensterkreuz(){
jl1 = new JLabel("0");
jl2 = new JLabel("0");
jl1.setSize(new Dimension(100,100));
jl2.setSize(new Dimension(100,100));
jl1.setFont(new Font ("Arial", Font.PLAIN, 15));
jl2.setFont(new Font ("Arial", Font.PLAIN, 15));
cP = new Point();
this.add(jl1);
this.add(jl2);
addMouseMotionListener(this);
}
public void mouseDragged (MouseEvent e){
}
public void mouseMoved (MouseEvent e) {
cP = e.getPoint();
repaint();
}
public void paint (Graphics g){
g.drawLine((cP.x),(cP.y-15), (cP.x),(cP.y+15));
g.drawLine((cP.x-15),(cP.y), (cP.x+15),(cP.y));
jl1.setText(String.valueOf(cP.x));
jl2.setText(String.valueOf(cP.y));
}
public static void main (String [] args) {
JFrame f = new JFrame();
JComponent test = new Fensterkreuz();
test.setOpaque(false);
f.setVisible(true);
f.setSize(1500,1000);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(test);
}
Put repaint() at the bottom of your main method. Repaint calls the Paint method you have but I think you also have to add your own overriding repaint method to stop “flickering”.
You are overriding the paint() method. So, you need add super.paint(g); as the first line in your overridden paint() method.
To show the 2 labels properly, you need to add this.setLayout(new FlowLayout(FlowLayout.LEFT)); line.
I'm adding the full code with above changes here, so that you can run it and see the results yourself.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Fensterkreuz extends JComponent implements MouseMotionListener {
private JLabel jl1;
private JLabel jl2;
private Point cP;
Fensterkreuz(){
jl1 = new JLabel("0");
jl2 = new JLabel("0");
jl1.setSize(new Dimension(100,100));
jl2.setSize(new Dimension(100,100));
jl1.setFont(new Font ("Arial", Font.PLAIN, 15));
jl2.setFont(new Font ("Arial", Font.PLAIN, 15));
cP = new Point();
//this.setLayout(new FlowLayout(FlowLayout.LEFT));
//this.add(jl1);
//this.add(jl2);
this.setLayout(new GridBagLayout());
this.add(jl1, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
this.add(jl2, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHEAST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
addMouseMotionListener(this);
}
public void mouseDragged (MouseEvent e){
}
public void mouseMoved (MouseEvent e) {
cP = e.getPoint();
repaint();
}
public void paint (Graphics g){
super.paint(g);
g.drawLine((cP.x),(cP.y-15), (cP.x),(cP.y+15));
g.drawLine((cP.x-15),(cP.y), (cP.x+15),(cP.y));
jl1.setText(String.valueOf(cP.x));
jl2.setText(String.valueOf(cP.y));
}
public static void main (String [] args) {
JFrame f = new JFrame();
JComponent test = new Fensterkreuz();
test.setOpaque(false);
f.setVisible(true);
f.setSize(1500,1000);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(test);
}
}
I am just throwing together a quick and dirty GUI to display some data when I ran into an odd issue. The last label I add to the JFrame doesn't want to be positioned or display the border I put on it, so it looks like this:
Here is my code:
public DisplayData (Connection tConn)
{
ID = tID;
conn = tConn;
setupObjects();
setupFrame();
}
private void setupObjects()
{
JLabel caseLabel = new JLabel ("Case #:");
JLabel dateLabel = new JLabel ("Date:");
JLabel reportLabel = new JLabel ("Report:");
JLabel offenceLabel = new JLabel ("Offence:");
JLabel descriptionLabel = new JLabel ("Description:");
this.add(caseLabel);
this.add(dateLabel);
this.add(reportLabel);
this.add(offenceLabel);
this.add(descriptionLabel);
caseLabel.setBounds(50, 50, 130, 25); //x, y, width, height
dateLabel.setBounds(50, 100, 130, 25);
reportLabel.setBounds(50, 150, 130, 25);
offenceLabel.setBounds(50, 200, 130, 25);
descriptionLabel.setBounds(100, 50, 130, 25);
caseLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
dateLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
reportLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
offenceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
descriptionLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
private void setupFrame()
{
this.setTitle("Data Display");
this.setSize (650, 700); //Width, Height
this.setLocation(300, 10);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
}
Yes, I know I should be using a proper layout manager, but like I said i just wanted something quick and dirty. Plus, I will not be beaten by something that should be this simple. Any ideas would be appreciated.
EDIT:
As Compass and Neophyte pointed out, my order of operations was off. Flipped my method calls and all is good again in the world. Thanks for the 2nd pair of eyes.
Contrary to the original poster's strategy, or any of the answers so far, the best approach to this problem is to use layouts.
Here is an example that shows how easy it is to position fields using layouts, and to change the GUI on later updates to the specification.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class CourtDetailsGUI {
private JComponent ui = null;
static final String[] FIELD_NAMES = {
"Case #:",
"Date:",
"Report:",
"Offence:",
"Plaintiff:",
"Defendant:"
};
CourtDetailsGUI(int num) {
initUI(num);
}
public void initUI(int num) {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(getFieldsPanel(num), BorderLayout.PAGE_START);
JTextArea ta = new JTextArea(5, 40);
JScrollPane sp = new JScrollPane(ta);
JPanel p = new JPanel(new GridLayout());
p.add(sp);
p.setBorder(new TitledBorder("Details"));
ui.add(p);
}
private JPanel getFieldsPanel(int num) {
JPanel outerPanel = new JPanel(new FlowLayout());
JPanel innerPanel = new JPanel(new GridLayout(0, 1, 15, 15));
outerPanel.add(innerPanel);
for (int ii=1; ii<num; ii++) {
JLabel l = new JLabel(FIELD_NAMES[ii]);
l.setBorder(new LineBorder(Color.BLACK));
innerPanel.add(l);
}
return outerPanel;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
for (int ii=0; ii<FIELD_NAMES.length; ii++) {
CourtDetailsGUI o = new CourtDetailsGUI(ii+1);
JFrame f = new JFrame("Data " + (ii+1));
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
}
};
SwingUtilities.invokeLater(r);
}
}
Your order of operations is incorrect.
You initially call setupObjects();
This plays your objects out onto a JFrame, which has the default LayoutManager of BorderLayout.
By using the default add(Component comp) method, with BorderLayout, you end up putting the component into null for BorderLayout, which is not supposed to be normal. Furthermore, the reason you can't see the border for this object is because the border is actually the size of the frame. If you explicitly set a region for BorderLayout, then you'll see it work, but setting to no region seems to just break BorderLayout.
Additional add calls appear to free the previous item from the BorderLayout null management, allowing the bounds to take over.
Afterwards, you call setupFrame(); which removes the layout manager, but does not refresh what is currently rendered.
This sets the layout to null, which does nothing to how the frame is displayed, but just removes the layout.
To avoid this issue, call setupFrame(); prior to setupObjects();, and then setVisible(true) can be called at the end of setupObjects();
I'm pretty new to Java, but have been using JPanels, JButtons, JLabels and JTextFields successfully in other parts of my program, but I'm running into trouble when trying to have a JPanel with a couple JButtons, JLabels, and JTextFields inside of it overtop of a painted background.
Here is all of the relevant code for this portion of the program. Currently, when the program runs the only thing that will display is the p1_fireButton, player1PowerField, and player1AngleField overtop of the background (Even though I have the components created for player 2, I purposely commented out adding the p2_Panel so that I could concentrate on p1_Panel.
The weird thing is that those JComponents will only display if I hit the TAB key after the program is running for whatever reason, which I'm also hoping someone could help me fix. My goal will be to have the p1_panel occupy the left orange box and the p2_panel occupy the right orange box. Help would be greatly appreciated!
public class GameFrame extends JFrame
{ //start class GameFrame
ImageIcon background = new ImageIcon("background.jpg");
ImageIcon terrain1 = new ImageIcon("terrain1.png");
//ImageIcon tank_red = new ImageIcon("tank_red.png");
//ImageIcon tank_red = new ImageIcon(player1Tank);
private int x_rectangle = 50;
private int y_rectangle = 50;
private JButton p1_fireButton;
private JButton p2_fireButton;
private JPanel p1_Panel;
private JPanel p2_Panel;
private JLabel player1PowerLabel;
private static JTextField player1PowerField;
private JLabel player1AngleLabel;
private static JTextField player1AngleField;
private JLabel player2PowerLabel;
private static JTextField player2PowerField;
private JLabel player2AngleLabel;
private static JTextField player2AngleField;
String player1Name;
String player2Name;
final Timer gameTimer = new Timer(8, new timer());
Projectile projectile = new Projectile(200, 300);
public GameFrame(String title)
{ //start GameFrame constructor
super(title);
Dimension size = getPreferredSize();
size.width = 1000;
setPreferredSize(size);
setResizable(false);
setLayout(null);
Color trans = new Color(0, 0, 0, 0);
//player1 panel
p1_Panel = new JPanel();
p1_Panel.setLayout(null);
p1_Panel.setBounds(0, 0, 500, 300);
p1_Panel.setBackground(trans);
p2_Panel = new JPanel();
p2_Panel.setLayout(null);
p2_Panel.setBounds(500, 0, 500, 300);
p2_Panel.setBackground(trans);
//player2 panel
/*p2_fireButtonPanel = new JPanel();
p2_fireButtonPanel.setBounds(400, 85, 100, 100);
p2_fireButtonPanel.setBackground(trans);*/
//player1 angle/power fields
player1PowerLabel = new JLabel("Power");
player1PowerLabel.setLayout(null);
player1PowerLabel.setBounds(400, 20, 50, 50);
player1PowerField = new JTextField(3);
player1PowerField.setLayout(null);
player1PowerField.setBounds(400, 10, 50, 25);
player1AngleLabel = new JLabel("Angle");
player1AngleLabel.setLayout(null);
player1AngleLabel.setBounds(30, 10, 50, 50);
player1AngleField = new JTextField(3);
player1AngleField.setLayout(null);
player1AngleField.setBounds(300, 10, 50, 25);
//player2 angle/power fields
player2PowerLabel = new JLabel("Power");
player2PowerLabel.setLayout(null);
player2PowerLabel.setBounds(0, 0, 10, 10);
player2PowerField = new JTextField(3);
player2PowerField.setLayout(null);
player2PowerField.setBounds(10, 10, 10, 10);
player2AngleLabel = new JLabel("Angle");
player2AngleLabel.setLayout(null);
player2AngleLabel.setBounds(30, 10, 10, 10);
player2AngleField = new JTextField(3);
player2AngleField.setLayout(null);
player2AngleField.setBounds(60, 10, 10, 10);
//player1 fire button
p1_fireButton = new JButton("Fire!");
p1_fireButton.setLayout(null);
p1_fireButton.setBounds(430, 70, 50, 50);
ActionListener fireListener = new fireButtonListener();
p1_fireButton.addActionListener(fireListener);
//player2 fire button
p2_fireButton = new JButton("Fire AGAIN!");
p2_fireButton.setLayout(null);
p2_fireButton.setBounds(530, 70, 50, 50);
//add components to player1 panel
p1_Panel.add(p1_fireButton);
p1_Panel.add(player1PowerLabel);
p1_Panel.add(player1PowerField);
p1_Panel.add(player1AngleLabel);
p1_Panel.add(player1AngleField);
//add components to player2 panel
p2_Panel.add(p2_fireButton);
p2_Panel.add(player2PowerLabel);
p2_Panel.add(player2PowerField);
p2_Panel.add(player2AngleLabel);
p2_Panel.add(player2AngleField);
//add components to GameFrame
add(p1_Panel);
//add(p2_Panel);
projectile.fireProjectile(60, -60 * Math.PI / 180.0);
} //end GameFrame constructor
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Image bg = background.getImage();
Image t1 = terrain1.getImage();
Image p1tank = StartPanel.getPlayer1Tank();
Image p2tank = StartPanel.getPlayer2Tank();
//Image tank1 = tank_red.getImage();
g2.drawImage(bg, 0, 0, 1000, 800, this);
g2.drawImage(t1, 0, 420, 1000, 380, this);
g2.drawImage(p1tank, 50, 300, 66, 50, null);
g2.drawImage(p2tank, 500, 300, 66, 50, null);
player1Name = new String(StartPanel.getPlayer1Name());
player2Name = new String(StartPanel.getPlayer2Name());
g.drawString(player1Name, 50, 50);
g.drawString(player2Name, 525, 50);
g2.setColor(Color.green);
g2.fillOval((int)projectile.getXPosition(), (int)projectile.getYPosition(), 15, 15);
}
public class timer implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//TanksGUI.gameFrame.moveRectangle(1, 1);
projectile.advanceProjectile(0.05);
if (projectile.getYPosition() > 400)
{
gameTimer.stop();
}
repaint();
}
}
public class fireButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
gameTimer.start();
}
}
} //end class GameFrame
Check out BackgroundPanel to help you with this. The basic code would be:
JPanel north = new JPanel();
north.add( new JLabel(...) );
north.add( new JTextField(10) );
JPanel gamePanel = new GamePanel();
BackgroundPanel background = new BackgroundPanel(...);
background.add(north, BorderLayout.North);
background.add(gamePanel);
frame.add(background);
The GamePanel is the panel where you do all the custom painting for your game characters. As noted by MadProgrammer, this painting should never be done in the paint() method of the frame.
Don't extend from JFrame you're not adding any functionality to it that creating an instance couldn't achieve. It also makes you're project unportable.
Don't override paint of top level containers. If for no other reason they are not double buffered, which will cause you problems if you want to perform animation. The paint chain for a top level container is rather complex and you've just circumvent the whole process.
Instead, create a custom component (from something like JPanel) and use it as you primary canvas. Override it's paintComponent method and render your background to it, making sure you call super.paintComponent first.
Make sure that any containers you are placing on this "canvas" are transparent, otherwise your background won't show up.
Have a look at Performing Custom Painting and Painting in AWT and Swing for more information
Well the title is quite self explanatory. I want to build two panels one on-top of each other in layers using java. I want the top layer to contain a JPanel which will contain a graphics2d object. I'd like both the JPanel and graphics2d to have transparent background (I still want the content drawn by the graphics2d visible). Does anyone have an idea how it can be done?
Call setOpaque(false) on the JPanel - that will not paint the JPanel's background.
Depending on what method you're overriding to get at the Graphics2D (JPanel's don't contain a Graphics2D object like a component - a Graphics2D object is used to paint the JPanel) - if it's paintComponent() you should read the JavaDocs for JComponent - and call super.paintComponent(g) first so that opacity is honored - and then do the rest of your painting.
Working example:
package com.stackoverflow.opaque;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class OpaqueExample extends JFrame {
private JLayeredPane layers;
private JPanel up, down;
private JButton toggleOpaque;
public OpaqueExample() {
layers = new JLayeredPane();
down = new JPanel();
down.setBackground(Color.GREEN);
down.setBounds(100, 100, 200, 200);
layers.add(down, new Integer(1));
up = new JPanel() {
public void paintComponent(Graphics og) {
super.paintComponent(og);
Graphics2D g = (Graphics2D)og;
GradientPaint gradient = new GradientPaint(0, 0, Color.BLUE, 10, 0,
Color.WHITE, true );
Polygon poly = new Polygon();
poly.addPoint(10, 10);
poly.addPoint(100, 50);
poly.addPoint(190, 10);
poly.addPoint(150, 100);
poly.addPoint(190, 190);
poly.addPoint(100, 150);
poly.addPoint(10, 190);
poly.addPoint(50, 100);
poly.addPoint(10, 10);
g.setPaint(gradient);
g.fill(poly);
g.setPaint(Color.BLACK);
g.draw(poly);
}
};
up.setBackground(Color.RED);
up.setBounds(150, 150, 200, 200);
layers.add(up, new Integer(2));
getContentPane().add(layers, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
toggleOpaque = new JButton("Toggle Opaque");
toggleOpaque.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
up.setOpaque(!up.isOpaque());
layers.repaint();
}
});
buttonPanel.add(toggleOpaque);
getContentPane().add(buttonPanel, BorderLayout.EAST);
}
public static void main(String[] args) {
JFrame f = new OpaqueExample();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}