I Have applet with a image of a java cup that can be repositioned by the clicking of 5 buttons to move it in the main area of the applet window.
the issue im having is the buttons are not being displayed in im applet the only thing that is showing is my cup.gif on the blue background, can any one see the problem with the code ,i want the buttons to show and work
And yes guys I know AWT is old but i have to learn it for my course...any help would be great thanks guys!
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class moveIt extends Applet implements ActionListener
{
private Image cup;
private Panel Keypad = new Panel();
public int top = 15;
public int left = 15;
private Button Keyarray[] = new Button[5];
public void init ()
{
cup=getImage(getDocumentBase(), "cup.gif");
Canvas myCanvas= new Canvas();
Keyarray[0] = new Button ("Up");
Keyarray[1] = new Button ("Left");
Keyarray[2] = new Button ("Down");
Keyarray[3] = new Button ("Right");
Keyarray[4] = new Button ("Center");
setBackground(Color.BLUE);
Panel frame = new Panel();
frame.setLayout(new BorderLayout());
frame.add(myCanvas, BorderLayout.NORTH);
frame.add(Keypad, BorderLayout.SOUTH);
Keypad.setLayout(new BorderLayout());
Keypad.add(Keyarray[0], BorderLayout.NORTH);
Keypad.add(Keyarray[1], BorderLayout.WEST);
Keypad.add(Keyarray[2], BorderLayout.SOUTH);
Keypad.add(Keyarray[3], BorderLayout.EAST);
Keypad.add(Keyarray[4], BorderLayout.CENTER);
Keyarray[0].addActionListener(this);
Keyarray[1].addActionListener(this);
Keyarray[2].addActionListener(this);
Keyarray[3].addActionListener(this);
Keyarray[4].addActionListener(this);
}//end of method init
public void paint(Graphics g)
{
g.drawImage(cup, left, top, this);
}
public void actionPerformed(ActionEvent e)
{
String arg= e.getActionCommand();
if (arg.equals("Up"))
top -= 15;
if (arg.equals("down"))
top += 15;
if (arg.equals("Left"))
left -= 15;
if (arg.equals("Right"))
left += 15;
if (arg.equals("Center"))
{
top=60;
} left=125;
repaint();
}//end paint method
}//end of class
You never add the frame to the applet this.add(frame)
Once you do, you will have to setOpaque(false) to the frame so you can see the background
Important Side Notes:
Instead of painting on the Applet directly, you should be painting rather on a JPanel and override it's paintComponent method.
You Need to call super.paint(g) or super.paintComponent(g)(for JPanel) in the paint method, as to not break the paint chain and see all kinds of wierd paint artifacts
I just noticed the AWT components. AWT is pretty much obsolete. You should move it up to using Swing. See the Swing Tutorials
Use Java naming convention. Variables begin with lower case letters, using camelCasing e.g. Keyarray → keyArray. Class names begin with capital letters using CamelCasing e.g. moveIt → MoveIt
Related
Background: Making a game in Swing. It is simple turn base game. Not a whole lot going on. Because of this I didn't think I would need to implement a Game Tick. Rather, my thought was when a component got changed or needed to be updated just simply revalidate/repaint that component on the fly rather than repainting the whole screen.
I have a GameJPanel which currently has all the components on it. This JPanel is the one that contains the components that get revalidated/repainted etc.
I figured I could make JLayeredPane that holds GameJPanel and my OptionJPanel. Have a Button on GameJPanel that when pressed causes the OptionJPanel to show on top of it and having its JPanel 50% transparent (so it gives the affect it dims the GameJPanel).
However, once I did this what happened was that the GameJPanel started to replace OptionJPanel components (because of the events... etc; repainting of the components).
So currently I am at a loss on what to do. I'm thinking if I had some sort of game tick I wouldn't be having this issue, however, I am not 100% certain. I'm a little worried if I implemented a gametick that the events in game will cause the GameJPanel components to show through for half a second then get replaced. There are some events that cause components to repaint themselves without manually doing it (like quick example for JLabel setText();)
As an example of what I'm trying to go for.
I have tried with a CardLayout but I couldn't figure out how to have the OptionJPanel be on top of GameJPanel while seeing GameJPanel in the background (I tried setting background color, setOpaque(false)..., tried to limit Option JPanel size but I think the CardLayout stretches it (not 100% sure)) all I got was a gray background when doing so.
I would prefer not to go the CardLayout route because in the future I also plan on placing components on top of the GameJPanel (like someone clicks a button, have another panel on a different layer have a component slide in or out etc).
I use CardLayout a ton with my other components in GameJPanel to swap screens around, but haven't had the need to have the other components behind the one showing to show through.
Any ideas on how to go about this would be great or even example code that shows this.
As noted above, you would use a JDialog, a component that is easy to make (similar to making a JFrame) and easy to place. Simply place it "relative-to" the JFrame, e.g.,
myDialog.setLocationRelativeTo(myJFrame);
... and it will automatically center itself on the JFrame. The tricky part is dimming the underlying JFrame, and for this you would need to use a JGlassPane added to the JFrame's rootpane, one set with a background color that uses an alpha composite value. The tricky part with this is to draw the darker background without causing side effects, and to do this, please read Rob Camick's (StackOverflow user camickr) excellent tutorial on drawing in Swing with alpha composites which you can find here: Java Tips Weblog: Backgrounds with Transparency
An example of such a program is shown here:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class DialogEg {
// path to example image used as "game" background
private static final String IMG_PATH = "https://upload.wikimedia.org/"
+ "wikipedia/commons/7/76/Jump_%27n_Bump.png";
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
// get the "game" background image, or exit if fail
BufferedImage img = null;
try {
URL imgUrl = new URL(IMG_PATH);
img = ImageIO.read(imgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
// pass "game" image into main JPanel so that it will be drawn
DeMainPanel mainPanel = new DeMainPanel(img);
JFrame frame = new JFrame("Dialog Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel); // add main JPanel to JFrame
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
// main JPanel
#SuppressWarnings("serial")
class DeMainPanel extends JPanel {
private BufferedImage img; // background image
// JButton action that shows the JDialog and darkens the glasspane
private PauseAction pauseAction = new PauseAction("Pause");
public DeMainPanel(BufferedImage img) {
super();
this.img = img;
add(new JButton(pauseAction));
}
// draw the "game" background image within the JPanel if not null
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
// size this JPanel to match the image's size
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
int width = img.getWidth();
int height = img.getHeight();
return new Dimension(width, height);
}
}
// Action / ActionListener for JButton -- shows JDialog and darkens glasspane
#SuppressWarnings("serial")
class PauseAction extends AbstractAction {
private static final int ALPHA = 175; // how much see-thru. 0 to 255
private static final Color GP_BG = new Color(0, 0, 0, ALPHA);
private DeDialogPanel deDialogPanel = new DeDialogPanel(); // jpanel shown in JDialog
public PauseAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
// comp is our JButton
Component comp = (Component) e.getSource();
if (comp == null) {
return;
}
// create our glass pane
JPanel glassPane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
// magic to make it dark without side-effects
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
// more magic below
glassPane.setOpaque(false);
glassPane.setBackground(GP_BG);
// get the rootpane container, here the JFrame, that holds the JButton
RootPaneContainer win = (RootPaneContainer) SwingUtilities.getWindowAncestor(comp);
win.setGlassPane(glassPane); // set the glass pane
glassPane.setVisible(true); // and show the glass pane
// create a *modal* JDialog
JDialog dialog = new JDialog((Window)win, "", ModalityType.APPLICATION_MODAL);
dialog.getContentPane().add(deDialogPanel); // add its JPanel to it
dialog.setUndecorated(true); // give it no borders (if desired)
dialog.pack(); // size it
dialog.setLocationRelativeTo((Window) win); // ** Center it over the JFrame **
dialog.setVisible(true); // display it, pausing the GUI below it
// at this point the dialog is no longer visible, so get rid of glass pane
glassPane.setVisible(false);
}
}
// JPanel shown in the modal JDialog above
#SuppressWarnings("serial")
class DeDialogPanel extends JPanel {
private static final Color BG = new Color(123, 63, 0);
public DeDialogPanel() {
JLabel pausedLabel = new JLabel("PAUSED");
pausedLabel.setForeground(Color.ORANGE);
JPanel pausedPanel = new JPanel();
pausedPanel.setOpaque(false);
pausedPanel.add(pausedLabel);
setBackground(BG);
int eb = 15;
setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
setLayout(new GridLayout(0, 1, 10, 10));
add(pausedPanel);
add(new JButton(new FooAction("RESUME")));
add(new JButton(new FooAction("RESTART")));
add(new JButton(new FooAction("EXIT TO MAP")));
}
// simple action -- all it does is to make the dialog no longer visible
private class FooAction extends AbstractAction {
public FooAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
Component comp = (Component) e.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose(); // here -- dispose of the JDialog
}
}
}
The GUI looks like this initially:
but then when the dialog shows and the glass pane is darkened, it looks like this:
So after about a month of working on my game I was drawn to this post once again. I implemented part of my game with what DontKnowMuchButGettingBetter's way and also implemented this by just adding the components to the GlassPane so to speak (Made a JPanel, set it to be GlassPane, did whatever on that Panel)...
The later implementation (GlassPane), isn't the best way to go about this because then you can't use the glass pane for other useful things.
I came back to my original idea to use a JLayeredPane. Having different Components on different levels and working off that. My issue before was that when components were getting repainted, the components in the backer layers were over painting the ones in the front layer.
Well I just came across a method called isOptimizedDrawingEnabled()... By making this method always return false for the JLayeredPane I was able to achieve what I wanted.
I don't understand this, I'm currently making a main menu for a game i'm making but for some reason when I hover over a JButton, it flashes up on the top left side of the JFrame. I don't have any mouseAction methods or anything, is it the gif i'm using? I'm not sure...
Here is a screengrab of the error
Here is my code :
import javax.swing.*;
import java.awt.*;
public class MainMenu {
JFrame frame = new JFrame("Frasergatchi");
public void display(){
frame.setSize(400,400);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
}
public void addComponents(){
JButton play = new JButton("Play");
JButton instructions = new JButton("Instructions");
JButton exit = new JButton("Exit");
JPanel panel = new JPanel();
paintMenu paintMenu = new paintMenu();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.add(panel);
play.setAlignmentX(Component.CENTER_ALIGNMENT);
instructions.setAlignmentX(Component.CENTER_ALIGNMENT);
exit.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(paintMenu);
panel.add(play);
panel.add(instructions);
panel.add(exit);
}
public class paintMenu extends JPanel{
public void paintComponent(Graphics graphics){
Image dog = new ImageIcon(getClass().getResource("DogMenuImage.gif")).getImage();
graphics.drawImage(dog,170,240,this);
}
}
}
The first statement in the paintComponent() method should always be:
super.paintComponent(g);
to make sure the background gets cleared.
Also:
Don't do I/O in a painting method. Painting methods are for painting only. Read the image in the constructor of your class and same the image in an instance variable.
Class names SHOULD start with an upper case character. Think of all the classes in the JDK and follow the standards.
There is no need to create a custom class to paint the image. Just use a JLabel with an Icon.
So I would like to have three JButtons all on top of each other, but not to large in width or height either. I am not too familiar with Java's layouts, and to be honest I am not too keen on them. Please view the image a code below to explain to me how, thanks.
package com.aqagame.harrykitchener;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class Main
{
private JButton playGame, playerNames, exitGame;
public Main()
{
JPanel mainCard = new JPanel(new BorderLayout(8, 8));
playGame = new JButton("Play Game");
playerNames = new JButton("Player Names");
exitGame = new JButton("Exit Game");
mainCard.add(playGame, BorderLayout.NORTH);
mainCard.add(playerNames, BorderLayout.CENTER);
mainCard.add(exitGame, BorderLayout.SOUTH);
JFrame window = new JFrame("Harry's AQA game");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(mainCard);
window.setSize(900, 800);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Main();
}
});
}
}
Check out the Java Documentation for the different layout managers. I know you're not familiar with them, which is why you should probably start. Once you get used to them there is no end to their benefits. There is a lot of excellent information in the documentation and I am sure you will learn a lot. Personally, I recommend looking at the Box Layout:
Create JPanel that uses a GridLayout and add all the buttons to the panel. The GridLayout will automactially size the buttons to be the same size.
Set the layout manager of your main window to use a GridBagLayout.
add the panel to the main window using the default GridBagConststraints. Then the panel will automatically be centered both horizontally and vertically.
To not use Box or GridBag, I think a combination such as this may work out:
Have main panel (let's call it A) have a BorderLayout
Create another panel (let's call it B), with a FlowLayout, with constructor aligning components to the center
Create another panel (let's call it C), with a GridLayout, 1 column 3 rows
Add each button to a new JPanel with a FlowLayout (1 JPanel per button, so buttons are wrapped by a FlowLayout), and then add each of those JPanels to C
Add C to B
Add B to A (center position)
I think this should cause buttons to be on top of each other with small amount of padding while not being stretched widthwise and while appearing in the center of the screen.
I am just starting to make a simple mp3 player, I am creating the play, forward, back, etc... Button but for some reason only the first button appears and to make the second button appear I have to go and scroll over it. If you could help me fix that, that would be great. And I am using a two images one named play.jpg and another named next.png.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Graphic extends JPanel{
JFrame f = new JFrame();
JPanel p = new JPanel(new GridBagLayout());
public Graphic(){
gui();
}
public void gui(){
f.setVisible(true);
f.setSize(1600,900);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(p);
ppr(75,26,25,25,"pics/play.jpg");
//above is the play button
ppr(40,26,25,25,"pics/next.png");
// above is the button that wont appear until it is scrolled over (it is just to the left of the button above
}
public void ppr(int x, int y, int width, int height, String file){
p.setLayout(null);
Toolkit tool = Toolkit.getDefaultToolkit();
Image player = tool.getImage(file);
ImageIcon playbutton = new ImageIcon(player);
JButton play = new JButton(playbutton);
play.setBounds(x, y, width, height);
p.add(play);
// ********************** above is the the method that makes a button
}
public static void main(String args[]) {
new Graphic();
}
}
Don't use setBounds. Use GridBagLayout
you specified while initialising the panel and specify GridBagConstraints
The setVisible(true) method should be invoked AFTER all the components have been added to the GUI.
I also agree with the other suggestions for better GUI design.
Run the GUI in a different thread, not the main thread.
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
All UI code should be run in the event dispatch thread for Swing.
In the below code I am attempting to move the three buttons to the left when you click the left button. When I click it; nothing happens currently. Can anyone explain to me what I am doing wrong here? Also, for some reason it has stopped compiling correctly and I am unsure why but I BELIEVE it is because of a mistake in my code while attempting to get the buttons to move to the left when you click the button. I do NOT want the window to move. Just the buttons within the window. Does any one see what I am doing wrong and can you explain it?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Buttons extends JFrame {
//Control Definitions
JButton resetButton;
JButton leftButton;
JButton colorButton;
JPanel buttonPanel;
// Layout Definiton
eventHandle evt;
FlowLayout flt;
Point point; //to Hold Previous Window Position
Color color; //to Hold Previous Color
public Buttons() {
super("Buttons Window");
flt = new FlowLayout();//inialize the Flow Layout
buttonPanel = new JPanel(flt);
//inialize the buttonPanel With Flow Layout
//initialize buttons
resetButton = new JButton("Reset");
leftButton = new JButton("Left");
colorButton = new JButton("Blue");
evt = new eventHandle(); //initiate the eventhandle class
buttonPanel.add(leftButton); //add leftButton
buttonPanel.add(colorButton);//add colorButton
buttonPanel.add(resetButton);//add colorButton
getContentPane().add(buttonPanel);//buttonPanel
//add actionlistners
leftButton.addActionListener(evt);
colorButton.addActionListener(evt);
resetButton.addActionListener(evt);
setBounds(20, 120, 250, 70);
//following Initate the point with Center of Scren
point = new Point((Toolkit.getDefaultToolkit().
getScreenSize().width - getWidth()) / 2,
(Toolkit.getDefaultToolkit().getScreenSize().height
- getHeight()) / 2);
setLocation(point); //locates the window in center
color = buttonPanel.getBackground();//stores the initial color
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
class eventHandle implements ActionListener { //Event Handler
public void actionPerformed(ActionEvent e) {
{
if (e.getSource() == leftButton) ///if its from leftButton
{
leftButton.setAlignmentX(Component.LEFT_ALIGNMENT);
colorButton.setAlignmentX(Component.LEFT_ALIGNMENT);
resetButton.setAlignmentX(Component.LEFT_ALIGNMENT);
//setLocation( (point.x -150), point.y);//shift the window 150 pixels left
} else if (e.getSource() == colorButton) {
buttonPanel.setBackground(color.BLUE);
//sets the backgorund to Blue
} else {
leftButton.setAlignmentX(Component.CENTER_ALIGNMENT);
//sets the location to previous location
colorButton.setAlignmentX(Component.CENTER_ALIGNMENT);
resetButton.setAlignmentX(Component.CENTER_ALIGNMENT);
}
}
}
}
public static void main(String[] args) {
Buttons buttonwindow = new Buttons();
}
}
It has stopped compiling, because you deleted one accolade, so put one accolade "}" just above the method:
public static void main(String[] args)
and the code should compile. pls feedback.
EDIT:
Also rewrite your main method like this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Buttons buttonwindow = new Buttons();
}
}
);
}
Every usage of Swing components must be done thorugh the Event Dispatch Thread (abbreviated EDT) or you will probably get unwanted visual effects. See here for explanation.
EDIT^2:
To achieve the desired behavior, rewrite the the action listener like this:
if (e.getSource() == leftButton) {
((FlowLayout)buttonPanel.getLayout()).setAlignment(FlowLayout.LEFT); //1
buttonPanel.revalidate(); //2
}
else if (e.getSource() == colorButton) {
buttonPanel.setBackground(color.BLUE);
}
else {
((FlowLayout)buttonPanel.getLayout()).setAlignment(FlowLayout.CENTER);
buttonPanel.revalidate();
}
Any change to the visual appereance to the Swing component must be done through the assigned layout manager, in this case FlowLayout - in line 1.
To see the change you must notify the Swing components layout manager to rearrange the components - in line 2 the revalidate() method "notifies" the layout manager to recalculate the new positions and eventually "notifies" the EDT to draw it on the screen.
You should update the layout manager to align the components to the left or right. Try something like;
((FlowLayout)getLayout()).setAlignment(FlowLayout.LEFT);
Instead
You code won't compile as the static main method appears inside the inner class eventHandle. You can fix simply by moving it into the class body of the outer class Buttons.
As you have all the objects references at class level, you could do the button alignment using, for instance:
flt.setAlignment(FlowLayout.RIGHT);
buttonPanel.revalidate();
...
Here you are adjusting the layout alignment of your FlowLayout and revalidating to visually reflect the updated changes on your panel.