How do I get my components on top of my painted JFrame? - java

i've gone about setting the background Image of my JFrame but now my components are (I assume) stuck behind it. I've tried reading about top level containers but I just can't get my head around it T_T. Any one have any ideas ? Maybe I need to find another way to set the background image ? Thank you for any help. :
#SuppressWarnings("serial")
public class CopyOfMainMenu extends JFrame {
//Running the GUI
public static void main(String[] args) throws IOException {
CopyOfMainMenu gui2 = new CopyOfMainMenu();
gui2.mainPanel();
}
public void thepanel () throws IOException {
// GridBagLayout/Constraint
GridBagConstraints gridbagc = new GridBagConstraints();
gbc.insets = new Insets(15, 15, 15, 15);
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridBagLayout());
// Creating JButtons/Icons
panel.add(buttonTwo, gbc); //SCOREBOARD
panel.add(buttonThree, gbc); //INSTRUCTIONS
// JButton size's
button.setPreferredSize(new Dimension(400, 35))
buttonTwo.setContentAreaFilled(false);
buttonThree.setBorder(BorderFactory.createEmptyBorder());
buttonThree.setContentAreaFilled(false);
}
}
Again, thanks in advance for any help.

You never add the panel anywhere (if you did, it would paint over the image). However, it's possible to use a JLabel as the container:
JComponent panel = new JLabel(new ImageIcon(ImageIO.read(new File("res/FinalBG.png"))));
panel.setLayout(new GridBagLayout());
...
// continue adding the components as before
...
frame.add(panel);
(or set the label as the content pane, which works just as well).

Inside the JFrame, override the paint method and draw your image using the Graphics object:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, width, height, null);
}

Related

Adding Canvas on JPanel on JFrame

