I got a project where I always want to center the focused JPanel. So I thought I can just change the Viewport position. But I can't use the viewport. I created an example project to show how I use the viewport. I just want that the user only see one of the orange boxes. But it should be also possible to view all boxes at once. So the view has to zoom in or something like this. How can I fix this problem?
My example:
import javax.swing.*;
import java.awt.*;
public class main {
public static void main(String [] args){
//create JFrame
JFrame _frame = new JFrame();
//create Viewport
JViewport _view = new JViewport();
//create Mainpanel
JPanel _mainPanel = new JPanel();
//tell the view to handle mainpanel
_view.setView(_mainPanel);
//create Layout
GridLayout _layout = new GridLayout(3,3,3,3);
//set gridlayout to mainpanel
_mainPanel.setLayout(_layout);
for(int i = 0;i<12;i++){
JPanel _tempPanel = new JPanel();
_tempPanel.setBackground(Color.ORANGE);
_tempPanel.setBorder(BorderFactory.createLineBorder(Color.black));
_mainPanel.add(_tempPanel);
}
_view.setExtentSize(new Dimension(300,300));
//add mainpanel to frame
_frame.add(_mainPanel);
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
_frame.pack();
//set size of Jframe
_frame.setSize(1000,1000);
_frame.setVisible(true);
}
}
JViewPort can not help you with your requirement.
Here is an ugly but running code. You can improve it yourself.
public static void main(String[] args) {
// create JFrame
JFrame _frame = new JFrame();
JPanel conPanel = new JPanel(new BorderLayout());
// create Mainpanel
JPanel _mainPanel = new JPanel() {
#Override
public String toString() {
return "All";
}
};
// create Layout
GridLayout _layout = new GridLayout(3, 3, 3, 3);
// set gridlayout to mainpanel
_mainPanel.setLayout(_layout);
JComboBox<JPanel> combo = new JComboBox<>();
combo.addItem(_mainPanel);
for (int i = 0; i < 12; i++) {
final int fi = i;
JPanel _tempPanel = new JPanel() {
#Override
public String toString() {
return "Panel" + fi;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString(toString(), 5, 15);
}
};
_tempPanel.setBackground(Color.ORANGE);
_tempPanel.setBorder(BorderFactory.createLineBorder(Color.black));
_mainPanel.add(_tempPanel);
combo.addItem(_tempPanel);
}
combo.addActionListener( e -> {
JPanel panel = (JPanel)combo.getSelectedItem();
conPanel.remove(_mainPanel);
_mainPanel.removeAll();
for(int i = 1; i < combo.getItemCount(); i++)
_mainPanel.add(combo.getItemAt(i));
conPanel.add(panel, BorderLayout.CENTER);
conPanel.revalidate();
conPanel.repaint();
} );
conPanel.add(_mainPanel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonsPanel.add(combo);
conPanel.add(buttonsPanel, BorderLayout.SOUTH);
// add mainpanel to frame
_frame.setContentPane(conPanel);
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// set size of Jframe
_frame.setSize(1000, 1000);
_frame.setVisible(true);
}
Related
I'm trying to create a program that lists movies in a Netflix style to learn Front-End coding.
How I want it to look in the end:
My guess is that every movie is a button component with an image a name label and a release year label.
I'm struggling to recreate this look. This is how it looks when I try it:
The navigationbar in my image is at the page start of a border layout. Below the navigationbar the movie container is in the center of the border layout.
My idea was creating a GridLayout and then create a button for each movie and adding it to the GridLayout.
You can recreate this with this code:
public class Main {
private static JFrame frame;
public static void main(String[] args) throws HeadlessException {
frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setBackground(new Color(32, 32, 32));
JPanel navigationPanel = createNavigationBar();
frame.add(navigationPanel, BorderLayout.PAGE_START);
JPanel moviePanel = createMoviePanel();
frame.add(moviePanel, BorderLayout.CENTER);
frame.setPreferredSize(new Dimension(1920, 1080));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Example App");
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static JPanel createMoviePanel() {
JPanel moviePanel = new JPanel();
GridLayout layout = new GridLayout(0, 10);
layout.setHgap(3);
layout.setVgap(3);
moviePanel.setLayout(layout);
moviePanel.setBackground(new Color(32, 32, 32));
ArrayList<String> exampleList = new ArrayList<>();
// Add stuff to the example list
for(int i = 0; i < 120; i++) {
exampleList.add(Integer.toString(i));
}
final File root = new File("");
for(final String movie : exampleList) {
JLabel picLabel = new JLabel();
try {
File imageFile = new File(root.getAbsolutePath() + "\\src\\images\\" + "imageName.jpg"); // Try to find the cover image
if(imageFile.exists()) {
BufferedImage movieCover = ImageIO.read(imageFile);
picLabel = new JLabel(new ImageIcon(movieCover));
} else {
BufferedImage movieCover = ImageIO.read(new File(root.getAbsolutePath() + "\\src\\images\\temp.jpg")); // Get a temp image
picLabel = new JLabel(new ImageIcon(movieCover));
}
} catch (IOException e) {
e.printStackTrace();
}
JLabel movieName = new JLabel("New Movie");
movieName.setForeground(Color.WHITE);;
JButton movieButton = new JButton();
movieButton.setLayout(new GridLayout(0, 1));
//movieButton.setContentAreaFilled(false);
//movieButton.setBorderPainted(false);
//movieButton.setFocusPainted(false);
movieButton.add(picLabel);
movieButton.add(movieName);
moviePanel.add(movieButton);
}
return moviePanel;
}
public static JPanel createNavigationBar() {
JPanel navBar = new JPanel();
navBar.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 20));
navBar.setBackground(new Color(25, 25, 25));
JButton homeButton = new JButton("Home");
homeButton.setContentAreaFilled(false);
homeButton.setBorderPainted(false);
homeButton.setFocusPainted(false);
JButton movieButton = new JButton("Movies");
movieButton.setContentAreaFilled(false);
movieButton.setBorderPainted(false);
movieButton.setFocusPainted(false);
// Add all the buttons to the navbar
navBar.add(homeButton);
navBar.add(movieButton);
return navBar;
}
}
I noticed that the GridLayout always tries to fit everything onto the window.
All that's needed is a properly configured JButton in a GridLayout.
E.G.
public static JPanel createMoviePanel() {
JPanel movieLibraryPanel = new JPanel(new GridLayout(0, 10, 3, 3));
movieLibraryPanel.setBackground(new Color(132, 132, 132));
int m = 5;
BufferedImage image = new BufferedImage(9 * m, 16 * m, BufferedImage.TYPE_INT_RGB);
for (int ii = 1; ii < 21; ii++) {
JButton picButton = new JButton("Mov " + ii, new ImageIcon(image));
picButton.setMargin(new Insets(0,0,0,0));
picButton.setForeground(Color.WHITE);
picButton.setContentAreaFilled(false);
picButton.setHorizontalTextPosition(JButton.CENTER);
picButton.setVerticalTextPosition(JButton.BOTTOM);
movieLibraryPanel.add(picButton);
}
return movieLibraryPanel;
}
Here is a complete source for the above with a tweak to put the year on a new line. It uses HTML in the JButton to break the button text into two lines.
The input focus is on the first button, whereas the mouse hovers over the '2009' movie:
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
class MovieGrid {
MovieGrid() {
JFrame f = new JFrame("Movie Grid");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.add(createMoviePanel());
f.pack();
f.setVisible(true);
}
public static JPanel createMoviePanel() {
JPanel movieLibraryPanel = new JPanel(new GridLayout(0, 10, 3, 3));
movieLibraryPanel.setBackground(new Color(132, 132, 132));
int m = 5;
BufferedImage image = new BufferedImage(
9 * m, 16 * m, BufferedImage.TYPE_INT_RGB);
for (int ii = 2001; ii < 2021; ii++) {
JButton picButton = new JButton(
"<html>Movie<br>" + ii, new ImageIcon(image));
picButton.setMargin(new Insets(0,0,0,0));
picButton.setForeground(Color.WHITE);
picButton.setContentAreaFilled(false);
picButton.setHorizontalTextPosition(JButton.CENTER);
picButton.setVerticalTextPosition(JButton.BOTTOM);
movieLibraryPanel.add(picButton);
}
return movieLibraryPanel;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new MovieGrid();
}
};
SwingUtilities.invokeLater(r);
}
}
Same idea's from Andrew Thompson answer but with some minor text alignment changes and hover effect
final class Testing
{
public static void main(String[] args)
{
JFrame frame=new JFrame("NEFLIX");
frame.setContentPane(new GridDisplay());
frame.pack();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static final class GridDisplay extends JPanel implements ActionListener
{
private GridDisplay()
{
super(new GridLayout(0,5,20,20));
setBackground(new Color(0,0,0,255));
BufferedImage image=new BufferedImage(150,200,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d=(Graphics2D)image.getGraphics();
g2d.setColor(Color.BLUE);
g2d.fillRect(0,0,image.getWidth(),image.getHeight());
HoverPainter painter=new HoverPainter();
for(int i=0;i<10;i++)
{
TVShowCard card=new TVShowCard(image,"Show "+i,"199"+i);
card.addMouseListener(painter);
add(card);
}
}
//highlight only on hover
private final class HoverPainter extends MouseAdapter
{
#Override
public void mouseExited(MouseEvent e) {
((TVShowCard)e.getSource()).setBorderPainted(false);
}
#Override
public void mouseEntered(MouseEvent e) {
((TVShowCard)e.getSource()).setBorderPainted(true);
}
}
private final class TVShowCard extends JButton
{
private TVShowCard(BufferedImage preview,String name,String year)
{
super();
setContentAreaFilled(false);
setBackground(new Color(0,0,0,0));
setFocusPainted(false);
setBorderPainted(false);
//I didn't use image icon & text horizontal alignment because the text always horizontally centered aligned but from the expected output it was left so created 2 labels for the job
setLayout(new GridBagLayout());
addIcon(preview);
addLabel(name,year);
addActionListener(GridDisplay.this);
}
private void addIcon(BufferedImage preview)
{
JLabel icon=new JLabel();
icon.setIcon(new ImageIcon(preview));
add(icon,new GridBagConstraints(0,0,1,1,1.0f,0.0f,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0));
}
private void addLabel(String name,String year)
{
JLabel label=new JLabel("<html><body>"+name+"<br>"+year+"</body></html>");
label.setForeground(Color.white);
label.setBackground(new Color(0,0,0,0));
add(label,new GridBagConstraints(0,1,1,1,1.0f,1.0f,GridBagConstraints.SOUTHWEST,GridBagConstraints.NONE,new Insets(5,0,0,0),0,0));
}
}
#Override
public void actionPerformed(ActionEvent e)
{
TVShowCard card=(TVShowCard)e.getSource();
//do stuff with it
}
}
}
I can't seem to figure out how I would add in a background WITH all of my panels showing.
I tried to set the JFrame content pane as a label with an imageicon and the frame does show, it just doesn't show the image like above.
This is the code that I've used.
frame.setContentPane(new JLabel(new ImageIcon("res/Wallpaper.png")));
The second attempt I've used is to ADD (not set) an image into the content pane of the frame. This did not work as shown in the second picture above and it only shows the panels but no background. The code is on the bottom.
frame.getContentPane().add(new JLabel(new ImageIcon("res/Wallpaper.png")));
The third attempt I've tried is to create a subclass of JComponent and Override the paintComponents method then setan object of it as the contentpane. This does not work and instead turns my screen blank.
Here is the code I've used and the class code is in the 1st answer of this link Setting background images in JFrame. The result is the 3rd image of this post.
File img = new File("res/Wallpaper.png");
BufferedImage myImage;
try {
myImage = ImageIO.read(img);
frame.setContentPane(new ImagePanel(myImage));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The 4th attempt I've tried is adding the picture into the main panel that fills up the screen. This does not work at all and instead breaks the image in half so half of the screen has the image half doesn't.
Here is the code I've used for my 4th attempt. The result is the 4th last image on the top.
BufferedImage myPicture;
try {
myPicture = ImageIO.read(new File("res/Wallpaper.png"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
pMain.add(picLabel);
} catch (IOException e) {
e.printStackTrace();
}
I'm not sure why the JPanels aren't showing up.
I know that in the 1st example when you set the frame as a JLabel it gives it a null layout but that was the only way I could find to DISPLAY the image.
I would like to somehow add the panels ontop of the frame with that background but after reading numerous threads I could not find out how.
If anyone does find out, please post the code and explain if you can. I also have the class get the system class theme that sets it into the theme of what the computer is using. Ex. I am using a windows operating system so it shows it kind of like my operating system.
This thread is not a duplicate. In other threads they only have a frame but in my thread I have several panels that aren't showing for some particular reason.
EDIT: I don't know what's up, I tried to use this thread Setting background images in JFrame but I had no luck.
The 1st method it gave me I tried and then instead of showing anything it showed nothing at all, no picture no components nothing at all. In case if you need more information I have: 4 JPanels on the bottom of the screen, I also have a border surrounding my window but doesn't show up in the 1st window. I also have borders surrounding my panels too.
So the 1st method I've tried setting it on the content pane, image loads but all of the components are gone.
2nd method I've tried adding it into the content pane but yet again with no luck and I get a panel with no background.
3rd method I've tried is creating a separate class and overriding the paintComponent method and adding an image to the constructor of it then placing this object of the class into the setcontentPane() parameter of the frame. Does not work at all, all I get is a blank frame.
Code I am using for my frame:
public class LoginScreen {
JCheckBox remember_User;
JButton login, create_Account, forums, faqs;
Border whiteLine;
JTextField userField;
JFormattedTextField passField;
private void createView() {
// Created essential details for the frame
JFrame frame = new JFrame();
frame.setTitle("Name of the game");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Defining panels and a constraint on the bottomPanel.
// More info - Total amt of panels: 5
// pLogin and pInfo are in the bottomCompPanel and bottomCompPanel is in
// bottomPanel
// bottom panel is in pMain
// Giving panels some attributes like backgrounds and borders
JPanel pMain = new JPanel(new BorderLayout());
pMain.setBorder(BorderFactory.createMatteBorder(3, 3, 6, 3,
Color.DARK_GRAY));
frame.getContentPane().add(pMain);
whiteLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
JPanel pLogin = new JPanel(new GridBagLayout());
pLogin.setBackground(Color.cyan);
pLogin.setPreferredSize(new Dimension(400, 250));
pLogin.setBorder(whiteLine);
JPanel pInfo = new JPanel(new GridBagLayout());
pInfo.setBackground(Color.green);
pInfo.setPreferredSize(new Dimension(200, 100));
pInfo.setBorder(whiteLine);
JPanel bottomCompPanel = new JPanel(new GridBagLayout());
GridBagConstraints bGBC = new GridBagConstraints();
bGBC.gridx = 0;
bGBC.gridy = 0;
bGBC.insets = new Insets(0, 20, 0, 0);
bGBC.anchor = GridBagConstraints.PAGE_END;
bottomCompPanel.add(pLogin, bGBC);
bGBC.gridx++;
bottomCompPanel.add(pInfo, bGBC);
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
bottomPanel.add(bottomCompPanel);
pMain.add(bottomPanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
public static void main(String[] args) {
LoginScreen login = new LoginScreen();
login.createView();
}
}
POST UPDATE 2: Here is the code that I've used using #peeskillet's 1st method. It works sort of but it gives me the same results as the 3rd photo, a cut off picture. P.S I add the panels down at the bottom to my JLabel at the end.
private void createView() {
//Created essential details for the frame
JFrame frame = new JFrame();
frame.setTitle("Name of the game");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JLabel background = new JLabel(new ImageIcon("res/Wallpaper.png"));
background.setLayout(new BorderLayout());
frame.setContentPane(background);
//Defining panels and a constraint on the bottomPanel.
//More info - Total amt of panels: 5
//pLogin and pInfo are in the bottomCompPanel and bottomCompPanel is in bottomPanel
//bottom panel is in pMain
//Giving panels some attributes like backgrounds and borders
whiteLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
JPanel pLogin = new JPanel(new GridBagLayout());
pLogin.setBackground(Color.cyan);
pLogin.setPreferredSize(new Dimension(400,250));
pLogin.setBorder(whiteLine);
JPanel pInfo = new JPanel(new GridBagLayout());
pInfo.setBackground(Color.green);
pInfo.setPreferredSize(new Dimension(200,100));
pInfo.setBorder(whiteLine);
JPanel bottomCompPanel = new JPanel(new GridBagLayout());
GridBagConstraints bGBC = new GridBagConstraints();
bGBC.gridx = 0;
bGBC.gridy = 0;
bGBC.insets = new Insets(0,20,0,0);
bGBC.anchor = GridBagConstraints.PAGE_END;
bottomCompPanel.add(pLogin, bGBC);
bGBC.gridx++;
bottomCompPanel.add(pInfo, bGBC);
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
bottomPanel.add(bottomCompPanel);
background.add(bottomPanel, BorderLayout.SOUTH);
"I tried to set the JFrame content pane as a label with an imageicon"
You need to set the layout on the JLabel. It will be null be default.
import java.awt.*;
import java.net.URL;
import javax.swing.*;
import javax.swing.border.Border;
public class BackgroundImage {
private static final String IMG = "http://i.stack.imgur.com/JEoYs.jpg";
private void init() throws Exception {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel background = new JLabel(new ImageIcon(new URL(IMG)));
background.setLayout(new GridBagLayout());
background.add(loginPanel());
f.setContentPane(background);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JPanel loginPanel() {
Border whiteLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
JPanel pLogin = new JPanel(new GridBagLayout());
pLogin.setBackground(Color.cyan);
pLogin.setPreferredSize(new Dimension(400, 250));
pLogin.setBorder(whiteLine);
return pLogin;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
new BackgroundImage().init();
} catch (Exception ex) {}
});
}
}
"I've tried is to create a subclass of JComponent and Override the paintComponents method then setan object of it as the contentpane"
Should be paintComponent (no "s"), but just like with JLabel, you need to set the layout. JComponent layout is null be default. You also need to give it a preferred size when painting.
import java.awt.*;
import java.net.URL;
import javax.swing.*;
import javax.swing.border.Border;
public class BackgroundImage {
private static final String IMG = "http://i.stack.imgur.com/JEoYs.jpg";
private void init() throws Exception {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent background = new BackgroundComponent(new ImageIcon(new URL(IMG)));
background.setLayout(new GridBagLayout());
background.add(loginPanel());
f.setContentPane(background);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JPanel loginPanel() {
Border whiteLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
JPanel pLogin = new JPanel(new GridBagLayout());
pLogin.setBackground(Color.cyan);
pLogin.setPreferredSize(new Dimension(400, 250));
pLogin.setBorder(whiteLine);
return pLogin;
}
class BackgroundComponent extends JComponent {
public ImageIcon background;
public BackgroundComponent(ImageIcon background) {
this.background = background;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(background.getIconWidth(), background.getIconHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background.getImage(),
0, 0,
background.getIconWidth(),
background.getIconHeight(), this);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
new BackgroundImage().init();
} catch (Exception ex) {}
});
}
}
Using (extending) JPanel instead of JComponent would be similar except JPanel does have a default layout which is FlowLayout.
UPDATE
To get your desired layout, you need to play around with the different layout managers. The combination I used is
Outer (main panel) -- BorderLayout
Bottom (bottom panel) -- BoxLayout inside (south) of outer layout
For the BorderLayout, you need to make sure the panel opaque property is set to false, as BorderLayout will stretch the panel and cover the background.
For the BoxLayout, you need to make sure to set the maximum size and the preferred size
import java.awt.*;
import java.net.URL;
import javax.swing.*;
import javax.swing.border.Border;
public class BackgroundImage {
private static final String IMG = "http://i.stack.imgur.com/JEoYs.jpg";
private final Border whiteLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
private void init() throws Exception {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent background = new BackgroundComponent(new ImageIcon(new URL(IMG)));
background.setLayout(new BorderLayout());
background.add(bottomPanel(), BorderLayout.SOUTH);
f.setContentPane(background);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JPanel bottomPanel() {
JPanel bottomPanel = new JPanel();
bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
BoxLayout layout = new BoxLayout(bottomPanel, BoxLayout.X_AXIS);
bottomPanel.setLayout(layout);
bottomPanel.setOpaque(false);
bottomPanel.add(Box.createHorizontalGlue());
bottomPanel.add(loginPanel());
bottomPanel.add(Box.createRigidArea(new Dimension(10, 0)));
bottomPanel.add(infoPanel());
return bottomPanel;
}
private JPanel infoPanel() {
JPanel pInfo = new JPanel(new GridBagLayout());
pInfo.setAlignmentY(Component.BOTTOM_ALIGNMENT);
pInfo.setBackground(Color.green);
pInfo.setMaximumSize(new Dimension(200, 100));
pInfo.setPreferredSize(new Dimension(200, 100));
pInfo.setBorder(whiteLine);
return pInfo;
}
private JPanel loginPanel() {
JPanel pLogin = new JPanel(new GridBagLayout());
pLogin.setAlignmentY(Component.BOTTOM_ALIGNMENT);
pLogin.setBackground(Color.cyan);
pLogin.setPreferredSize(new Dimension(400, 250));
pLogin.setMaximumSize(new Dimension(400, 250));
pLogin.setBorder(whiteLine);
return pLogin;
}
class BackgroundComponent extends JComponent {
public ImageIcon background;
public BackgroundComponent(ImageIcon background) {
this.background = background;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(background.getIconWidth(), background.getIconHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background.getImage(),
0, 0,
background.getIconWidth(),
background.getIconHeight(), this);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
new BackgroundImage().init();
} catch (Exception ex) {
}
});
}
}
For more information about using the different layout managers, see
Laying Out Components Within a Container
You can try JLayeredPane and setOpaque(boolean) method.
Code:
public class BackgroundImageTest{
private JFrame frame;
public BackgroundImageTest() {
frame = new JFrame("Background Image Frame");
// set frame properties
JPanel panel = new JPanel(new FlowLayout());
panel.setOpaque(false);
JButton btn = new JButton("Change Background");
panel.add(btn);
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
setBackgroundImage(getImage(new File("Wallpaper2.png")));
}
});
JPanel main = (JPanel) frame.getContentPane();
main.setLayout(new FlowLayout());
main.add(panel);
main.setOpaque(false);
setBackgroundImage(getImage(new File("Wallpaper.png")));
frame.setVisible(true);
}
private Image getImage(File imageFile) {
BufferedImage image = null;
try {
image = ImageIO.read(imageFile);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return image;
}
private void setBackgroundImage(Image img) {
if(img == null) return;
ImageIcon ii = new ImageIcon(img);
JLabel lblBG = new JLabel(ii);
lblBG.setName("BackgroundImageLabel");
JLayeredPane layeredPane = frame.getLayeredPane();
Component[] comps = layeredPane.getComponentsInLayer(new Integer(Integer.MIN_VALUE));
for (int i = 0; i < comps.length; i++) {
System.out.println(comps[i].getName());
if (comps[i] instanceof JLabel && comps[i].getName().equals("BackgroundImageLabel")){
layeredPane.remove(comps[i]);
break;
}
}
layeredPane.add(lblBG, new Integer(Integer.MIN_VALUE));
lblBG.setBounds(0,0,ii.getIconWidth(), ii.getIconHeight());
}
}
I am making a platformer game for a class project and so far all I have been able to do is add the chicken character to the game. I need to be able to have him move forward on the press of "D" or right arrow. My code is:
public class Main extends JFrame {
public Main(){
//Creates Title Image
JLabel title = new JLabel(" ");
ImageIcon tl = new ImageIcon("title.gif");
title.setIcon(tl);
//Creates Start Image
final JButton start = new JButton("");
ImageIcon st = new ImageIcon("start.gif");
start.setIcon(st);
//Creates Options Image
JButton options = new JButton("");
ImageIcon opt = new ImageIcon("options.gif");
options.setIcon(opt);
options.setBackground(Color.BLACK);
//Create first frame for "Start" button
final JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(1, 1));
p1.add(start, BorderLayout.CENTER);
//Create second panel for title label
final JPanel p2 = new JPanel(new BorderLayout());
p2.setLayout(new GridLayout(1, 3));
p2.add(title, BorderLayout.WEST);
//Create third panel for "Options" button
final JPanel p3 = new JPanel(new BorderLayout());
p3.setLayout(new GridLayout(1, 1));
p3.add(options, BorderLayout.SOUTH);
//Creates fourth panel to organize all other primary
final JPanel p4 = new JPanel(new BorderLayout());
p4.setLayout(new GridLayout(1, 3));
p4.add(p1, BorderLayout.WEST);
p4.add(p2, BorderLayout.CENTER);
p4.add(p3, BorderLayout.EAST);
//When button is clicked, it changes the level
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(start.isEnabled()) {
remove(p4);
setSize(1440, 500);
add(new ContentPanel1());
validate();
}
else {
return;
}
}
});
//Adds fourth panel to frame
add(p4, BorderLayout.CENTER);
}
public static void main(String arg[]) {
Main frame = new Main();
//Finds screen size of monitor
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//Creates the frame
frame.setTitle("Cockadoodle Duty: Awakening");
frame.setSize(screenSize);
frame.setLocale(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
String background = "#000000";
frame.setBackground(Color.decode(background));
}
}
class coordinate {
public static int x;
public static int y;
}
class ContentPanel1 extends JPanel{
Image back = Toolkit.getDefaultToolkit().getImage("level0.gif");
Image chick = Toolkit.getDefaultToolkit().getImage("chicken.gif");
ContentPanel1() {
MediaTracker mt = new MediaTracker(this);
mt.addImage(back, 0);
try {
mt.waitForAll();
} catch (InterruptedException e){
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
coordinate.x = 20;
coordinate.y = 321;
super.paintComponent(g);
int imwidth = back.getWidth(null);
int imheight = back.getHeight(null);
g.drawImage(back, 1, 1, null);
g.drawImage(chick, coordinate.x, coordinate.y, null);
}
public void MoveDirection(KeyEvent e, Graphics g) {
coordinate.x = 20;
coordinate.y = 321;
super.paintComponent(g);
int key = e.getKeyCode();
if(key == 68) {
coordinate.x += 1;
g.drawImage(chick, coordinate.x, coordinate.y, null);
}
}
}
The main trouble I have been having with my code is the bit at the end with the MoveDirection method. The way I have it going is by adding a new chicken to the frame (This was mainly due to the fact that I was just testing to see if the code worked). Is there a better way to do that too?
Start by taking a look at How to Use Key Bindings
NEVER call super.paintComponent(g); (or paintComponent(g);) directly from outside the context of the paintComponent method, there is a lot more to painting then just painting the component background. See Painting in AWT and Swing and Performing Custom Painting for more details. Instead, simply call repaint when you want to, well, repaint the component.
The use of MediaTracker is out of date and you should be using the ImageIO API instead, which will block automatically while reading the image. See Reading/Loading an Image for more details
Don't use Toolkit.getDefaultToolkit().getScreenSize() in combination with JFrame#setSize, the getScreenSize method does not take into account things like the task bar or dock of some OS's, instead use the JFrame#setExtendedState and pass it JFrame.MAXIMIZED_BOTH
frame.setLocale(null); isn't doing what you think it is
I have a JPanel (cardLayoutPanel) which layout is CardLayout.
I also have another 3 different panels (firstPagePanel, secondPagePanel, thirdPagePanel)
firstPagePanel size is approximately around 450x400,
secondPagePanel size is approximately around 800x600
thirdPagePanel size is approximately around 1024x768
I cardLayoutPanel.add all 3 panels and I show firstPagePanel first as my view.
I want to let my program displayed the size of firstPagePanel first which is 450x400
and then if secondPagePanel is displayed, it will change the size to 800x600 and if thirdPagePanel is displayed,it will change the size to 1024,768
Instead of guessing what my 3 panel size should be, I used frame.getPreferredSize() but my first view will always take in the size of my thirdPagePanel which is 1024x768 instead of 450x400;
What can I do to resolve this issue?
public class MainFrame {
private CardLayout cardLayout = new CardLayout();
private JPanel cardLayoutPanel = new JPanel();
private FirstPagePanel firstPagePanel = new FirstPagePanel();
private SecondPagePanel secondPagePanel = new SecondPagePanel();
private ThirdPagePanel thirdPagePanel = new ThirdPagePanel();
private JFrame frame = new JFrame("Panel size test");
public MainFrame() {
cardLayoutPanel.setLayout(cardLayout);
cardLayoutPanel.add(firstPagePanel,"1");
cardLayoutPanel.add(secondPagePanel,"2");
cardLayoutPanel.add(thirdPagePanel,"3");
cardLayout.show(cardLayoutPanel,"1");
frame.add(cardLayoutPanel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.getPreferredSize();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
}
}
The easiest way is to:
Remove the current panel.
Add the new panel.
Pack the top level container.
E.G.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class ThreeSizeGui {
public static void swapComponentsAndResizeUI(
JComponent ui,
JComponent current,
JComponent next) {
ui.remove(current);
ui.add(next);
current = next;
Component c = ui.getTopLevelAncestor();
if (c instanceof Window) {
Window w = (Window) c;
w.pack();
}
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
final JPanel ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(6, 6, 6, 6));
JPanel controls = new JPanel(
new FlowLayout(FlowLayout.LEADING));
ui.add(controls, BorderLayout.PAGE_START);
int s = 100;
Dimension[] sizes = {
new Dimension(s * 4, s * 2),
new Dimension(s * 6, s * 3),
new Dimension(s * 8, s * 4)
};
final JComboBox cb = new JComboBox(sizes);
controls.add(cb);
final JPanel[] panels = new JPanel[sizes.length];
for (int ii = 0; ii < sizes.length; ii++) {
Dimension d = sizes[ii];
BufferedImage bi = new BufferedImage(
d.width, d.height, BufferedImage.TYPE_INT_RGB);
JPanel p = new JPanel(new GridLayout());
JLabel l = new JLabel(new ImageIcon(bi));
p.add(l);
panels[ii] = p;
}
ItemListener sizeListener = new ItemListener() {
JPanel current = panels[0];
#Override
public void itemStateChanged(ItemEvent e) {
JPanel next = panels[cb.getSelectedIndex()];
swapComponentsAndResizeUI(ui, current, next);
current = next;
}
};
cb.addItemListener(sizeListener);
ui.add(panels[0], BorderLayout.CENTER);
JFrame f = new JFrame("Three Sized Panels");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(ui);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
I am using swing to build a GUI with 4 JPanels inside a JPanel using the BorderLayout manager:
A row of labels
A column of JButtons
A display area (it is a class that extends JPanel and has nothing added to it and is used as a drawing area)
Another column of buttons
My code looks like this:
JPanel middle = new JPanel();
middle.setLayout(new BorderLayout());
middle.add(midLabels,BorderLayout.NORTH);
middle.add(pickupButtons,BorderLayout.WEST);
middle.add(simulation,BorderLayout.CENTER);
middle.add(dropButtons,BorderLayout.EAST);
The simulation panel is just an extended JPanel that overrides paintComponent to draw an image. The problem is, the simulation area is on the left and not in the middle:
What I actually want is:
Edit, here is an example, do I need to use a different layout manager to get the empty JPanel positioned correctly?:
import java.awt.*;
import javax.swing.*;
public class Test extends JFrame {
final static int MAXFLOORS = 8;
public Test() {
setLayout(new BorderLayout());
setTitle("Simulator");
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500, 500);
JPanel simulation = new JPanel();
JPanel dropButtons = new JPanel();
JPanel pickupButtons = new JPanel();
pickupButtons.setLayout(new GridLayout(MAXFLOORS, 1));
dropButtons.setLayout(new GridLayout(MAXFLOORS, 1));
setLayout(new BorderLayout());
add(simulation,BorderLayout.CENTER);
add(dropButtons,BorderLayout.EAST);
add(pickupButtons,BorderLayout.WEST);
for (int i = MAXFLOORS; i != 0; i--) {
JButton pb = new JButton("F" + i);
dropButtons.add(pb);
JButton db = new JButton("F" + i);
dropButtons.add(db);
}
repaint();
}
public static void main(String[] args) {
new Test();
}
}
Look at your code:
for (int i = MAXFLOORS; i != 0; i--) {
final JButton pb = new JButton("F" + i);
dropButtons.add(pb);
final JButton db = new JButton("F" + i);
dropButtons.add(db);
}
You're adding onto dropButtons twice, instead of pickupButtons.