Let me start off by saying I know I've violated some basic Java principles in this messy code, but I'm desperately trying to finish a program by Tuesday for a social science experiment, and I don't know Java, so I'm basically just fumbling through it for now.
With that disclaimer out of the way, I have a separate program working where a circle is moving around the screen and the user must click on it. It works fine when its in its own separate class file, but when I add the code to my main program, it's no longer working. I don't even really understand why repaint() calls my paint() function — as far as I'm concerned, it's magic, but I've noticed that repaint() calls paint() in my test program, but not in the more complicated actual program, and I assume that's why the circle is no longer painting on my program.
Entire code is below:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.io.FileReader;
import java.io.IOException;
import java.util.Calendar;
public class Reflexology1 extends JFrame{
private static final long serialVersionUID = -1295261024563143679L;
private Ellipse2D ball = new Ellipse2D.Double(0, 0, 25, 25);
private Timer moveBallTimer;
int _ballXpos, _ballYpos;
JButton button1, button2;
JButton movingButton;
JTextArea textArea1;
int buttonAClicked, buttonDClicked;
private long _openTime = 0;
private long _closeTime = 0;
JPanel thePanel = new JPanel();
JPanel thePlacebo = new JPanel();
final JFrame frame = new JFrame("Reflexology");
final JFrame frame2 = new JFrame("The Test");
JLabel label1 = new JLabel("Press X and then click the moving dot as fast as you can.");
public static void main(String[] args){
new Reflexology1();
}
public Reflexology1(){
frame.setSize(600, 475);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Reflexology 1.0");
frame.setResizable(false);
frame2.setSize(600, 475);
frame2.setLocationRelativeTo(null);
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.setTitle("Reflexology 1.0");
frame2.setResizable(false);
button1 = new JButton("Accept");
button2 = new JButton("Decline");
//movingButton = new JButton("Click Me");
ListenForAcceptButton lForAButton = new ListenForAcceptButton();
ListenForDeclineButton lForDButton = new ListenForDeclineButton();
button1.addActionListener(lForAButton);
button2.addActionListener(lForDButton);
//movingButton.addActionListener(lForMButton);
JTextArea textArea1 = new JTextArea(24, 50);
textArea1.setText("Tracking Events\n");
textArea1.setLineWrap(true);
textArea1.setWrapStyleWord(true);
textArea1.setSize(15, 50);
textArea1.setEditable(false);
FileReader reader = null;
try {
reader = new FileReader("EULA.txt");
textArea1.read(reader, "EULA.txt");
} catch (IOException exception) {
System.err.println("Problem loading file");
exception.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException exception) {
System.err.println("Error closing reader");
exception.printStackTrace();
}
}
}
JScrollPane scrollBar1 = new JScrollPane(textArea1, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
AdjustmentListener listener = new MyAdjustmentListener();
thePanel.add(scrollBar1);
thePanel.add(button1);
thePanel.add(button2);
frame.add(thePanel);
ListenForMouse lForMouse = new ListenForMouse();
thePlacebo.addMouseListener(lForMouse);
thePlacebo.add(label1);
frame2.add(thePlacebo);
ListenForWindow lForWindow = new ListenForWindow();
frame.addWindowListener(lForWindow);
frame2.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
if(e.getKeyChar() == 'X' || e.getKeyChar() == 'x') {moveBallTimer.start();}
}
});
frame.setVisible(true);
moveBallTimer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
moveBall();
System.out.println("Timer started!");
repaint();
}
});
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(frame2.isVisible()){ moveBallTimer.start(); }
}
});
}
private class ListenForAcceptButton implements ActionListener{
public void actionPerformed(ActionEvent e){
if (e.getSource() == button1){
Calendar ClCDateTime = Calendar.getInstance();
System.out.println(ClCDateTime.getTimeInMillis() - _openTime);
_closeTime = ClCDateTime.getTimeInMillis() - _openTime;
//frame.getContentPane().remove(thePanel);
//thePlacebo.addKeyListener(lForKeys);
//frame.getContentPane().add(thePlacebo);
//frame.repaint();
//moveBallTimer.start();
frame.setVisible(false);
frame2.setVisible(true);
frame2.revalidate();
frame2.repaint();
}
}
}
private class ListenForDeclineButton implements ActionListener{
public void actionPerformed(ActionEvent e){
if (e.getSource() == button2){
JOptionPane.showMessageDialog(Reflexology1.this, "You've declined the license agreement. DO NOT RESTART the program. Please go inform a researcher that you have declined the agreement.", "WARNING", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
}
private class ListenForWindow implements WindowListener{
public void windowActivated(WindowEvent e) {
//textArea1.append("Window is active");
}
// if this.dispose() is called, this is called:
public void windowClosed(WindowEvent arg0) {
}
// When a window is closed from a menu, this is called:
public void windowClosing(WindowEvent arg0) {
}
// Called when the window is no longer the active window:
public void windowDeactivated(WindowEvent arg0) {
//textArea1.append("Window is NOT active");
}
// Window gone from minimized to normal state
public void windowDeiconified(WindowEvent arg0) {
//textArea1.append("Window is in normal state");
}
// Window has been minimized
public void windowIconified(WindowEvent arg0) {
//textArea1.append("Window is minimized");
}
// Called when the Window is originally created
public void windowOpened(WindowEvent arg0) {
//textArea1.append("Let there be Window!");
Calendar OlCDateTime = Calendar.getInstance();
_openTime = OlCDateTime.getTimeInMillis();
//System.out.println(_openTime);
}
}
private class MyAdjustmentListener implements AdjustmentListener {
public void adjustmentValueChanged(AdjustmentEvent arg0) {
AdjustmentEvent scrollBar1;
//System.out.println(scrollBar1.getValue()));
}
}
public void paint(Graphics g) {
//super.paint(g);
frame2.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fill(ball);
System.out.println("Calling fill()");
}
protected void moveBall() {
//System.out.println("I'm in the moveBall() function!");
int width = getWidth();
int height = getHeight();
int min, max, randomX, randomY;
min =200;
max = -200;
randomX = min + (int)(Math.random() * ((max - min)+1));
randomY = min + (int)(Math.random() * ((max - min)+1));
//System.out.println(randomX + ", " + randomY);
Rectangle ballBounds = ball.getBounds();
//System.out.println(ballBounds.x + ", " + ballBounds.y);
if (ballBounds.x + randomX < 0) {
randomX = 200;
} else if (ballBounds.x + ballBounds.width + randomX > width) {
randomX = -200;
}
if (ballBounds.y + randomY < 0) {
randomY = 200;
} else if (ballBounds.y + ballBounds.height + randomY > height) {
randomY = -200;
}
ballBounds.x += randomX;
ballBounds.y += randomY;
_ballXpos = ballBounds.x;
_ballYpos = ballBounds.y;
ball.setFrame(ballBounds);
}
public void start() {
moveBallTimer.start();
}
public void stop() {
moveBallTimer.stop();
}
private class ListenForMouse implements MouseListener{
// Called when the mouse is clicked
public void mouseClicked(MouseEvent e) {
//System.out.println("Mouse Panel pos: " + e.getX() + " " + e.getY() + "\n");
if (e.getX() >=_ballXpos && e.getX() <= _ballXpos + 25 && e.getY() <=_ballYpos && e.getY() >= _ballYpos - 25 ) {
System.out.println("TRUE");
}
System.out.println("{e.getX(): " + e.getX() + " / " + "_ballXpos: " + _ballXpos + " | " + "{e.getY(): " + e.getY() + " / " + "_ballYpos: " + _ballYpos);
}
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
// System.out.println("e.getX(): " + e.getX() + " / " + "_ballXpos: " + _ballXpos);
// Mouse over
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
// Mouse left the mouseover area:
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
Could anyone tell me what I need to do to get repaint() to call the paint() method in the above program? I'm assuming the multiple frames is causing the problem, but that's just a guess. Thanks.
You should not paint directly on JFrame. JPanel or extension of JComponent should be used. For painting override paintComponent() rather than paint(). Don't forget to call super.paintComponent(g);.
Also, keep in mind that repaint() only schedules component update, it does not trigger immediate paint().
For more details see Performing Custom Painting and Painting in AWT and Swing.
For example you can apply the following changes. TestPanel will paint the ball.
class TestPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fill(ball);
}
}
Then, update thePlacebo panel:
JPanel thePlacebo = new TestPanel();
Add repaint in moveBall():
thePlacebo.repaint();
Here is an example based on original code:
package so;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.Random;
import javax.swing.*;
public class TestBall {
private static void createAndShowUI() {
final TestPanel panel = new TestPanel();
panel.validate();
JFrame frame = new JFrame("TestBall");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(300, 300));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
ActionListener timerAction = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
panel.moveBall();
}
};
Timer timer = new Timer(1000, timerAction);
timer.setRepeats(true);
timer.start();
}
static class TestPanel extends JPanel {
public static int BALL_SIZE = 25;
private Ellipse2D ball = new Ellipse2D.Double(0, 0, BALL_SIZE,
BALL_SIZE);
Random rand = new Random();
public TestPanel() {
this.addMouseListener(new MouseAdapter() {
// Called when the mouse is clicked
public void mouseClicked(MouseEvent e) {
if (ball.contains(e.getPoint())) {
System.out.println("hit the ball");
}
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fill(ball);
}
public void moveBall() {
Rectangle ballBounds = ball.getBounds();
ball.setFrame(ballBounds);
ballBounds.x = rand.nextInt(getWidth() - BALL_SIZE + 1) + 1;
ballBounds.y = rand.nextInt(getHeight() - BALL_SIZE + 1) + 1;
ball.setFrame(ballBounds);
repaint();
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Related
I am learning Java currently and have been given the assignmnet of finidhing off a program to create the game Conways's life (we started with some code provided to us and must add features etc to this).
I am currently stuck on a menu option for the game. I want it to start off at the menu screen, wherein buttons appear at the top for "Start", "Random", "Load", Save". I have written code so that the program displays these buttons, through a fillRect option in my paint method.
My question is, how do I use the mousePressed method to recognise the cells selected so that I can get an action to occur when they are selected. I been looking at this for a while but can't seem to get this working.
Any suggestion would be a massive help. I have shared my code below. It's a work in progress but I would really like to get this working before continuing on with the other functionality.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
public class ConwaysLife extends JFrame implements Runnable, MouseListener {
// member data
private BufferStrategy strategy;
private Graphics offscreenBuffer;
private boolean gameState[][] = new boolean[40][40];
private boolean isGameInProgress = false;
// constructor
public ConwaysLife () {
//Display the window, centred on the screen
Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = screensize.width/2 - 400;
int y = screensize.height/2 - 400;
setBounds(x, y, 800, 800);
setVisible(true);
this.setTitle("Conway's game of life");
// initialise double-buffering
createBufferStrategy(2);
strategy = getBufferStrategy();
offscreenBuffer = strategy.getDrawGraphics();
// register the Jframe itself to receive mouse events
addMouseListener(this);
// initialise the game state
for (x=0;x<40;x++) {
for (y=0;y<40;y++) {
gameState[x][y]=false;
}
}
// create and start our animation thread
Thread t = new Thread(this);
t.start();
}
// thread's entry point
public void run() {
while ( 1==1 ) {
// 1: sleep for 1/5 sec
try {
Thread.sleep(200);
} catch (InterruptedException e) { }
// 2: animate game objects [nothing yet!]
/*if (isGameInProgress == false) {
this.repaint();
}*/
// 3: force an application repaint
this.repaint();
}
}
// mouse events which must be implemented for MouseListener
public void mousePressed(MouseEvent e) {
while (!isGameInProgress) {
int x = e.getX()/20;
int y = e.getY()/20;
if(x >= 10 && x <= 80 && y >= 40 && y <= 65) {
isGameInProgress = !isGameInProgress;
this.repaint();
}
}
// determine which cell of the gameState array was clicked on
int x = e.getX()/20;
int y = e.getY()/20;
// toggle the state of the cell
gameState[x][y] = !gameState[x][y];
// request an extra repaint, to get immediate visual feedback
this.repaint();
}
public void mouseReleased(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseClicked(MouseEvent e) { }
//
// application's paint method
public void paint(Graphics g) {
Font font = new Font("Veranda", Font.BOLD, 20);
g = offscreenBuffer; // draw to off screen buffer
// clear the canvas with a big black rectangle
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 800);
/*look to add a while game in progress loop here!!!*/
// draw menu options
if(!isGameInProgress) {
g.setColor(Color.green);
g.fillRect(10, 40, 70, 25);
g.fillRect(100, 40, 100, 25);
g.fillRect(300, 40, 170, 25);
g.setColor(Color.BLACK);
g.setFont(font);
g.drawString("Start", 15, 60);
g.drawString("Random", 105, 60);
g.drawString("Load", 305, 60);
g.drawString("Save", 395, 60);
}
// redraw all game objects
g.setColor(Color.WHITE);
for (int x=0;x<40;x++) {
for (int y=0;y<40;y++) {
if (gameState[x][y]) {
g.fillRect(x*20, y*20, 20, 20);
}
}
}
// flip the buffers
strategy.show();
}
// application entry point
public static void main(String[] args) {
ConwaysLife w = new ConwaysLife();
}
}
You're not going to like the answer, but it's the "correct" way to approach the problem.
What you need to understand is, Swing/AWT is using a "passive" rendering workflow and BufferStrategy is using a "active" rendering workflow, these are incompatible with each other.
As a general rule, you should not be overriding paint of top level containers like JFrame, this is going to end in no end of issues. Instead, you should be starting with something like JPanel and overriding it's paintComponent method instead.
Having said that, there's a "simpler" solution available to you. CardLayout. This will allow you to seperate the workflows of the menu from the game and resolve the issue between Swing/AWT and BufferStrategy
For example...
import java.awt.Canvas;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferStrategy;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public final class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
enum View {
MENU, GAME;
}
private CardLayout cardLayout = new CardLayout();
private GamePane gamePane;
public MainPane() {
setLayout(cardLayout);
gamePane = new GamePane();
add(new MenuPane(new MenuPane.Observer() {
#Override
public void startNewGame() {
showGame();
}
#Override
public void randomGame() {
}
#Override
public void loadGame() {
}
#Override
public void saveGame() {
}
}), View.MENU);
add(gamePane, View.GAME);
}
protected void add(Component compent, View view) {
add(compent, view.name());
}
protected void showGame() {
show(View.GAME);
gamePane.start();
}
protected void showMenu() {
gamePane.stop();
show(View.MENU);
}
protected void show(View view) {
cardLayout.show(this, view.name());
}
}
public class MenuPane extends JPanel {
public interface Observer {
public void startNewGame();
public void randomGame();
public void loadGame();
public void saveGame();
}
private Observer observer;
public MenuPane(Observer observer) {
this.observer = observer;
JButton startButton = new JButton("Start");
JButton randomButton = new JButton("Random");
JButton loadButton = new JButton("Load");
JButton saveButton = new JButton("Save");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.ipadx = 10;
gbc.ipady = 10;
gbc.insets = new Insets(8, 8, 8, 8);
gbc.weightx = GridBagConstraints.REMAINDER;
add(startButton, gbc);
add(randomButton, gbc);
add(loadButton, gbc);
add(saveButton, gbc);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.startNewGame();
}
});
randomButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.randomGame();
}
});
loadButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.loadGame();
}
});
saveButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.saveGame();
}
});
}
}
public class GamePane extends Canvas {
private Thread thread;
private volatile boolean isRunning = false;
public GamePane() {
setBackground(Color.BLACK);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
protected void start() {
if (isRunning) {
return;
}
createBufferStrategy(3);
isRunning = true;
thread = new Thread(new Runnable() {
#Override
public void run() {
mainLoop();
}
});
thread.start();
}
protected void stop() {
if (!isRunning || thread == null) {
return;
}
isRunning = false;
try {
thread.join();
} catch (InterruptedException ex) {
}
thread = null;
}
protected void mainLoop() {
try {
while (isRunning) {
render();
Thread.sleep(16);
}
} catch (InterruptedException ex) {
}
}
protected void render() {
BufferStrategy strategy = getBufferStrategy();
if (strategy == null) {
return;
}
// Render single frame
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics graphics = strategy.getDrawGraphics();
FontMetrics fm = graphics.getFontMetrics();
String text = "All your game are belong to us";
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = (getHeight() - fm.getHeight()) / 2;
graphics.setColor(Color.WHITE);
graphics.drawString(text, x, y + fm.getAscent());
// Render to graphics
// ...
// Dispose the graphics
graphics.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());
}
}
}
I would strongly recommend that you take the time to read through:
Creating a GUI With Swing
A Visual Guide to Layout Managers
Performing Custom Painting
Painting in AWT and Swing
BufferStrategy and BufferCapabilities
JavaDocs for BufferStrategy which demonstrate how the API should be used.
A "fully" BufferStrategy based approach...
Now, if you can't use Swing, "for reasons", you can still achieve a simular concept using "delegation".
Basically this means "delegating" responsibility for performing some workflow to another. In this case, we want to delegate the rendering and the handling of the mouse events.
This allows you to have a dedicated workflow for the menu and a dedicated workflow for the game, without having to try and mix a lot of state.
Why do I keep on insisting on separating these two workflows? Simply, because it makes it MUCH easier to manage and reason about, but also because it supports the Single Responsibility Principle.
The follow example makes use of Renderable interface to define the core functionality that end "render" delegate will need to implement, in this case, it's pretty simple, we want to tell the renderer to "render" it's content on each paint pass and we want to (optionally) delegate mouse clicked events (this could be done via a second interface or even just the MouseListener interface directly, but I've made it a requirement of the Renderable interface for demonstration purposes.
The "basic" solution to your actual question is found through the use of Rectangle#contains(Point).
This basically inspects each "button" Rectangle to determine if the supplied MouseEvent occurs within it's bounds, if it does, we take action.
It is, however, a little more complicated then that, as we need to have the Rectangles built ahead of time, not difficult, but it's state which is actually reliant on the parent, as we need to know the area in which the renderer is been displayed, run the example, you'll see what I mean 😉
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public final class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MainPane mainPane = new MainPane();
JFrame frame = new JFrame();
frame.add(mainPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
mainPane.start();
}
});
}
public interface Renderable {
public void render(Graphics2D g2d, Dimension size);
// We could just extend from MouseListener
// but I don't need all those event handlers
public void mouseClicked(MouseEvent e);
}
public class MainPane extends Canvas {
private Thread thread;
private volatile boolean isRunning = false;
private Renderable currentRenderer;
private MenuRenderer menuRenderer;
private GameRenderer gameRenderer;
public MainPane() {
setBackground(Color.BLACK);
gameRenderer = new GameRenderer();
menuRenderer = new MenuRenderer(new MenuRenderer.Observer() {
#Override
public void startNewGame() {
showGame();
}
#Override
public void randomGame() {
}
#Override
public void loadGame() {
}
#Override
public void saveGame() {
}
});
showMenu();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (currentRenderer == null) {
return;
}
currentRenderer.mouseClicked(e);
}
});
}
protected void showMenu() {
// This may need to tell the game renderer to stop
// or pause
currentRenderer = menuRenderer;
}
protected void showGame() {
currentRenderer = gameRenderer;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
protected void start() {
if (isRunning) {
return;
}
createBufferStrategy(3);
isRunning = true;
thread = new Thread(new Runnable() {
#Override
public void run() {
mainLoop();
}
});
thread.start();
}
protected void stop() {
if (!isRunning || thread == null) {
return;
}
isRunning = false;
try {
thread.join();
} catch (InterruptedException ex) {
}
thread = null;
}
protected void mainLoop() {
try {
while (isRunning) {
render();
Thread.sleep(16);
}
} catch (InterruptedException ex) {
}
}
protected void render() {
BufferStrategy strategy = getBufferStrategy();
if (strategy == null && currentRenderer != null) {
return;
}
// Render single frame
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
g2d.setBackground(Color.BLACK);
g2d.fillRect(0, 0, getWidth(), getHeight());
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setRenderingHints(hints);
// Render to graphics
currentRenderer.render(g2d, getSize());
// Dispose the graphics
g2d.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());
}
}
public class GameRenderer implements Renderable {
#Override
public void render(Graphics2D g2d, Dimension size) {
FontMetrics fm = g2d.getFontMetrics();
String text = "All your game are belong to us";
int x = (size.width - fm.stringWidth(text)) / 2;
int y = (size.height - fm.getHeight()) / 2;
g2d.setColor(Color.WHITE);
g2d.drawString(text, x, y + fm.getAscent());
}
#Override
public void mouseClicked(MouseEvent e) {
}
}
public class MenuRenderer implements Renderable {
public interface Observer {
public void startNewGame();
public void randomGame();
public void loadGame();
public void saveGame();
}
private Observer observer;
private String[] menuOptions = new String[]{
"New Game",
"Random",
"Load Game",
"Save Game"
};
private Rectangle[] menuBounds;
private int internalPadding = 20;
private int horizontalGap = 16;
public MenuRenderer(Observer observer) {
this.observer = observer;
}
#Override
public void render(Graphics2D g2d, Dimension size) {
if (menuBounds == null) {
createMenus(g2d, size);
}
renderMenus(g2d);
}
protected void createMenus(Graphics2D g2d, Dimension size) {
FontMetrics fm = g2d.getFontMetrics();
int totalHeight = (((fm.getHeight() + internalPadding) + horizontalGap) * menuOptions.length) - horizontalGap;
int buttonHeight = fm.getHeight() + internalPadding;
menuBounds = new Rectangle[menuOptions.length];
int buttonWidth = 0;
for (int index = 0; index < menuOptions.length; index++) {
int width = fm.stringWidth(menuOptions[index]) + internalPadding;
buttonWidth = Math.max(width, buttonWidth);
}
int yPos = (size.height - totalHeight) / 2;
for (int index = 0; index < menuOptions.length; index++) {
int xPos = (size.width - buttonWidth) / 2;
Rectangle menuRectangle = new Rectangle(xPos, yPos, buttonWidth, buttonHeight);
menuBounds[index] = menuRectangle;
yPos += buttonHeight + (horizontalGap / 2);
}
}
protected void renderMenus(Graphics2D g2d) {
for (int index = 0; index < menuOptions.length; index++) {
String text = menuOptions[index];
Rectangle bounds = menuBounds[index];
renderMenu(g2d, text, bounds);
}
}
protected void renderMenu(Graphics2D g2d, String text, Rectangle bounds) {
FontMetrics fm = g2d.getFontMetrics();
int textWidth = fm.stringWidth(text);
int textXPos = (bounds.x + (internalPadding / 2)) + ((bounds.width - internalPadding - textWidth) / 2);
int textYPos = bounds.y + (internalPadding / 2);
RoundRectangle2D buttonBackground = new RoundRectangle2D.Double(bounds.x, bounds.y, bounds.width, bounds.height, 20, 20);
g2d.setColor(Color.BLUE.darker());
g2d.fill(buttonBackground);
g2d.setColor(Color.WHITE);
g2d.drawString(text, textXPos, textYPos + fm.getAscent());
}
#Override
public void mouseClicked(MouseEvent e) {
if (menuBounds == null) {
return;
}
for (int index = 0; index < menuOptions.length; index++) {
if (menuBounds[index].contains(e.getPoint())) {
switch (index) {
case 0:
observer.startNewGame();
break;
case 2:
observer.randomGame();
break;
case 3:
observer.loadGame();
break;
case 4:
observer.saveGame();
break;
}
}
}
}
}
}
I'm currently coding a game and I'm trying to have it where if you click on the first button on the front page, it shows a transition screen for 5 seconds, and then shows the game. Here is my code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ForgottenMain extends JPanel implements KeyListener,MouseListener{
/**
*
*/
private static final int TIMER_DELAY = 35;
private static final long serialVersionUID = -4926251405849574401L;
public static BufferedImage attic,flashlight,player,killer,frontpage,transition;
public static boolean onFrontPage,up,down,left,right,inAttic,onTransition;
public static int px,py,kx,ky;
public static Thread th1,th2;
public static JFrame frame = new JFrame("Forgotten");
public static void main(String[] args){
onFrontPage = true;
px = 600;
py = 400;
ForgottenMain fm = new ForgottenMain();
frame.add(fm);
frame.setSize(1200,800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
frame.add(new ForgottenMain());
fm.repaint();
}
public ForgottenMain(){
init();
}
public void init(){
setSize(1200,800);
setVisible(true);
frame.addKeyListener(this);
frame.addMouseListener(this);
try{
player = ImageIO.read(new File("char.png"));
flashlight = ImageIO.read(new File("flashlightimage.png"));
attic = ImageIO.read(new File("attic.png"));
killer = ImageIO.read(new File("killer.png"));
frontpage = ImageIO.read(new File("frontpageoutline.png"));
transition = ImageIO.read(new File("transitionoutline.png"));
} catch (Exception e){
e.printStackTrace();
}
// Gameloop
new javax.swing.Timer(TIMER_DELAY, new ActionListener() {
public void actionPerformed(ActionEvent e) {
gameLoop();
}
}).start();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int fx = px - 1033;
int fy = py - 635;
kx = 500;
ky = 500;
// Removes the flickering of the images
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Resets the screen to make sure that it only shows the character once
g2.clearRect(0, 0, 1200, 800);
// Draws the background attic
if(inAttic == true){
System.out.println("Drawing attic");
g2.drawImage(attic,0,0,this);
}
if(onFrontPage == true){
g2.drawImage(frontpage, 0, 0, this);
}
// Draws the player
if(onFrontPage == false && onTransition == false){
g2.drawImage(player, px, py, this);
// Draws the Serial Killer
g2.drawImage(killer, kx, ky, this);
// Draws the flashlight
g2.drawImage(flashlight, fx, fy, this);
}
if(onTransition == true){
g2.drawImage(transition, 0, 0, this);
System.out.println("Drawing Transition");
try {
System.out.println("Sleeping for 5 Seconds");
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Done sleeping.");
onTransition = false;
inAttic = true;
}
System.out.println(px + " " + py);
}
public void gameLoop(){
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("MouseLocation: " + arg0.getX() + ", " + arg0.getY());
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent e) {
if(e.getX() > 499 && e.getY() > 343 && e.getX() < 748 && e.getY() < 391){
onFrontPage = false;
onTransition = true;
repaint();
}
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
My problem is, in the paint method, in the if statement testing if onTransition is equal to true, it's supposed to draw the image transition, wait 5 seconds, and then draw the game.
However, right now it's waiting 5 seconds, then quickly drawing the transition screen and then the game. For some reason they are out of order.
How can I fix this? I have tried alternate methods of waiting 5 seconds, for example using currentTimeMillis();, but have the same outcome.
You have some serious problems:
you add panels twice
you have some circuitous use of frame etc
Beyond that the following will work: you have to realize that you don't have control of the painting process. Therefore you should launch a new thread to count the sleep and let the paint do its work uninhibited.
(Also I have removed static - if you really want them you can try to put them back in - if it doesnt work you just throw them out)
class F extends JPanel implements MouseListener{
/**
*
*/
private static final int TIMER_DELAY = 35;
private static final long serialVersionUID = -4926251405849574401L;
public BufferedImage attic,flashlight,player,killer,frontpage,transition;
public boolean onFrontPage,up,down,left,right,inAttic,onTransition;
public int px,py,kx,ky;
public static Thread th1,th2;
public JFrame frame = new JFrame("Forgotten");
public F(){
init();
}
public void init(){
setSize(1200,800);
setVisible(true);
onFrontPage = true;
px = 600;
py = 400;
frame.add(this);
frame.setSize(1200,800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
frame.addMouseListener(this);
try{
// player = ImageIO.read(new File("char.png"));
// flashlight = ImageIO.read(new File("flashlightimage.png"));
// attic = ImageIO.read(new File("attic.png"));
// killer = ImageIO.read(new File("killer.png"));
attic = ImageIO.read(new File(...));
frontpage = ImageIO.read(new File(...));
transition = ImageIO.read(new File(...));
} catch (Exception e){
e.printStackTrace();
}
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int fx = px - 1033;
int fy = py - 635;
kx = 500;
ky = 500;
// Removes the flickering of the images
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Resets the screen to make sure that it only shows the character once
g2.clearRect(0, 0, 1200, 800);
// Draws the background attic
if(inAttic == true){
System.out.println("Drawing attic"+System.currentTimeMillis());
g2.drawImage(attic,0,0,this);
}
if(onFrontPage == true){
g2.drawImage(frontpage, 0, 0, this);
}
// Draws the player
if(onFrontPage == false && onTransition == false){
g2.drawImage(player, px, py, this);
// Draws the Serial Killer
g2.drawImage(killer, kx, ky, this);
// Draws the flashlight
g2.drawImage(flashlight, fx, fy, this);
}
if(onTransition == true){
Graphics gt=transition.getGraphics();
gt.setColor(Color.red);
gt.drawString("xxx"+System.currentTimeMillis(), 10, 100);
g2.drawImage(transition, 0, 0, this);
onTransition = false;
inAttic = true;
}
System.out.println(px + " " + py);
}
public void gameLoop(){
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("MouseLocation: " + arg0.getX() + ", " + arg0.getY());
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent e) {
onFrontPage = false;
onTransition = true;
Thread th=new Thread() {
public void run() {
repaint();
System.out.println("Drawing Transition"+System.currentTimeMillis());
try {
System.out.println("Sleeping for 5 Seconds"+System.currentTimeMillis());
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Done sleeping."+System.currentTimeMillis());
repaint();
}
};
th.start();
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
I am trying to paint a line when my variable readyToDraw is TRUE by using an if... statement in class's Paint method paintComponent() . I guess I'm doing something wrong because the line never gets painted. How do I fix this? Is there a way to call paintComponent() from another method?
Full code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.Graphics2D;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.SwingWorker;
import javax.swing.border.LineBorder;
import javax.swing.AbstractAction;
import javax.swing.Action;
public class MainFrame {
public int x1, x2, y1, y2;
private boolean readyToDraw = false;
private int clickCount = 0;
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame window = new MainFrame();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainFrame() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 600);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(Color.WHITE);
buttonPanel.setBorder(new LineBorder(new Color(0, 0, 0), 2, true));
buttonPanel.setBounds(10, 11, 100, 85);
frame.getContentPane().add(buttonPanel);
buttonPanel.setLayout(null);
JPanel paint = new Paint();
frame.getContentPane().add(paint);
JButton btnLine = new JButton("Line");
btnLine.setBackground(Color.LIGHT_GRAY);
btnLine.setBounds(4, 4, 92, 25);
btnLine.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
if (readyToDraw == true) {
System.out.println("Let's draw!");
}
else {
}
System.out.println("Line");
}
});
JButton btnRectangle = new JButton("Rectangle");
btnRectangle.setBackground(Color.LIGHT_GRAY);
btnRectangle.setBounds(4, 30, 92, 25);
btnRectangle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
if (readyToDraw == true) {
System.out.println("Let's draw!");
}
else {
}
System.out.println("Rectangle");
}
});
JButton btnCircle = new JButton("Circle");
btnCircle.setBackground(Color.LIGHT_GRAY);
btnCircle.setBounds(4, 56, 92, 25);
btnCircle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
if (readyToDraw == true) {
System.out.println("Let's draw!");
}
else {
}
System.out.println("Circle");
}
});
buttonPanel.add(btnLine);
buttonPanel.add(btnRectangle);
buttonPanel.add(btnCircle);
}
private class Paint extends JPanel implements MouseListener {
public Paint() {
this.setBackground(Color.WHITE);
this.setBounds(120, 11, 664, 550);
this.addMouseListener(this);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g);
//if (readyToDraw) {
g2.setStroke(new BasicStroke(4));
g2.setColor(Color.BLACK);
g2.drawLine(x1, y1, x2, y2);
//}
}
#Override
public void mouseEntered(MouseEvent arg0) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage("cursor.png");
Point hotSpot = new Point(15, 15);
Cursor cursor = toolkit.createCustomCursor(image, hotSpot, "Dot");
this.setCursor(cursor);
}
#Override
public void mouseExited(MouseEvent arg0) {
Cursor dotCursor = new Cursor(Cursor.DEFAULT_CURSOR);
this.setCursor(dotCursor);
}
public void mouseClicked(MouseEvent e) {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
if (clickCount == 0) {
x1 = e.getX();
y1 = e.getY();
clickCount++;
} else if (clickCount == 1) {
x2 = e.getX();
y2 = e.getY();
clickCount++;
readyToDraw = true;
} else {
clickCount = 0;
readyToDraw = false;
repaint();
}
System.out.println(x1 + " " + y1 + " " + clickCount + " " + x2
+ " " + y2 + readyToDraw);
}
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
}
public class Screen extends Canvas implements Runnable {
private static final int MAX_FPS = 60;
private static final int FPS_SAMPLE_SIZE = 6;
private boolean[] keysPressed = new boolean[256];
private ArrayList<Character> characters = new ArrayList<>();
private ArrayList<Character> ai = new ArrayList<>();
private Thread thread;
private BufferedImage bg;
//for testing putposes
private Player slime = new Player("Slime.png", 100, 100);
private Player bird = new Player("Bird.png", 250, 250);
private Player giant = new Player("Giant.png", 250, 500);
private Player swordsman = new Player("Swordsman.png", 500, 250);
//screen dimensions
private int height = ((Toolkit.getDefaultToolkit().getScreenSize().height-32)/5*4);
private int width = Toolkit.getDefaultToolkit().getScreenSize().width;
private long prevTick = -1;
private LinkedList<Long> frames = new LinkedList<>();
private int averageFPS;
private boolean running;
public Screen() {
setSize(width, height);
try {bg = ImageIO.read(new File("GUI Images/success.jpg"));}
catch (Exception e) {Utilities.showErrorMessage(this, e);}
characters.add(slime);
// ai.add(bird);
//ai.add(giant);
// ai.add(swordsman);
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {keysPressed[e.getKeyCode()] = true;}
public void keyReleased(KeyEvent e) {keysPressed[e.getKeyCode()] = false;}
public void keyTyped(KeyEvent e) {}
});
addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
});
addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
});
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {}
});
setVisible(true);
start();
}
public void paint(Graphics g){
BufferStrategy bs = getBufferStrategy();
if(getBufferStrategy() == null){
createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.drawImage(bg,0,0,width,height, null);
g.drawString(String.valueOf(averageFPS), 0, 0);
for (Character character : ai){
character.setY(character.getY() + (int)(Math.random() * 10 - 5));
character.setX(character.getX() + (int)(Math.random() * 10 - 5));
}
for (Character character : ai) {g.drawImage(character.getImage(), character.getX(), character.getY(), null);}
for (Character character : characters) {g.drawImage(character.getImage(), character.getX(), character.getY(), null);}
g.dispose();
bs.show();
}
public void run() {
while (running) {
tick();
repaint();
}
}
public synchronized void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
try {thread.join();}
catch (InterruptedException e) {Utilities.showErrorMessage(this, e);}
}
public void tick() {
if (keysPressed[KeyEvent.VK_W] && (slime.getY() > 0)) {slime.setY(slime.getY() - 1);}
if (keysPressed[KeyEvent.VK_S] && (slime.getY() < height)) {slime.setY(slime.getY() + 1);}
if (keysPressed[KeyEvent.VK_A] && (slime.getY() > 0)) {slime.setX(slime.getX() - 1);}
if (keysPressed[KeyEvent.VK_D] && (slime.getY() < width)) {slime.setX(slime.getX() + 1);}
// System.out.println(slime.getX() + ", " + slime.getY());
long pastTime = System.currentTimeMillis() - prevTick;
prevTick = System.currentTimeMillis();
if (frames.size() == FPS_SAMPLE_SIZE) {
frames.remove();
}
frames.add(pastTime);
// Calculate average FPS
long sum = 0;
for (long frame : frames) {
sum += frame;
}
long averageFrame = sum / FPS_SAMPLE_SIZE;
averageFPS = (int)(1000 / averageFrame);
// Only if the time passed since the previous tick is less than one
// second divided by the number of maximum FPS allowed do we delay
// ourselves to give Time time to catch up to our rendering.
if (pastTime < 1000.0 / MAX_FPS) {
try {
Thread.sleep((1000 / MAX_FPS) - pastTime);
System.out.println(averageFPS);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
There's my code, essentially this is just test code for the screen to see if I can properly paint objects to the screen, but there's erratic white frames that keep getting painted. They don't seem to be caused by any sort of input in particular, they just happen seemingly randomly during frame refreshes. Any ideas as to what it might be?
Don't override paint and use a BufferStrategy within it. Painting is usually done on a need to do bases (AKA "passive" rendering). BufferStrategy is a "active" rendering approach, where you take control of the paint process and update the buffer directly, the two don't tend to play well together
Take the logic from the current paint method and place it within your game loop.
This will require you to remove your call to start within the constructor, as the component won't have been added to a valid native peer (a component which is displayed on the screen).
Instead, create an instance of Screen, add it to your frame and then call start, for example...
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestScreen {
public static void main(String[] args) {
new TestScreen();
}
public TestScreen() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Frame frame = new Frame("Testing");
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Screen screen = new Screen();
frame.add(screen);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
screen.start();
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class Screen extends Canvas implements Runnable {
private static final int MAX_FPS = 60;
private static final int FPS_SAMPLE_SIZE = 6;
private boolean[] keysPressed = new boolean[256];
private ArrayList<Character> characters = new ArrayList<>();
private ArrayList<Character> ai = new ArrayList<>();
private Thread thread;
private BufferedImage bg;
private long prevTick = -1;
private LinkedList<Long> frames = new LinkedList<>();
private int averageFPS;
private boolean running;
public Screen() {
try {
bg = ImageIO.read(new File("GUI Images/success.jpg"));
} catch (Exception e) {
e.printStackTrace();
}
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
keysPressed[e.getKeyCode()] = true;
}
public void keyReleased(KeyEvent e) {
keysPressed[e.getKeyCode()] = false;
}
public void keyTyped(KeyEvent e) {
}
});
addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
});
addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
});
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
}
});
}
#Override
public Dimension getPreferredSize() {
int height = ((Toolkit.getDefaultToolkit().getScreenSize().height - 32) / 5 * 4);
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
return new Dimension(width, height);
}
public void run() {
createBufferStrategy(3);
BufferStrategy bs = null;
while (running) {
bs = getBufferStrategy();
Graphics g = bs.getDrawGraphics();
g.drawImage(bg, 0, 0, getWidth(), getHeight(), null);
FontMetrics fm = g.getFontMetrics();
g.setColor(Color.RED);
g.drawString(String.valueOf(averageFPS), 0, fm.getAscent());
g.dispose();
bs.show();
tick();
}
}
public synchronized void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void tick() {
// if (keysPressed[KeyEvent.VK_W] && (slime.getY() > 0)) {
// slime.setY(slime.getY() - 1);
// }
// if (keysPressed[KeyEvent.VK_S] && (slime.getY() < height)) {
// slime.setY(slime.getY() + 1);
// }
// if (keysPressed[KeyEvent.VK_A] && (slime.getY() > 0)) {
// slime.setX(slime.getX() - 1);
// }
// if (keysPressed[KeyEvent.VK_D] && (slime.getY() < width)) {
// slime.setX(slime.getX() + 1);
// }
// // System.out.println(slime.getX() + ", " + slime.getY());
long pastTime = System.currentTimeMillis() - prevTick;
prevTick = System.currentTimeMillis();
if (frames.size() == FPS_SAMPLE_SIZE) {
frames.remove();
}
frames.add(pastTime);
// Calculate average FPS
long sum = 0;
for (long frame : frames) {
sum += frame;
}
long averageFrame = sum / FPS_SAMPLE_SIZE;
averageFPS = (int) (1000 / averageFrame);
// Only if the time passed since the previous tick is less than one
// second divided by the number of maximum FPS allowed do we delay
// ourselves to give Time time to catch up to our rendering.
if (pastTime < 1000.0 / MAX_FPS) {
try {
Thread.sleep((1000 / MAX_FPS) - pastTime);
System.out.println(averageFPS);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
}
I tried to draw a simple rectangle on a JPanel wich is on a JFrame, but it didn't work. Can someone please give me some advices? Would be happy if someone could... I really tried hard, but I couldn figure out how to do this. This code is part of my "Snake" -program. All the rest works, in excep of this. Here is my Code:
package initialising_Package;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Initialising extends JPanel implements WindowListener,
ItemListener, ChangeListener, Runnable {
/**
* #param args
*/
private String name;
private JFrame frame;
private boolean fall = false;
private JSlider slider;
private JLabel lbl1, lbl2, lbl3, lbl4;
private JComboBox box1, box2, box3;
private String[] positionsx, positionsy, laenge;
private JPanel pnl1, pnl2, pnl3, pnlpnl;
private JButton btn;
private int beginningLenght, posX, posY;
private boolean start = false;
public Initialising() {
initStartFrame("Initialising");
}
public void initStartFrame(String name) {
frame = new JFrame(name);
frame.setLocation(300, 300);
frame.setSize(500, 350);
frame.setUndecorated(false);
frame.getContentPane().setLayout(new GridLayout(5, 1));
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setVisible(true);
frame.addWindowListener(this);
// GUI
slider = new JSlider(1, 100, 50);
slider.addChangeListener(this);
slider.setPaintTicks(false);
slider.setPaintTrack(true);
positionsx = new String[50];
positionsy = new String[50];
for (int i = 0, j = 0; i < 50; i++, j = j + 10) {
positionsx[i] = new String("" + j);
positionsy[i] = new String("" + j);
}
laenge = new String[45];
for (int i = 0; i < 45; i++) {
laenge[i] = "" + (i + 1);
}
box1 = new JComboBox(positionsx);
box1.addItemListener(this);
box2 = new JComboBox(positionsy);
box2.addItemListener(this);
box3 = new JComboBox(laenge);
box3.addItemListener(this);
lbl1 = new JLabel("Geschwindigkeit: ");
lbl2 = new JLabel("Startlaenge: ");
lbl3 = new JLabel("Position: ");
pnlpnl = new JPanel();
pnlpnl.setPreferredSize(new Dimension(95, 490));
pnlpnl.setBackground(Color.BLACK);
pnl1 = new JPanel();
pnl1.setLayout(new GridLayout(1, 2));
pnl2 = new JPanel();
pnl2.setLayout(new GridLayout(1, 2));
pnl3 = new JPanel();
pnl3.setLayout(new GridLayout(1, 3));
btn = new JButton("Snake!");
btn.setPreferredSize(new Dimension(80, 490));
pnl1.add(lbl1);
pnl1.add(slider);
pnl2.add(lbl2);
pnl2.add(box3);
pnl3.add(lbl3);
pnl3.add(box1);
pnl3.add(box2);
frame.add(pnlpnl);
frame.add(pnl1);
frame.add(pnl2);
frame.add(pnl3);
frame.add(btn);
// GUI
frame.validate();
frame.repaint();
}
public int getSpeed() {
return slider.getValue();
}
public int getBeginningLenght() {
return beginningLenght;
}
public int getPosX() {
return posX;
}
public int getPosY() {
return posY;
}
#Override
public void windowActivated(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowClosed(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowClosing(WindowEvent arg0) {
int z = JOptionPane.showConfirmDialog(frame,
"Willst du wirklich benden?", "Warnung", 0);
if (z == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
#Override
public void windowDeactivated(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowDeiconified(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowIconified(WindowEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void windowOpened(WindowEvent arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Initialising init = new Initialising();
new Thread(init).start();
}
#Override
public void itemStateChanged(ItemEvent e) {
// TODO Auto-generated method stub
if (e.getSource().equals(box1)) {
posX = Integer.parseInt((String) box1.getSelectedItem());
System.out.println("PosX: " + posX);
} else if (e.getSource().equals(box2)) {
posY = Integer.parseInt((String) box2.getSelectedItem());
System.out.println("PosY: " + posY);
} else if (e.getSource().equals(box3)) {
beginningLenght = Integer.parseInt((String) box3.getSelectedItem());
System.out.println("Beginning Lenght: " + beginningLenght);
System.out.println("H: " + pnlpnl.getHeight() + " B: "
+ pnlpnl.getWidth());
}
}
#Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
if (e.getSource().equals(slider)) {
System.out.println("Speed: " + slider.getValue());
}
}
#Override
public void paintComponent(Graphics gr) {
super.paint(gr);
gr.setColor(Color.CYAN);
gr.fillRect(0, 0, 200, 200);
}
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
System.out.println("It works!!");
try {
Thread.sleep(800);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!start) {
}
repaint();
validate();
}
}
}
Remove the paintComponent from the JFrame. That did also call super.paint i.o. super.paintComponent.
pnlpnl = new JPanel() {
#Override
public void paintComponent(Graphics gr) {
super.paintComponent(gr);
gr.setColor(Color.CYAN);
gr.fillRect(0, 0, 200, 200);
}
};
In this paintComponent you can use the JFrame's fields.
As initStartFrame is called in the constructor it should not be overridable (the child class's version then would be called, without the child class being entirely initialized).
//Sometimes: public final void initStartFrame(String name) {
private void initStartFrame(String name) {
Start the frame as such:
// GUI
frame.validate();
//frame.repaint();
frame.pack();
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});