I hope the title wasn´t too confusing.
First off, I am still a beginner, I only started learning java a few months ago and didn´t start working with graphic components until a few weeks ago. Here is my problem:
I got a JFrame as a container and then a Canvas "canvas" to store BufferedImages and JPanel "bPanel" to hold three JButtons. For some reason, even though I used bPanel.setOpaque(false) and/or bPanel.setBackground(new Color(0, 0, 0, 0) the JPanel would still block the Canvas, no matter which one I add first and which one I add second, no matter if I add the Canvas onto the JFrame or the JPanel.
I looked around the internet for hours and tried at least 5 different solutions that did not work. For some reason, I can´t get loading images through a JPanel to work, probably because my display class is not extending anything.
Anyway, let´s continue:
Here is the code I have (yes I know I could go for Display extends JFrame but that doesn´t solve the problem, I already tried that).
public class Display {
private Game game;
private JFrame frame;
private Canvas canvas;
private JPanel bPanel;
private String title;
private int width, height;
private JButton stand, draw, reset;
private Icon drawIMG, standIMG, resetIMG;
private int bwidth, bheight;
public Display(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
createDisplay();
}
private void createDisplay() {
frame = new JFrame(title);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
canvas = new Canvas();
canvas.setPreferredSize(new Dimension(width, height));
canvas.setMaximumSize(new Dimension(width, height));
canvas.setMinimumSize(new Dimension(width, height));
canvas.setFocusable(false);
bPanel = new JPanel();
bPanel.setSize(width, height);
bPanel.setPreferredSize(new Dimension(width, height));
//bPanel.setOpaque(false);
bPanel.setBackground(new Color(0, 0, 0, 0));
bPanel.setLayout(null);
drawIMG = new ImageIcon(this.getClass().getResource("/textures/button_draw.png"));
standIMG = new ImageIcon(this.getClass().getResource("/textures/button_stand.png"));
resetIMG = new ImageIcon(this.getClass().getResource("/textures/button_reset.png"));
draw = new JButton(drawIMG);
stand = new JButton(standIMG);
reset = new JButton(resetIMG);
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent drawClicked) {
if (game.getPhase() == 1)
game.playerDraw();
}
});
stand.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent standClicked) {
if (game.getPhase() == 1)
{
game.setPhase(2);
removeButtons();
}
}
});
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent resetClicked) {
game.reset();
}
});
bwidth = 300;
bheight = 100;
//bPanel.add(new JLabel(new ImageIcon(getClass().getResource("/textures/background.png"))), BorderLayout.CENTER);
addButton(draw);
addButton(stand);
addButton(reset);
draw.setBounds(100, ((height/2)-(bheight/2)), bwidth, bheight);
stand.setBounds(((width-100)-bwidth), ((height/2)-(bheight/2)), bwidth, bheight);
reset.setBounds(((width/2)-40), (height-120), 80, 80);
frame.add(canvas);
frame.add(bPanel);
frame.pack();
}
public void showImage(String path) {
JLabel jl = new JLabel();
jl.setIcon(new javax.swing.ImageIcon(getClass().getResource(path)));
frame.add(jl);
frame.repaint();
}
public void setGame(Game game) {
this.game = game;
}
public void addButton(JButton button) {
bPanel.add(button);
bPanel.setLayout(null);
}
public void showButtons() {
draw.setVisible(true);
stand.setVisible(true);
}
public void removeButtons() {
draw.setVisible(false);
stand.setVisible(false);
}
public void removePanel(JPanel panel) {
frame.remove(panel);
}
public Canvas getCanvas() {
return canvas;
}
public JFrame getFrame() {
return frame;
}
public JPanel getBPanel() {
return bPanel;
}
}
In this try of mine for example the picture was only displayed after the JButton "stand" was pressed:
public void showImage(String path) {
JLabel jl = new JLabel();
jl.setIcon(new javax.swing.ImageIcon(getClass().getResource(path)));
frame.add(jl);
frame.repaint();
}
I am pretty desperate bc I spent many hours trying to figure out a solution to load graphics in.
Thanks for help in advance :D
Several issues:
Don't use a null layout. Swing was designed to be using with layout managers.
The default layout manager for a JFrame is a BorderLayout. If you don't specify a constraint, the component is added to the CENTER. Only one component can be displayed in the CENTER. So you can't just keep adding components to the frame. You need to have a parent/child hierarchy.
Don't use a Canvas. That is an AWT component. If you want to do custom painting in Swing you can use the JPanel
So your code might be something like:
//addButton(draw);
//addButton(stand);
//addButton(reset);
bPanel(draw);
bPanel(stand);
bPanel(reset);
The default layout manager for a JPanel is a FlowLayout. So the buttons will be added from left to right and centered on the panel.
//frame.add(bPanel);
frame.add(bPanel, BorderLayout.PAGE_START);
Now all the buttons will be added at the top of the frame.
//private Canvas canvas;
private JPanel canvas;
….
//canvas = new Canvas();
canvas = new JPanel(new BorderLayout());
…
//frame.add(canvas);
frame.add(canvas, BorderLayout.CENTER);
Now the "canvas" will be added to the CENTER of the BorderLayout of the frame, which means it will take up all the space not used by the button panel.
public void showImage(String path) {
JLabel jl = new JLabel();
jl.setIcon(new javax.swing.ImageIcon(getClass().getResource(path)));
frame.add(jl);
frame.repaint();
}
You can't add the image directly to the frame because you have already added other components to the frame. Instead use:
//frame.add(jl);
//frame.repaint();
canvas.add(jl);
canvas.repaint();
So the image is added to the canvas which is added to the frame so you have a parent/child hierarchy.
//draw.setBounds(100, ((height/2)-(bheight/2)), bwidth, bheight);
//stand.setBounds(((width-100)-bwidth), ((height/2)-(bheight/2)), bwidth, bheight);
//reset.setBounds(((width/2)-40), (height-120), 80, 80);
Above code is not needed, since it is the job of the layout manager to set the size and location of each component based on the rules of the layout manager.
So basically you need to start over and learn some Swing basics. Maybe the Swing tutorial will help. There are demos of how to use each of the layout managers.

Buttons are set to be left-aligned but are still displayed as centered

