I need to make a scrolling background for this platformer. It needs to scroll a 2400x500 image while the frame size is about 1440x900. If it could just gradually change over time that would be great. This is my code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
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);
//Creates label for level 0 background image
JLabel background = new JLabel(" ");
ImageIcon back = new ImageIcon("level0.gif");
background.setIcon(back);
//Creates a panel for level 0
final JPanel p5 = new JPanel();
p5.setLayout (new BorderLayout(1, 1));
p5.add(background);
//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);
add(p5, BorderLayout.CENTER);
invalidate();
validate();
}
else {
return;
}
}
});
//Adds fourth panel to frame
add(p4, BorderLayout.CENTER);
}
public static void main(String args[]) {
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));
}
}
Add the label containing the icon to a scroll panel
Use a Swing Timer to schedule the scrolling
When the Timer fires you can scroll background.
The scrolling code might be something like:
JViewport viewport = scrollPane.getViewport();
Point position = viewport.getViewPosition();
position.x += 2;
viewport.setViiewPosition( position );
Related
I have a card layout where I switch panels with a button. However, the code (switching panels) works only when lines:
JScrollPane scrPane = new JScrollPane(card1);
frame.add(scrPane);
are removed. In other case, clicking button achieves nothing. Is there an option to keep the scrolling (I need this, since the main application will have a lot of wrapped text) without disabling an option to switch cards?
package com.code;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.event.*;
public class Card {
public static void main(String[] args) {
JFrame frame = new JFrame("App");
frame.setVisible(true);
frame.setSize(1200, 800);//Give it a size
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel(new CardLayout());
frame.add(mainPanel);
JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
mainPanel.add(menu, "menu");
mainPanel.add(card1, "card1");
mainPanel.add(card2, "card2");
JLabel l1 = new JLabel("label 1");
JLabel l2 = new JLabel("label 2");
card1.add(l1);
card2.add(l2);
JButton click = new JButton("Click!");
menu.add(click);
JScrollPane scrPane = new JScrollPane(card1);
frame.add(scrPane);
click.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
cardLayout.show(mainPanel, "card1");
}
});
}
}
A JFrame (its content pane) uses BorderLayout by default. That means you can have only 1 component at BorderLayout.CENTER. When you frame.add(component) the default constraints is BorderLayout.CENTER.
Now, you frame.add(mainPanel); and then frame.add(scrPane);. So main panel is removed, since scrPane is being added after it.
Doing JScrollPane scrPane = new JScrollPane(card1); it means you add a scrollpane to card1, and not in content pane. I guess that you want it to the content pane (the whole frame). So the fix is to delete frame.add(mainPanel); and do the following:
JScrollPane scrPane = new JScrollPane(mainPanel);
frame.add(scrPane);
Now, the main panel is added to scrPane and scrPane is added to the frame.
However, your GUI will be empty after that, because you frame.setVisible(true); before you are finished adding components to it. Take a look at Why shouldn't I call setVisible(true) before adding components?
Eventually, full code is:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("App");
frame.setSize(1200, 800);//Give it a size
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel(new CardLayout());
JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
JPanel card2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
mainPanel.add(menu, "menu");
mainPanel.add(card1, "card1");
mainPanel.add(card2, "card2");
JLabel l1 = new JLabel("label 1");
JLabel l2 = new JLabel("label 2");
card1.add(l1);
card2.add(l2);
JButton click = new JButton("Click!");
menu.add(click);
JScrollPane scrPane = new JScrollPane(mainPanel);
frame.add(scrPane);
click.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
cardLayout.show(mainPanel, "card1");
}
});
frame.setVisible(true);
});
}
Some good links I suggest you to read are the Initial Threads and What does .pack() do?
I am trying to add a JScrollPane (createTeamScrollPane) to a JPanel (createTeamPanel) that I have. I have a frame, with a BorderLayout with the NORTH portion being used by a JPanel called tabMenu, and then the CENTER portion I would like my 'createTeamPanel' to have this scrolling ability as it will have more content than what I can fit on the screen at once. I am then adding both panels to the frame. Currently the code as is runs but the window appears blank. Once resizing the window, I then see the 3 buttons in the NORTH portion of my frame (why is this happening?) and when I click on 'Create Team' it brings up the list of JLabels and JButtons I expect but I don't see any scrolling bars?
public static void main (String args[]) {
JFrame frame = new JFrame();
frame.setTitle("v0.01");
frame.setSize(800, 800);
//frame.setLayout(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JPanel tabMenu = new JPanel();
JPanel createTeamPanel = new JPanel();
createTeamPanel.setLayout(new BoxLayout(createTeamPanel, BoxLayout.Y_AXIS));
createTeamPanel.setSize(800, 700);
createTeamPanel.setVisible(showCreateTeamPanel);
createTeamPanel.setBackground(Color.gray);
JScrollPane createTeamScrollPane = new JScrollPane(createTeamPanel);
createTeamScrollPane.setBounds(50, 50, 200, 500);
createTeamScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
createTeamScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
createTeamScrollPane.setPreferredSize(new Dimension(500,500));
//createTeamPanel.add(createTeamScrollPane);
List<Player> teamList = MockTeams.initTeam();
int xcoord = 100;
int ycoord = 50;
for(Player player : teamList) {
JLabel label = new JLabel(player.getName());
label.setBounds(xcoord, ycoord, Constants.buttonWidth, Constants.buttonHeight);
JButton addToTeamBtn = new JButton("Add to team");
addToTeamBtn.setBounds(xcoord + 100, ycoord, Constants.buttonWidth, Constants.buttonHeight);
addToTeamBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myTeam.add(player);
addToTeamBtn.setEnabled(false);
}
});
createTeamPanel.add(label);
//createTeamFrame.add(label);
createTeamPanel.add(addToTeamBtn);
//createTeamFrame.add(addToTeamBtn);
ycoord += 50;
}
JButton createTeamBtn = new JButton("Create Team");
createTeamBtn.setBounds(0,0,150,20);
createTeamBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Hide/Show Create team panel
if (!showCreateTeamPanel) {
showCreateTeamPanel = true;
createTeamPanel.setVisible(showCreateTeamPanel);
} else {
showCreateTeamPanel = false;
createTeamPanel.setVisible(showCreateTeamPanel);
}
}
});
JButton manageTeamBtn = new JButton("Team Statistics");
manageTeamBtn.setBounds(100,150,150,40);
JButton resetBtn = new JButton("Reset Season");
resetBtn.setBounds(100,200,150,40);
tabMenu.add(createTeamBtn);
tabMenu.add(manageTeamBtn);
tabMenu.add(resetBtn);
mainPanel.add(tabMenu, BorderLayout.NORTH);
mainPanel.add(createTeamPanel, BorderLayout.CENTER);
frame.add(mainPanel);
}
Expected result is to see a scrolling ability on the createTeamPanel but it is not there.
Fixed: I was able to add the JScrollPane to the mainPanel with:
mainPanel.add(createTeamScrollPane, BorderLayout.CENTER);
Essentially, I am trying to add a home screen with 4 buttons, 3 difficulty buttons and a play button. I add the buttons to a JPanel and add the JPanel with a BoxLayout of Center. Why does the buttons still go all the way off to the right? Setting the icon for a JLabel on and adding it to the home screen JPanel is a possible mess up the flow of components? I want the difficulty buttons to be on top of the of the gif with the Play button at the bottom. Thanks for your help.
//container
snake = new JFrame();
snake.setLayout(new BorderLayout());
//home screen panel
homeScreen = new JPanel();
homeScreen.setLayout(new BoxLayout(homeScreen, BoxLayout.X_AXIS));
homeScreen.setPreferredSize(new Dimension(320, 320));
JLabel bg = new JLabel();
ImageIcon icon = new ImageIcon("HomeBG.gif");
icon.getImage().flush();
bg.setIcon(icon);
homeScreen.add(bg);
easy = new JButton("Easy");
medium = new JButton("Medium");
hard = new JButton("Hard");
play = new JButton("Play");
//button listeners code here
homeScreen.add(easy);
homeScreen.add(medium);
homeScreen.add(hard);
homeScreen.add(play);
snake.add(homeScreen, BorderLayout.CENTER);
snake.setTitle("Snake Game");
snake.pack();
snake.setVisible(true);
snake.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
You need to change your code as shown below.
snake = new JFrame();
snake.setLayout(new BorderLayout());
//home screen panel
homeScreen = new JPanel(new BorderLayout());
//homeScreen.setLayout(new BoxLayout(homeScreen, BoxLayout.X_AXIS));
homeScreen.setPreferredSize(new Dimension(320, 320)); // probably you need to remove this line!
JLabel bg = new JLabel();
ImageIcon icon = new ImageIcon("HomeBG.gif");
icon.getImage().flush();
bg.setIcon(icon);
homeScreen.add(bg);
easy = new JButton("Easy");
medium = new JButton("Medium");
hard = new JButton("Hard");
play = new JButton("Play");
//button listeners code here
JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonsPanel.add(easy);
buttonsPanel.add(medium);
buttonsPanel.add(hard);
buttonsPanel.add(play);
homeScreen.add(buttonsPanel, BorderLayout.NORTH);
snake.add(homeScreen, BorderLayout.CENTER);
snake.setTitle("Snake Game");
snake.pack();
snake.setVisible(true);
snake.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
I would use a compound layout for this. Put the level buttons in a (panel in a) FlowLayout. Put the play button in a 2nd FlowLayout. Add those panels to the PAGE_START and PAGE_END of a BorderLayout. Add a label containing the GIF to the CENTER of the same border layout.
BTW - the level buttons should be radio buttons (in a button group - BNI).
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class LayoutManagersWithIcon {
private JComponent ui = null;
LayoutManagersWithIcon() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,4,4,4));
JPanel levelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
ui.add(levelPanel, BorderLayout.PAGE_START);
levelPanel.add(new JRadioButton("Easy"));
levelPanel.add(new JRadioButton("Medium"));
levelPanel.add(new JRadioButton("Hard"));
JPanel startPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
ui.add(startPanel, BorderLayout.PAGE_END);
startPanel.add(new JButton("Play"));
JLabel label = new JLabel(new ImageIcon(
new BufferedImage(400, 100, BufferedImage.TYPE_INT_RGB)));
ui.add(label);
}
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) {
}
LayoutManagersWithIcon o = new LayoutManagersWithIcon();
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 am making a platformer game for a project for class and need to have a chicken character jump on some platforms. I have a start screen and a button, and when the button is clicked, it will change the frame to the first level. When I add the chicken character to the frame as well as the background image, all I can see is the background image. Should I be using a different layout or is there something else I can do. This is my code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Main extends JFrame {
public Main(){
//Creates Chicken Character
final JLabel chicken = new JLabel(" ");
ImageIcon chick1 = new ImageIcon("chicken.gif");
ImageIcon chick2 = new ImageIcon("chicken2.gif");
chicken.setIcon(chick1);
//Sets Chicken Location
chicken.setLocation(1, 1);
//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);
//Creates label for level 0 background image
JLabel background = new JLabel(" ");
ImageIcon back = new ImageIcon("level0.gif");
background.setIcon(back);
//Creates a panel for level 0
final JPanel p5 = new JPanel();
chicken.setLocation(1, 1);
p5.add(background);
//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);
add(new ContentPanel());
add(chicken);
chicken.setLocation(100, 100);
setSize(1440, 500);
setLocale(null);
chicken.isOpaque();
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 ContentPanel extends JPanel{
Image bgimage = null;
ContentPanel() {
MediaTracker mt = new MediaTracker(this);
bgimage = Toolkit.getDefaultToolkit().getImage("level0.gif");
mt.addImage(bgimage, 0);
try {
mt.waitForAll();
} catch (InterruptedException e){
e.printStackTrace();
}
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
int imwidth = bgimage.getWidth(null);
int imheight = bgimage.getHeight(null);
g.drawImage(bgimage, 1, 1, null);
}
}
Note: It's been a while since I used the Graphics API
Quick Answer:
You need to draw everything in your paintComponent method. Your drawing routine should check the state of all game objects and draw them accordingly. Right now the panel is drawing the background image - that's it. Add your chicken image the same way you added your bgImage.
Some more things to consider:
If you experience screen flicker look into Double Buffering.
Not to overwhelm you but you might want to do some light reading on game coding. Get a general idea on how to code your game loop and what happens each time the loop is executed.
Since you are using an OO language you should also probably make a Chicken class.
public class Chicken {
private int x;
private int y;
private Image chickenSprtie;
//add get / set for access
}
Or even a general Super Class - Sprite with int x, int y. Or even a "Drawable" interface to forces all your drawable game objects to have common methods....
I really didn't now how to form the question i have a gridlayout with 4 buttons. When the user press Add module i want under the buttons a form instead of a new windows if this is possible.
frame = new JFrame("ModuleViewer");
makeMenu(frame);
Container contentPane = frame.getContentPane();
// Specify the layout manager with nice spacing
contentPane.setLayout(new GridLayout(0, 2));
addModule = new JButton("Toevoegen Module");
contentPane.add(addModule);
overview = new JButton("Overzicht Modules");
contentPane.add(overview);
addSchoolweeks = new JButton("Aapassen schoolweken");
contentPane.add(addSchoolweeks);
weekheavy = new JButton("Weekbelasting");
contentPane.add(weekheavy);
frame.pack();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(d.width/2 - frame.getWidth()/2, d.height/2 - frame.getHeight()/2);
frame.setVisible(true);
I know that i first need to add een action method for the buttons i know how to do that so that isn't important. I only want to know how i could create a layout under the buttons so when a user clicks the layout will be draw.
Each panel can only have one layout, but you can use multiple panels for the desired effect: a top panel using GridLayout to hold your buttons, and a bottom panel using CardLayout to hold multiple other panels, one for each button click. Each of these panels can use whatever layout you want, depending on its contents.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardLayoutDemo implements Runnable
{
final static String CARD1 = "Red";
final static String CARD2 = "Green";
final static String CARD3 = "Blue";
JPanel cards;
CardLayout cardLayout;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new CardLayoutDemo());
}
public void run()
{
JButton btnRed = createButton("Red");
JButton btnGreen = createButton("Green");
JButton btnBlue = createButton("Blue");
JPanel buttons = new JPanel(new GridLayout(1,3));
buttons.add(btnRed);
buttons.add(btnGreen);
buttons.add(btnBlue);
JPanel card1 = new JPanel();
card1.setBackground(Color.RED);
JPanel card2 = new JPanel();
card2.setBackground(Color.GREEN);
JPanel card3 = new JPanel();
card3.setBackground(Color.BLUE);
cardLayout = new CardLayout();
cards = new JPanel(cardLayout);
cards.add(card1, CARD1);
cards.add(card2, CARD2);
cards.add(card3, CARD3);
JFrame f = new JFrame("CardLayout Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(buttons, BorderLayout.NORTH);
f.add(cards, BorderLayout.CENTER);
f.setSize(300, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JButton createButton(final String name)
{
JButton button = new JButton(name);
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
cardLayout.show(cards, name);
}
});
return button;
}
}