I'm trying to develop a simple game. The games is about the shapes. Shapes will move and we'll catch by mouse. I have already created a oval and given size of oval graphic. But I cannot move this shape repeatedly. I think I need to use timer class. I have been trying 2 hours myself but I didnt do yet.
The code;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class myshapestry extends JFrame implements ActionListener {
JFrame frame=new JFrame("Deneme");
Container l ;
private static int ballX=150;
private static int ballY=150;
myshapestry() {
l=this.getContentPane();
l.setLayout(null);
MyPanel panel=new MyPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.add(panel);
frame.setVisible(true);
frame.setSize(getPreferredSize());``
}
public Dimension getPreferredSize() {
return new Dimension(500,600);
}
public static void main (String args[]){
myshapestry tr=new myshapestry();
tr.setTitle("Game of Shapes");
}
private static class MyPanel extends JPanel {
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.fillOval(ballX, ballY,50 , 70);
}
public void actionPerformed(ActionEvent e){
ballX = ballX + 5;
ballY = ballY + 10;
repaint();
}
}
}
I was trying these code in the myshapestry code block;
Timer timer=new Timer(100,myshapestry);
t.start();
Add something like this
javax.swing.Timer timer=new javax.swing.Timer(100, panel) ;
timer.start();
Each 100msec the timer invokes actionPerformed() method of your MyPanel class
Related
I've been trying to create two layered images within a JFrame using JLayeredPane however I'm not able to draw a shape using the paint() function within the Canvas class.
Here is what I wrote:
package com.baduk.main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class Game extends Canvas implements Runnable {
private ImageIcon icon;
private JLabel back;
private JLayeredPane layer;
/**
*
*/
private static final long serialVersionUID = -3441156857004256039L;
public Game() {
//Background image with depth 0
icon = new ImageIcon("C:/Users/scaraven/Downloads/baduk_board.png");
back = new JLabel(icon);
back.setBounds(0,0,icon.getIconWidth(),icon.getIconHeight());
//Create JFrame
JFrame frame = new JFrame("BADUK");
frame.setSize(new Dimension(icon.getIconWidth()+5,icon.getIconHeight()+25));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
//Create JLayeredPane
layer = new JLayeredPane();
layer.add(back,new Integer(1));
layer.add(this,new Integer(0));
frame.setContentPane(layer);
frame.setVisible(true);
}
public static void main(String[] args) {
new Game();
}
#Override
public void run() {
// TODO Auto-generated method stub
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.fillRect(10, 10, 100, 100);
}
}
According to what I wrote, A Jframe should be generated with an image as the background and a black rectangle on top, however I only get the image. Does anyone know what is wrong with the code I wrote and what I need to change?
I created a Java gui that displays a circle with a JSlider that can be moved from left to right and changes the size of the circle. Everything runs with no errors. My issue is getting a JTextfield that would display the area, diameter, radius, etc.. of the circle and updates it when the JSlider is moved. I have one main class and two sub-classes. I didn't put the main since it's not important.
Here's what I have"
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
public class SliderFrame extends JFrame
{
private JSlider diameterJSlider;
private OvalPanel myPanel;
public SliderFrame()
{
super("Circle");
myPanel = new OvalPanel();
myPanel.setBackground(Color.WHITE);
diameterJSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 10);
diameterJSlider.setMajorTickSpacing(10);
diameterJSlider.setPaintTicks(true);
diameterJSlider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
myPanel.setDiameter(diameterJSlider.getValue());
}
}
);
add(diameterJSlider, BorderLayout.SOUTH);
add(myPanel, BorderLayout.CENTER);
}
}
import java.awt.Graphics;
import java.awt.Dimension;
import javax.swing.JPanel;
public class OvalPanel extends JPanel
{
private int diameter = 10;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawOval(30, 30, diameter, diameter);
}
public void setDiameter(int newDiameter)
{
diameter = (newDiameter >= 0 ? newDiameter: 10 );
repaint();
}
public Dimension getPreferredSize()
{
return new Dimension(200, 200);
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
}
I'm trying to make a simple game in java where you can move the player (Defender) in the 4 directions. I tried to make the key detecting with a key adapter, but it doesn't work. What could be the problem (I tried to do a System.out.println at the key press to make sure that the problem isn't at the Defender)?
Code:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class DefenderComponent extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private static final int WIDTH = 160;
private static final int HEIGHT = 120;
private static final int SCALE = 4;
Defender player = new Defender();
public DefenderComponent() {
Dimension size = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);
setMinimumSize(size);
setMaximumSize(size);
setPreferredSize(size);
addKeyListener(new TKeyListener());
Timer timer = new Timer(5, this);
timer.start();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Test2");
frame.add(new DefenderComponent());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setFocusable(true);
new DefenderComponent();
}
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
Image i = player.getImage();
g2d.drawImage(i, player.getX(), player.getY(), i.getWidth(this) * SCALE, i.getHeight(this) * SCALE, this);
}
public void actionPerformed(ActionEvent e) {
player.move();
repaint();
}
}
KeyEvents are only generated for the component that has focus. A JPanel is not focusable by default.
Don't use a KeyListener. Instead you should be using Key Bindings which are more flexible.
See Motion Using the Keyboard for more information and examples.
frame.addActionListener(this);
is what you missed.
that line says. this class is an ActionListener. please call this class when you receive an action.
if you want to add the ActionListener to the JPanel
public DefenderComponent() {
addActionListener(this);
....
}
I'm trying to build a simple paint tool. The mouseDrag events creates a new ellipse and causes my JPanel to repaint().
This works fine so far.
However, if I press any button (or any other UI component) before firing the mouseDrag event for the first time, the button is painted in the upper left corner of my panel.
I have isolated the code into this test application:
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test extends JFrame
{
public Test()
{
final JPanel paintPanel = new JPanel(){
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
g2d.setPaintMode();
g2d.setStroke(new BasicStroke(1));
g2d.fillRect(100, 100, 10, 10);
}
};
paintPanel.setPreferredSize(new Dimension(300,300));
paintPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e)
{
paintPanel.repaint();
}
});
this.setLayout(new FlowLayout());
this.add(paintPanel);
this.add(new JButton("Dummy"));
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String... args)
{
new Test();
}
}
A Screenshot for "seeing" the problem in my Main application
+1 to #MadProgrammer's answers.
You should have super.paintComponent(..) as the first call in your overriden paintComponent()
Do not extend JFrame unnecessarily
Create and minipulate Swing components via EDT
Dont call setPrefferedSize() rather override getPrefferedSize()
Here is an example which incorporates my advice's and #MadProgrammer's:
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
JFrame frame;
public Test() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final PaintPanel paintPanel = new PaintPanel();
paintPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
paintPanel.addRect(e.getX(), e.getY());
}
});
frame.setLayout(new FlowLayout());
frame.add(paintPanel);
frame.add(new JButton("Dummy"));
frame.pack();
frame.setVisible(true);
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
class PaintPanel extends JPanel {
public PaintPanel() {
addRect(100, 100);
}
ArrayList<Rectangle> rects = new ArrayList<>();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaintMode();
for (Rectangle r : rects) {
g2d.setStroke(new BasicStroke(1));
g2d.fillRect(r.x, r.y, r.width, r.height);
}
}
public void addRect(int x, int y) {
rects.add(new Rectangle(x, y, 10, 10));
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
You're not calling super.paintComponent.
The graphics context used for a paint cycle is shared between all the components begin painted, this means if you don't take care to clear it before painting onto, you will end up with what ever was painted before you.
One of the jobs of paintComponent is to prepare the graphics for painting
I am making a simple game using a JFrame. I have made a simple "Start" screen which basically consists of a String and a JButton. I am picking up the button click with the actionPerformed(ActionEvent e) method. I don't know how to change the cards using a button click. This may seem like a simple problem to solve, but the twist comes with this: My main JFrame, my StartScreen and my JPanel where the game takes place are all in separate files. My main file, Virus.java, is where I create the JFrame. My file VirusGamePanel.java is where the game takes place. My file StartScreen.java is the screen with the button. I want to change 'cards' to the game screen when the player clicks the button. How can I do this?
My StartScreen.java file:
package virus;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.CardLayout;
public class StartScreen extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
JButton start = new JButton("Start");
public StartScreen(){
start.addActionListener(this);
start.setBounds(new Rectangle(400,300,100,30));
this.add(start);
}
public void paint(Graphics g){
super.paint(g);
g.setFont(new Font("Impact",Font.BOLD,72));
g.setColor(Color.MAGENTA);
g.drawString("Virus",275,300);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==start)
{
//what to do here?
}
}
}
My Virus.java file:
package virus;
import javax.swing.*;
import java.awt.CardLayout;
import virus.StartScreen;
public class Virus extends JFrame{
private static final long serialVersionUID =1L;
JFrame jf = new JFrame("Virus");
static JPanel thegame = new JPanel(new CardLayout());
JPanel game = new VirusGamePanel();
JPanel start = new StartScreen();
public Virus(){
jf.setResizable(false);
jf.setSize(600,600);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(EXIT_ON_CLOSE);
jf.setVisible(true);
jf.add(thegame);
thegame.add(start);
thegame.add(game);
}
public static void main(String[] args) {
new Virus();
}
}
You simply have to right this in your actionPerformed(...) method :
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==start)
{
//what to do here?
CardLayout cardLayout = (CardLayout) Virus.thegame.getLayout();
cardLayout.next(Virus.thegame);
}
}
As very much pointed out by #kleopatra (THE EMPRESS) herself, don't override paint() instead do your painting stuff inside paintComponent(Graphics g) method of any JPanel/JComponent. Moreover, first add the components to your JFrame, once it's size is realized, then only set it to Visible, not before that. Instead of setting sizes for the JFrame simply override the JPanel's method getPreferredSize(), make it return some valid Dimension Object.
Do watch this sequence, as you write your code the next time :
public Virus(){
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setResizable(false);
thegame.add(start);
thegame.add(game);
jf.add(thegame);
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}
Here is your full code :
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.CardLayout;
public class Virus extends JFrame{
private static final long serialVersionUID =1L;
JFrame jf = new JFrame("Virus");
static JPanel thegame = new JPanel(new CardLayout());
JPanel game = new VirusGamePanel();
JPanel start = new StartScreen();
public Virus(){
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setResizable(false);
thegame.add(start);
thegame.add(game);
jf.add(thegame);
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}
public static void main(String[] args) {
new Virus();
}
}
class StartScreen extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
JButton start = new JButton("Start");
public StartScreen(){
start.addActionListener(this);
start.setBounds(new Rectangle(400,300,100,30));
this.add(start);
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setFont(new Font("Impact",Font.BOLD,72));
g.setColor(Color.MAGENTA);
g.drawString("Virus",275,300);
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(600, 600));
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==start)
{
//what to do here?
CardLayout cardLayout = (CardLayout) Virus.thegame.getLayout();
cardLayout.next(Virus.thegame);
}
}
}
class VirusGamePanel extends JPanel
{
public VirusGamePanel()
{
JLabel label = new JLabel("I am ON", JLabel.CENTER);
add(label);
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(600, 600));
}
}
Your StartScreen class has to have access to the instance of the CardLayout of the JFrame and the instance of the VirusGamePanel class. You can pass these instances in the constructor or a setLayout method and setVirusGamePanel method of your StartScreen class.
Something like:
layout.next(virusGamePanel);
should work.