I'm trying to create an interface with Swing.
This is my code:
public class JavaApplication30
{
public static void main(String[] args) throws IOException
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));
frame.setPreferredSize(new Dimension(1280, 720));
frame.setResizable(false);
frame.setContentPane(new JPanel()
{
BufferedImage image = ImageIO.read(new File("C:\\Users\\user\\Documents\\NetBeansProjects\\JavaApplication29\\src\\eila.jpg"));
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, 1280, 720, this);
}
});
JPanel a = new JPanel();
a.setAlignmentX(Component.LEFT_ALIGNMENT);
a.setPreferredSize(new Dimension(150, 500));
a.setMaximumSize(new Dimension(150, 500));
a.setOpaque(false);
a.add(Box.createRigidArea(new Dimension(5,50)));
JButton amico = new JButton("Amico");
a.add(amico);
a.add(Box.createRigidArea(new Dimension(5,20)));
amico.setPreferredSize(new Dimension(150, 50));
JButton bello = new JButton("Bello");
a.add(bello);
a.add(Box.createRigidArea(new Dimension(5,20)));
bello.setPreferredSize(new Dimension(150, 50));
JButton compagno = new JButton("Compagno");
a.add(compagno);
compagno.setPreferredSize(new Dimension(150, 50));
frame.getContentPane().add(a);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class ImagePanel extends JComponent {
private Image image;
public ImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
I set the button alignment to the left, but my buttons are still centered.
This didn't happen without paintComponent for the background.
Why is this? How can I align the buttons on the left?
I set Alignment to left, but my buttons are centered
The setAlignmentX(...) is only a hint for how the "panel" should be aligned in its parent panel. When you add the buttons to the panel, what matters is the layout manager of the panel.
By default a JPanel uses a FlowLayout. Also by default when you create a FlowLayout, the components added to the panel are centered aligned in the space of the panel.
Change the layout manager to be a FlowLayout with the components left aligned. Read the FlowLayout API for the proper constructor to use.
Also, you can provide a default gap between the buttons, so there is no need for the Box.createRigidArea(...). The component is really meant to be used when you use a BoxLayout.

JPanel won't move if it fills the screen

First of all, sorry for the vague title I don't know how to word the question in a sentence.
I have a simple programme that slides one JPanel into view as another gets pushed out, when a button is clicked.
If the first JPanel's width is set as getWidth() then the JPanel will not move when the button is clicked, however if I change the width to getWidth() - 1 it works perfectly fine!?!
A simple example is shown below
public class SlidingJPanel extends JFrame{
public JPanel panel = new JPanel();
public JPanel panel2 = new JPanel();
public JLabel label = new JLabel(" SUCCESS!!!!!!!");
public JButton button = new JButton("TESTING");
public class MyJPanel extends JPanel implements ActionListener{
public int x = 0;
public int delay = 70;
final Timer timer = new Timer(delay,this);
public MyJPanel(){};
public void paintComponent(Graphics g)
{
super.paintComponent(g);
button.setBounds(10, 20, 100, 50);
button.addActionListener(this);
panel.setBorder(BorderFactory.createLineBorder(Color.black));
panel.setBounds(x, 0, getWidth(), getHeight());
panel.add(button);
panel2.setBorder(BorderFactory.createLineBorder(Color.blue));
panel2.setBounds(x - getWidth(), 0, getWidth(), getHeight());
panel2.add(label);
add(panel);
add(panel2);
}
#Override
public void actionPerformed(ActionEvent arg0) {
timer.addActionListener(move);
timer.start();
}
ActionListener move = new ActionListener(){
public void actionPerformed(ActionEvent e){
repaint();
x++;
}
};
}
public static void main(String args [])
{
new SlidingJPanel();
}
SlidingJPanel()
{
Container container = getContentPane();
MyJPanel panel = new MyJPanel();
container.add(panel);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500,500);
setTitle("JPanel Draw Rect Animation");
setVisible(true);
}
}
ignore any coding conventions I may have ignored or missed this is just a rough draft.
Hope someone can help :)
The paintComponent() method is for painting only! There is no need for you to override this method.
You should NOT be:
updating the property of components (ie. bounds, border)
adding components to a container
If you want to animate a component then when the timer fires you can use setLocation(...) or setSize() or setBounds(). The component will automatically be repainted.
I don't know if fixing this will solve your problem, but the current approach is wrong.

Adding a JPanel to a JLayeredPane causes paints and resizes to have no effect

I am trying to add a JPanel (well, several) to a JLayeredPane. However, when I do so, the paint component method of the JPanel seems to have no effect. An example is included below:
import javax.swing.*;
import java.awt.*;
public class Example {
public static void main(String[] args) {
// This Works as expected
JFrame usingPanel = new JFrame();
JPanel p = new JPanel();
p.add(new BluePanel());
usingPanel.setContentPane(p);
usingPanel.pack();
usingPanel.setVisible(true);
// This makes the frame but does not paint the BluePanel
JFrame usingLayer = new JFrame();
JLayeredPane l = new JLayeredPane();
l.setPreferredSize(new Dimension(200,200));
l.add(new BluePanel(), JLayeredPane.DEFAULT_LAYER);
JPanel p2 = new JPanel();
p2.add(l);
usingLayer.setContentPane(p2);
usingLayer.pack();
usingLayer.setVisible(true);
}
static class BluePanel extends JPanel{
public BluePanel(){
setPreferredSize(new Dimension(200,200));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 200, 200);
}
}
}
Why is this? and what are the possible solutions?
JLayeredPane does not have a LayoutManager, so you need to set the location and size of your panels yourself.
See the tutorial
you hardcoded the size on the screen and have to change from
g.fillRect(0, 0, 200, 200);
to
g.fillRect(0, 0, getWidth(), getHeight());
(a minor change) add the method
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
and then remove of code line setPreferredSize(new Dimension(200,200));

