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;
}
}
Related
I'm trying to create a canvas for my oval shape, and I want it to be different from the main JFrame color. So far, using setSize upon the panel doesn't work, it ended up creating a small box that I couldn't draw in. Here is the panel design that I intended it to be, with the white-colored part as the main frame.
PanelDesign
As I've said, using all three Layout modes (Border, Flow, and Grid) only creates a yellow small box in the upper middle part of the frame. This is the code that I use.
How can I create the panel design similar to the image posted above?
setTitle("Oval Shape Mover");
setSize(500, 200);
setLayout(new BorderLayout());
JPanel mainpanel, panel1, panel2;
mainpanel = new JPanel();
panel1 = new JPanel();
panel2 = new JPanel();
panel1.setBackground(Color.YELLOW);
mainpanel.add(panel1, BorderLayout.CENTER);
mainpanel.add(panel2);
add(mainpanel);
setVisible(true);
The layouts used to make Java Swing GUIs will more often honor the preferred size than the size. Having said that, a custom rendered component should override (rather than set) getPreferredSize().
This example suggests a preferred size by using a JLabel to display the icon, and empty borders to pad the GUI out.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.net.*;
public class RedDotLayout {
private JComponent ui = null;
String urlToRedCircle = "https://i.stack.imgur.com/wCF8S.png";
RedDotLayout() {
try {
initUI();
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
public final void initUI() throws MalformedURLException {
ui = new JPanel(new BorderLayout());
ui.setBackground(Color.YELLOW);
ui.setBorder(new LineBorder(Color.BLACK, 2));
JLabel label = new JLabel(new ImageIcon(new URL(urlToRedCircle)));
label.setBorder(new CompoundBorder(
new LineBorder(Color.GREEN.darker(), 2),
new EmptyBorder(20, 200, 20, 200)));
ui.add(label, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel();
bottomPanel.setBackground(Color.WHITE);
bottomPanel.setBorder(new EmptyBorder(30, 50, 30, 50));
ui.add(bottomPanel, BorderLayout.PAGE_END);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
RedDotLayout o = new RedDotLayout();
JFrame f = new JFrame(o.getClass().getSimpleName());
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);
}
}
I want to make a background image for a game I'm designing but I cant figure out the right way to get the effect I want, I want a background that can be seen behind text etc. basically having the background cover the whole JFrame / JPanel not just one section of the layout (e.g. BorderLayout.Center) I think it does this anyway but if it does do that how do I make the background for those transparent to see the background which is behind...
Confusing i know but I hope someone here understands what I am trying to do and can help... this is my current code. I have been playing around with the background so dont read to much in how i have written it.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
public class GamePanel extends JPanel {
private JTextPane playertext;
private JTextField wealthstring, currentwealth;
public GamePanel() {
super();
setLayout(new BorderLayout());
setBackground(Game.getBackgroundColor());
Border raised = BorderFactory.createRaisedBevelBorder();
Border lowered = BorderFactory.createLoweredBevelBorder();
setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(4, 4, 4, 4), (BorderFactory.createCompoundBorder(raised, lowered))));
add(northpanel(), BorderLayout.NORTH);
add(eastpanel(), BorderLayout.EAST);
}
private JLabel northpanel() {
Font northfont = new Font("Engravers MT", Font.BOLD, 12);
ImageIcon banner = new ImageIcon("images/banner.png", "North Background");
playertext = new JTextPane();
playertext.setFont(northfont);
playertext.setEditable(false);
playertext.setText("Player: \n" + Game.getName());
playertext.setBackground(Game.getBackgroundColor());
playertext.setBorder(new EmptyBorder(10,10,10,10));
wealthstring = new JTextField("Money: ");
wealthstring.setFont(northfont);
wealthstring.setEditable(false);
wealthstring.setHorizontalAlignment(wealthstring.RIGHT);
wealthstring.setBorder(null);
wealthstring.setBackground(Game.getBackgroundColor());
currentwealth = new JTextField();
currentwealth.setFont(northfont);
currentwealth.setEditable(false);
currentwealth.setHorizontalAlignment(wealthstring.RIGHT);
currentwealth.setBackground(Game.getBackgroundColor());
currentwealth.setBorder(null);
String wealthrounded = String.format("%.2f", Game.getMoney());
currentwealth.setText(wealthrounded);
JPanel wealthtext = new JPanel();
wealthtext.setLayout(new GridLayout(2, 1));
wealthtext.setBackground(Game.getBackgroundColor());
wealthtext.setBorder(new EmptyBorder(10,10,10,10));
wealthtext.add(wealthstring);
wealthtext.add(currentwealth);
JLabel northpanel = new JLabel();
northpanel.setLayout(new BorderLayout());
northpanel.setIcon(banner);
northpanel.add(new JSeparator(), BorderLayout.PAGE_END);
northpanel.add(playertext, BorderLayout.WEST);
northpanel.add(wealthtext, BorderLayout.EAST);
return northpanel;
}
private JPanel eastpanel() {
JButton tab1 = new JButton("Tab 1");
JButton tab2 = new JButton("Tab 2");
JButton tab3 = new JButton("Tab 3");
JPanel easttabs = new JPanel();
easttabs.setLayout(new GridLayout(1, 3));
easttabs.add(tab1);
easttabs.add(tab2);
easttabs.add(tab3);
JPanel eastpanels = new JPanel();
eastpanels.setLayout(new BorderLayout());
eastpanels.setBackground(Game.getBackgroundColor());
eastpanels.add(easttabs, BorderLayout.NORTH);
return eastpanels;
}
}
So if you already have a JPanel that has your image as Background and you want to add another panel over it with your components you can use Opacity to achieve this. Only the components added to this panel will be visible. Here's the code :
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class TransparentPane extends JPanel {
public TransparentPane() {
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0f));
g2d.setColor(getBackground());
g2d.fill(getBounds());
g2d.dispose();
}
}
Create a class that extends from JPanel and in its paint method draw an image over it.
Now create a class the extends from JFrame and in its constructor set its contentpane to the object of that JPanel class like below. Now you can add components to jframe.
class SimpleTest extends JFrame {
JButton btn = new JButton("A Game");
public SimpleTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new CPane());
getContentPane().setBackground(Color.red);
getContentPane().add(btn, BorderLayout.NORTH);
setSize(new Dimension(300, 300));
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SimpleTest();
}
});
}
}
class CPane extends JPanel {
Image back;
public void paintComponent(Graphics g) {
super.paintComponent(g);
try {
back = ImageIO.read(getClass().getResource("back.jpg"));
} catch (Exception ex) {
}
g.drawImage(back, 0, 0, this);
}
}
If you want to make a jpanel transparent then do
panel.setOpaque(false);
I'm trying to add three rectangles to the center of BorderLayout and I'm completely lost. My finished program needs to increase the height of the rectangle as the sliders move but I'm trying to figure out how to intitally draw these three rectangles to the jpanel. I'm so lost. My code is below.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ShowColors extends JPanel
{
public static void main(String args[])
{
JFrame frame = new JFrame();
JPanel main = new JPanel(new BorderLayout());
main.setSize(2000, 1000);
frame.setContentPane(main);
JPanel jp1 = new JPanel(new GridLayout(0, 1));
JPanel jp2 = new JPanel(new GridLayout(2,3));
JPanel jp3 = new JPanel(new GridLayout(1, 3));
jp1.setPreferredSize(new Dimension(90, 800));
jp2.setPreferredSize(new Dimension(1000, 150));
jp3.setPreferredSize(new Dimension(800, 600));
JRadioButton rb1 = new JRadioButton("Decimal", true);
JRadioButton rb2 = new JRadioButton("Binary");
JRadioButton rb3 = new JRadioButton("Hex");
JRadioButton rb4 = new JRadioButton("Octal");
JButton jb1 = new JButton("RESET");
ButtonGroup group = new ButtonGroup();
group.add(rb1);
group.add(rb2);
group.add(rb3);
group.add(rb4);
JSlider jRed = new JSlider(0,255);
JSlider jGreen = new JSlider(0,255);
JSlider jBlue = new JSlider(0,255);
jRed.setPaintLabels(true);
jRed.setPaintTicks(true);
jRed.setMinorTickSpacing(5);
jRed.setMajorTickSpacing(50);
jRed.setValue(0);
jGreen.setPaintLabels(true);
jGreen.setPaintTicks(true);
jGreen.setMinorTickSpacing(5);
jGreen.setMajorTickSpacing(50);
jGreen.setValue(0);
jBlue.setPaintLabels(true);
jBlue.setPaintTicks(true);
jBlue.setMinorTickSpacing(5);
jBlue.setMajorTickSpacing(50);
jBlue.setValue(0);
JLabel labelR = new JLabel("Red", JLabel.CENTER);
JLabel labelG = new JLabel("Green", JLabel.CENTER);
JLabel lableB = new JLabel("Blue", JLabel.CENTER);
jp1.add(rb1);
jp1.add(rb2);
jp1.add(rb3);
jp1.add(rb4);
jp1.add(jb1);
jp2.add(labelR);
jp2.add(labelG);
jp2.add(lableB);
jp2.add(jRed);
jp2.add(jGreen);
jp2.add(jBlue);
main.add(jp1, BorderLayout.WEST);
main.add(jp2, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g)
{
super.paint(g);
g.drawRect(0, 0, 10, 20);
g.setColor(Color.RED);
g.fillRect(0, 0, 10, 20);
g.drawRect(10, 0, 10, 20);
g.setColor(Color.GREEN);
g.fillRect(10, 0, 10, 20);
g.drawRect(20, 0, 10, 20);
g.setColor(Color.BLUE);
g.fillRect(20, 0, 10, 20);
}
}
here is my layout and i want the rectangles in the center.
I think you just need a simple subclass of JPanel and override paintComponent(). Something like this should get you going:
import javax.swing.*;
import java.awt.*;
public class Canvas extends JPanel {
// TODO member variables for rectangle size/color
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(10,10,100,50);
g.drawRect(10,80,100,50);
}
}
EDIT:
Actually, I guess you really don't need a "Canvas" class, you can just use a plain JPanel as #MadProgrammer suggests. What you do need is a class that will encapsulate the Rectangle behavior, which can just be a simple JComponent that gets added to the JPanel that holds your three rectangles.
Here's a working solution, imports excluded for brevity:
public class ShowColors {
class Rectangle extends JComponent implements ChangeListener {
private JSlider slider;
private Color color;
public Rectangle(JSlider slider, Color color) {
this.slider = slider;
this.color = color;
this.setPreferredSize(new Dimension(250, 250));
slider.addChangeListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int value = slider.getValue();
g.setColor(color);
g.fillRect(10,10,100,value);
}
#Override
public void stateChanged(ChangeEvent arg0) {
this.repaint();
}
}
public ShowColors() {
JFrame frame = new JFrame();
JPanel main = new JPanel(new BorderLayout());
main.setSize(2000, 1000);
frame.setContentPane(main);
JPanel jp1 = new JPanel(new GridLayout(0, 1));
JPanel jp2 = new JPanel(new GridLayout(2, 3));
jp1.setPreferredSize(new Dimension(90, 800));
jp2.setPreferredSize(new Dimension(1000, 150));
JRadioButton rb1 = new JRadioButton("Decimal", true);
JRadioButton rb2 = new JRadioButton("Binary");
JRadioButton rb3 = new JRadioButton("Hex");
JRadioButton rb4 = new JRadioButton("Octal");
JButton jb1 = new JButton("RESET");
ButtonGroup group = new ButtonGroup();
group.add(rb1);
group.add(rb2);
group.add(rb3);
group.add(rb4);
JSlider jRed = buildSlider();
JSlider jGreen = buildSlider();
JSlider jBlue = buildSlider();
JLabel labelR = new JLabel("Red", JLabel.CENTER);
JLabel labelG = new JLabel("Green", JLabel.CENTER);
JLabel lableB = new JLabel("Blue", JLabel.CENTER);
jp1.add(rb1);
jp1.add(rb2);
jp1.add(rb3);
jp1.add(rb4);
jp1.add(jb1);
jp2.add(labelR);
jp2.add(labelG);
jp2.add(lableB);
jp2.add(jRed);
jp2.add(jGreen);
jp2.add(jBlue);
JPanel canvas = new JPanel();
canvas.setLayout(new FlowLayout());
canvas.setPreferredSize(new Dimension(800, 600));
canvas.add(new Rectangle(jRed, Color.RED));
canvas.add(new Rectangle(jGreen, Color.GREEN));
canvas.add(new Rectangle(jBlue, Color.BLUE));
main.add(jp1, BorderLayout.WEST);
main.add(jp2, BorderLayout.SOUTH);
main.add(canvas, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static JSlider buildSlider() {
JSlider slider = new JSlider(0, 255);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(50);
slider.setValue(50);
return slider;
}
public static void main(String args[]) {
new ShowColors();
}
}
And here's what it looks like:
Don't override paint, painting in Swing is achieved by a delicate and complicated chain of methods, which is easily broken. Instead, override it's paintComponent method instead. See Painting in AWT and Swing for more details
Having said that, don't add all your components to the same panel onto which you want to draw, you'll end up painting underneth all the components. Instead, create a separate JPanel which acts as the paint surface and another JPanel which acts as the controller (containing the controls and the paint surface). Use setters and getters to change the state of the paint surface. See Performing Custom Painting for more details.
Create some kind of "drawable" object, which knows how to paint itself and what it should use to paint itself (the color)
Create some kind of List (in the paint surface class) which can hold the objects which you want to paint. Within in it's paintComponent you will will loop through the list and request that each object paint itself, passing it the Graphics context. Take a look at 2D Graphics for more details
This previous answer may also help
I'm creating a slideshow using swing and trying to place it in the center of my JFrame. The slideshow works fine, but it's taking up the entire center section. How would I limit it to a small place under the banner?
Here's a picture of what it looks like.
Here's a picture of what I want it to look like
This is what I have so far, you run this class.
package com.RBV2.engine;
import javax.swing.*;
import com.RBV2.Settings;
import com.RBV2.panels.News;
import com.RBV2.panels.SlideShow;
import com.RBV2.panels.SlideShow.MovingPanel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
/*
* Author Jon & David
*
*/
#SuppressWarnings("serial")
public class Client extends JFrame implements ActionListener {
private JPanel bottomPanel, news;
private JButton launch;
private JLabel loading, banner;
private MovingPanel slideshow;
protected boolean updated = false;
private void createLayout() {
createPanel();
addPanel();
setVisible(true);
}
private void createPanel() {
bottomPanel = new JPanel(new BorderLayout());
news = new News();
slideshow = new SlideShow.MovingPanel();
launch = new JButton(new URL("http://www.runerebellion.com/clientImages/launch.png"));
loading = new JLabel(new URL("http://www.runerebellion.com/clientImages/loader.gif"));
banner = new JLabel(new URL("http://www.runerebellion.com/clientImages/201457.gif"));
launch.addActionListener(this);
}
private void addPanel() {
setTitle("RuneRebellionV2 Launcher");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
//Bottom Panel
add(bottomPanel, BorderLayout.SOUTH);
bottomPanel.add(new JLabel(" Launcher, release " + Settings.version), BorderLayout.WEST);
bottomPanel.setBackground(Color.BLACK);
bottomPanel.add(launch, BorderLayout.EAST);
launch.setPreferredSize(new Dimension(120, 40));
//News Feed
add(news, BorderLayout.CENTER);
news.add(banner, BorderLayout.CENTER);
banner.setPreferredSize(new Dimension(500, 70));
//slideshow
slideshow.setPreferredSize(new Dimension(610, 331));
add(slideshow, BorderLayout.CENTER);
//Sets size
setSize(Settings.width, Settings.height);
}
public Client() throws IOException {
createLayout();
}
public static void main(String args[]) throws IOException {
final Client l = new Client();
l.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
l.setVisible(true);
}
});
}
These specific lines of code call the slideshow(I commented out exactly where)
private void addPanel() {
setTitle("RuneRebellionV2 Launcher");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
//Bottom Panel
add(bottomPanel, BorderLayout.SOUTH);
bottomPanel.add(new JLabel(" Launcher, release " + Settings.version), BorderLayout.WEST);
bottomPanel.setBackground(Color.BLACK);
bottomPanel.add(launch, BorderLayout.EAST);
launch.setPreferredSize(new Dimension(120, 40));
//News Feed
add(news, BorderLayout.CENTER);
news.add(banner, BorderLayout.CENTER);
banner.setPreferredSize(new Dimension(500, 70));
//slideshow here
slideshow.setPreferredSize(new Dimension(610, 331));
add(slideshow, BorderLayout.CENTER);
//Sets size
setSize(Settings.width, Settings.height);
}
Here is my slideshow class, you may need this also.
package com.RBV2.panels;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class SlideShow extends JFrame {
public static class MovingPanel extends JPanel {
public int i = 0;
public MovingPanel() {
Timer timer = new Timer(3000, new TimerListener());
timer.start();
}
protected void paintComponent(Graphics x) {
super.paintComponent(x);
int y = i % 25;
Image showImg = new ImageIcon("bin/slide/" + y + ".png").getImage();
x.drawImage(showImg, 0, 0, getWidth(), getHeight(), 0, 0, 610, 331, null);
}
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
i++;
repaint();
if (i >= 5)
i = 1;
}
}
}
}
So my question is how would I limit the slideshow to be in a box in the very center under the banner.
Have a look at this picture (from Border layout Tutorial)
As you are only adding panels to the Center and South(PAGE_END) regions of the layout manager there is no other components to stop the center panel from stretching out as far as it can.
Note this relevant sentence of the tutorial
If the window is enlarged, the center area gets as much of the available space as possible. The other areas expand only as much as necessary to fill all available space. Often a container uses only one or two of the areas of the BorderLayout object — just the center, or the center and the bottom.
You either need to add blank panels on the other sides or make use of an empty border within your Center panel. See here about how to use borders.
I painted the background, then painted the images over the background
protected void paintComponent(Graphics x) {
super.paintComponent(x);
int y = i % 25;
Image showImg = new ImageIcon("bin/slide/" + y + ".png").getImage();
super.paintComponent(x);
x.drawImage((Settings.background).getImage(), 0, 0, getWidth(), getHeight(), this);
x.drawImage(showImg, 360, 260, getWidth(), getHeight(), 0, 0, 110, 31, null);
}
I'm working with JFrames in Java, specifically with absolutely positioned elements that need to overlap. I understand that to overlay components, one should make a JPanel (with setOpacity(false);), and position it with either setBounds(x,y,x2,y2); or setPosition(x,y) & setSize(x,y). Unfortunately the panels act like CSS's inline-divs; they take up only the needed amount of room on their line, and do not stack.
This is the code I have so far, but it doesn't seem to act like I'd imagine it would:
class Login extends JFrame {
private JPanel backgroundpanel;
private JPanel panel;
private JPanel panel2;
private JTextField usernameBox;
private JPasswordField passwordBox;
private JButton button;
private int height = 319;
private int width = 452;
private ImageIcon ii = new ImageIcon("special-window-BG.png");
private JLabel image;
public Login() {
setLayout(null);
setTitle("Login");
setSize(width,height);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
buildPanel();
add(backgroundpanel);
setVisible(true);
}
private void buildPanel() {
usernameBox = new JTextField(20);
passwordBox = new JPasswordField(20);
button = new JButton("Login");
image = new JLabel(ii);
backgroundpanel = new JPanel();
panel = new JPanel();
panel2 = new JPanel();
backgroundpanel.add(panel);
backgroundpanel.add(panel2);
backgroundpanel.add(image);
panel.setBackground(Color.red);
panel.setBounds(0, 0, 10, 10);
panel.setOpaque(false);
panel2.setBackground(Color.blue);
panel2.setBounds(0, 0, 10, 10);
panel2.setOpaque(false);
panel.add(passwordBox);
panel2.add(button);
backgroundpanel.setOpaque(false);
backgroundpanel.isOptimizedDrawingEnabled();
backgroundpanel.setBounds(0, 0, width, height);
...cot'd, however unnecessary.
So basically, I'd like to know how to absolutely position JPanels (or JComponents, if that's simpler) over a JPanel with a background-image.
Thanks for taking a look at this question, I've spent far too much time on this method; the commented-out code extends nearly 500 lines passed what I posted, so I have nowhere else to turn to. The image below shows a crude illustration of what I'm trying to accomplish, I'm not sure if I'actually come close to getting it yet, because sometimes the JComponents seem to disappear as if they're behind the background image, however I'd like to find the simple solution that's most likely right in front of my eyes!
http://i.stack.imgur.com/revz8.jpg
I'd like to find the simple solution that's most likely right in front of my eyes!
Something like this?
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class LoginPanel extends JPanel {
private static final long serialVersionUID = 1L;
BufferedImage image;
LoginPanel(BufferedImage image) {
super(new GridBagLayout());
this.image = image;
JPanel controls = new JPanel(new BorderLayout(15,35));
controls.setOpaque(false);
controls.setBorder(new EmptyBorder(110,0,0,0));
JPanel fields = new JPanel(new GridLayout(0,1,30,30));
fields.setOpaque(false);
controls.add(fields, BorderLayout.CENTER);
fields.add(new JTextField(20));
fields.add(new JPasswordField(20));
JPanel button = new JPanel(new GridBagLayout());
button.setOpaque(false);
controls.add(button, BorderLayout.PAGE_END);
button.add(new JButton("Log In"));
Dimension prefSize = new Dimension(image.getWidth(),image.getHeight());
setPreferredSize(prefSize);
add(controls);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
public static void main(String[] args) throws Exception {
URL url = new URL("http://i.stack.imgur.com/revz8.jpg");
final BufferedImage image = ImageIO.read(url);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
LoginPanel p = new LoginPanel(image);
JOptionPane.showMessageDialog(null, p);
}
});
}
}
You're setting setLayout(null) on your JFrame but not on the "backgroundpanel" (which layout is default set to FlowLayout).
You shouldn't set layout of your Login frame - because it is default set to BorderLayout - and it's ok (you want the "backgroundpanel" to grow to match the parent).
Instead setLayout(null) on your JPanel - "backgroundpanel" - to which you add your arbitrary positioned panels.