Java painting graphics in JApplet issues

I hope this does not appear too much of a newbie question. I've not done graphical style programming before. My objective is to create a pinball advergame in an applet. However, I'm falling at one of the first hurdles. My applet is not displaying the results of the paintComponent method from my Table class (which extends the JPanel). I've tried several things, such as how I load the image (currently using double buffering but I did use a mediatracker before), seeing if not having any other GUI stuff would allow the painting to occur (since I wondered if it was being drawn underneath somehow) and other things. This problem has stumped me and I'm starting to wonder (and hope) if it's something small that I've overlooked, if it is, then I'm sorry but would still be grateful for help, as I can't go very far without this problem being fixed first. My code for my Pinball (applet) and Table class are below, the other classes aren't implemented yet. Once again, I appreciate any help.
import javax.swing.*; // useful for the drawing side, also going to be a JApplet
import java.awt.*;
import java.net.*;
public class Pinball extends JApplet {
// variables go here
Table table;
// further initialisation of the GUI
public void init() {
setSize(300, 300);
table = new Table(this);
add(table);
setContentPane(table); // makes our graphical JPanel container the content pane for the Applet
// createGUI(); // this has been moved onto the table class
}
public void stop() {
}
}
And now the Table class:
import java.awt.*; // needed for old style graphics stuff
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*; // gives us swing stuff
import java.io.IOException;
import java.net.*; // useful for anything using URLs
public class Table extends JPanel {
// attributes go here
Pinball pb;
Color bgColour;
JPanel eastPanel;
JPanel logoPanel;
JPanel livesPanel;
JPanel scorePanel;
JPanel tablePanel;
JPanel scrollTextPanel;
Image logo;
// constructor goes here
public Table(Pinball pb) {
setPreferredSize(new Dimension(300, 300));
this.pb = pb;
// this is not needed anymore, with the new loadImage class down the bottom
// Toolkit tk = Toolkit.getDefaultToolkit(); // needed to get images
// logo = tk.getImage(base + "images/logo.jpg");
logo = loadImage("logo.jpg");
createGUI();
}
// public methods go here
// all GUI creation stuff goes here
public void createGUI() {
/* allows the three parts (top, middle and right)
* to be made through (north, center and right) */
setLayout(new BorderLayout());
// setting the background colour
bgColour = new Color(190, 186, 221); // makes the sky blue colour for the background.
setBackground(bgColour);
// now putting a panel for the east side
eastPanel = new JPanel();
eastPanel.setBackground(bgColour);
eastPanel.setLayout(new BorderLayout(8, 8));
eastPanel.setPreferredSize(new Dimension(100, 280));
logoPanel = new JPanel();
logoPanel.setBackground(Color.WHITE);
logoPanel.setPreferredSize(new Dimension(100, 100));
logoPanel.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.white));
//JLabel label1 = new JLabel("Logos go here");
//logoPanel.add(label1);
eastPanel.add(logoPanel, "North");
livesPanel = new JPanel();
livesPanel.setBackground(Color.WHITE);
livesPanel.setPreferredSize(new Dimension(100, 100));
JLabel label2 = new JLabel("Lives go here");
livesPanel.add(label2);
eastPanel.add(livesPanel, "Center");
scorePanel = new JPanel();
scorePanel.setBackground(Color.WHITE);
scorePanel.setPreferredSize(new Dimension(100, 80));
JLabel label3 = new JLabel("Scores go here");
scorePanel.add(label3);
eastPanel.add(scorePanel, "South");
add(eastPanel, "East");
tablePanel = new JPanel();
tablePanel.setBackground(bgColour);
tablePanel.setPreferredSize(new Dimension(200, 280));
add(tablePanel, "Center");
scrollTextPanel = new JPanel();
scrollTextPanel.setPreferredSize(new Dimension(300, 20));
scrollTextPanel.setBackground(Color.WHITE);
scrollTextPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(scrollTextPanel, "North");
// repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(logo, 5, 5, 90, 90, null);
g.drawLine(0, 0, 300, 300); // for testing, does not work
}
// a little useful method for handling loading of images and stuff
public BufferedImage loadImage(String filename) {
BufferedImage image = null;
try {
URL url = new URL(pb.getCodeBase(), "images/" + filename);
image = ImageIO.read(url);
} catch (IOException e) {
}
return image;
}
}
Your Table JPanel is covered by other JPanels, which can be OK, but you won't be able to see through an opaque component that is covering it, in particular the tablePanel JPanel. For example, try:
tablePanel = new JPanel();
// tablePanel.setBackground(bgColour); //!! removed
tablePanel.setOpaque(false); //!! added
And see what happens.
An unrelated question for you regarding this code here:
public void init() {
setSize(300, 300);
table = new Table(this);
add(table);
setContentPane(table); // makes our graphical JPanel container the content
Why are you adding the table Table object twice, once to the JApplet's contentPane and then next as the JApplet's contentPane?
Run then examine this code & see if you can spot the source of the problem.
// <applet code='Pinball' width='300' height='300'></applet>
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*; // useful for the drawing side, also going to be a JApplet
import javax.imageio.ImageIO;
import java.net.*;
import java.io.IOException;
public class Pinball extends JApplet {
// variables go here
Table table;
// further initialisation of the GUI
public void init() {
table = new Table(this);
setContentPane(table); // makes our graphical JPanel container the content pane for the Applet
}
}
class Table extends JPanel {
// attributes go here
Pinball pb;
Color bgColour;
JPanel eastPanel;
JPanel logoPanel;
JPanel livesPanel;
JPanel scorePanel;
JPanel tablePanel;
JPanel scrollTextPanel;
Image logo;
// constructor goes here
public Table(Pinball pb) {
//setPreferredSize(new Dimension(300, 300));
this.pb = pb;
// this is not needed anymore, with the new loadImage class down the bottom
//Toolkit tk = Toolkit.getDefaultToolkit(); // needed to get images
//logo = tk.getImage(base + "images/logo.jpg");
int size = 100;
logo = //loadImage("logo.jpg");
new BufferedImage( size,size, BufferedImage.TYPE_INT_RGB);
Graphics g = logo.getGraphics();
g.setColor(Color.red);
g.fillRect(0,0,size,size);
createGUI();
}
// public methods go here
// all GUI creation stuff goes here
public void createGUI() {
/* allows the three parts (top, middle and right)
* to be made through (north, center and right) */
setLayout(new BorderLayout(20,20));
// setting the background colour
bgColour = new Color(190, 186, 221); // makes the sky blue colour for the background.
setBackground(bgColour);
// now putting a panel for the east side
eastPanel = new JPanel();
eastPanel.setBackground(bgColour);
eastPanel.setLayout(new BorderLayout(8, 8));
eastPanel.setPreferredSize(new Dimension(100, 280));
logoPanel = new JPanel();
logoPanel.setBackground(Color.WHITE);
logoPanel.setPreferredSize(new Dimension(100, 100));
logoPanel.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.green));
eastPanel.add(logoPanel, "North");
livesPanel = new JPanel();
livesPanel.setBackground(Color.WHITE);
livesPanel.setPreferredSize(new Dimension(100, 100));
JLabel label2 = new JLabel("Lives go here");
livesPanel.add(label2);
eastPanel.add(livesPanel, "Center");
scorePanel = new JPanel();
scorePanel.setBackground(Color.WHITE);
scorePanel.setPreferredSize(new Dimension(100, 80));
JLabel label3 = new JLabel("Scores go here");
scorePanel.add(label3);
eastPanel.add(scorePanel, "South");
add(eastPanel, "East");
tablePanel = new JPanel();
tablePanel.setBackground(bgColour);
tablePanel.setPreferredSize(new Dimension(200, 280));
add(tablePanel, "Center");
scrollTextPanel = new JPanel();
scrollTextPanel.setPreferredSize(new Dimension(300, 20));
scrollTextPanel.setBackground(Color.WHITE);
scrollTextPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(scrollTextPanel, "North");
}
#Override
public void paintComponent(Graphics g) {
System.out.println("paintComponent");
super.paintComponent(g);
g.setColor(Color.black);
g.drawImage(logo, 5, 5, 90, 90, this);
g.drawLine(0, 0, 300, 300); // for testing, does not work
}
// a little useful method for handling loading of images and stuff
public BufferedImage loadImage(String filename) {
BufferedImage image = null;
try {
URL url = new URL(pb.getCodeBase(), "images/" + filename);
image = ImageIO.read(url);
} catch (IOException e) {
// do NOT ignore exceptions in broken code.
}
return image;
}
}

Categories

Resources