Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I don't really have any code to show for the problem I add a JLabel to the JPanel, and I set the text to the mouse's current x/y position while the mouse is moving.
I'd appreciate if anyone could explain why this is happening.
PComponent.java
public class PComponent extends JPanel implements Commons {
private static final long serialVersionUID = -5525789712337277886L;
public PComponent(int x, int y, int width, int height) {
this.setLocation(x, y);
this.setSize(width, height);
}
}
PNode
public class PNode extends PComponent {
public PNode(int x, int y, int width, int height) {
super(x, y, width, height);
this.setOpaque(false);
this.setBorder(BorderFactory.createLineBorder(Color.RED));
}
}
PInterface
public abstract class PInterface extends PComponent implements Resizable {
public PInterface(int x, int y, int width, int height, int nodeW, int nodeH) {
super(x, y, width, height);
this.nodeW = nodeW;
this.nodeH = nodeH;
this.node = new PNode[MAX_NODES];
this.addNodes();
this.registerInterface();
this.pack();
}
private void registerInterface() {
for (int i = 0; i < cachedInterface.length; i++) {
if(cachedInterface[i] == null) {
cachedInterface[i] = this;
break;
}
}
}
private void addNodes() {
int index = 0;
for (int i = 0; i < this.getWidth(); i+=nodeW) {
for (int j = 0; j < this.getHeight(); j+=nodeH) {
PNode node = new PNode(i,j,nodeW,nodeH);
this.add(node);
this.node[index] = node;
index++;
}
}
}
public void writeToNode(String s, int index) {
if(node[index] != null) {
if(node[index].getComponent(0) instanceof JLabel) {
((JLabel) node[index].getComponent(0)).setText(s);
}
}
}
public void writeToNode(String s, int index, int child) {
if(node[index] != null) {
if(node[index].getComponent(child) instanceof JLabel) {
((JLabel) node[index].getComponent(child)).setText(s);
}
}
}
#Override
public void resize() {
}
protected abstract void pack();
protected void createTransparentInterface(int r, int g, int b, int o) {
this.setBackground(new Color(r, g, b, o));
}
public static PInterface[] getCachedInterfaces() {
return cachedInterface;
}
public int getNodeW() {
return nodeW;
}
public void setNodeW(int nodeW) {
this.nodeW = nodeW;
}
public int getNodeH() {
return nodeH;
}
public void setNodeH(int nodeH) {
this.nodeH = nodeH;
}
private static PInterface[] cachedInterface = new PInterface[MAX_INTERFACES];
protected int nodeW;
protected int nodeH;
protected PNode[] node;
}
ClientDetailsInterface
public class ClientDetailsInterface extends PInterface {
public ClientDetailsInterface() {
super(0, 0, 200, 100, 100, 50);
this.createTransparentInterface(255, 0, 0, 100);
}
#Override
protected void pack() {
this.node[0].add(new JLabel("X:"));
this.node[0].add(new JLabel("Y:"));
}
}
Canvas
public class Canvas extends JPanel implements Resizable, Commons, MouseMotionListener {
private static final long serialVersionUID = 8374256772293662258L;
public Canvas() {
this.setBackground(Color.WHITE);
this.setFocusable(true);
this.addMouseMotionListener(this);
this.registerInterfaces();
}
private void registerInterfaces() {
int count = 0;
new ClientDetailsInterface();
for (int i = 0; i < PInterface.getCachedInterfaces().length; i++) {
if (PInterface.getCachedInterfaces()[i] != null) {
this.add(PInterface.getCachedInterfaces()[i]);
count++;
}
}
System.out.println("Loaded: " + count + " interfaces!");
}
#Override
public void resize() {
// TODO add resizing code
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent mouse) {
PInterface.getCachedInterfaces()[0].writeToNode("X:" + mouse.getX(), 0,0);
PInterface.getCachedInterfaces()[0].writeToNode("Y:" + mouse.getY(), 0,1);
}
}
new screenshot
http://prntscr.com/6dp6rd
Sounds like you are doing custom painting somewhere and you forgot to invoke:
super.paintComponent(g);
to make sure the background is cleared before you do your custom painting.
This of course assumes you are overriding the paintComponent() method. If you are overriding paint(...), don't. Custom painting is done by overriding the paintComponent(...) method.
If you need more help then post your SSCCE because the problem is with your code and we can't tell what you code looks like from a picture.
Edit:
Don't override getX() and getY(). Those are methods of the component class used for painting components at a specific location.
Final Edit:
Take a look at Backgrounds With Transparency for the problem and the solution.
Related
So I have a problem with my mouse detection using a object called Ornament that inherits JComponent and I am getting the mouse clicks using java.awt.event.MouseEvent.
The solution me and my group though would be the best is to compare the distance of each ornament to the mouse and if its less than 50 (which is the radius of the ornament) it would do something.
private class ME implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
for(int i = 0; i < ORNAMENT_AMOUNT; i++) {
Ornament current = oh.getOrnament(i);
int distance = (int)(Math.sqrt(((e.getX() - current.getX()) * (e.getX() - current.getX())) + ((e.getY() - current.getY()) * (e.getY() - current.getY()))));
if(distance <= 50) {
System.out.println("CIRCLE CLICKED!");
current.reset();
}
}
}
The problem that I am getting is that it just does not work how it should. I click in the same spot many times and eventually it will trigger the event on one of the ornaments. Its random and confusing.
Here is the Ornament class
//ornament class to define the game object ornament
public class Ornament extends JComponent{
private int xPos;
private int yPos;
private int velocity;
private int screenWidth;
private int screenHeight;
private Random rand;
public Ornament(int screenWidth, int screenHeight, int velocity) {....}
public int getY() { return yPos; }
public int getX() { return xPos; }
#Override
public void paintComponent(Graphics graphics) {
float r = rand.nextFloat();
float g = rand.nextFloat();
float b = rand.nextFloat();
super.paintComponent(graphics);
graphics.setColor(new Color(r, g, b));
graphics.fillOval(0, 0, 50, 50);
}
....
public void reset() {
this.yPos = -(int)(Math.random()*500);
this.xPos = (int)(Math.random()*screenWidth);
this.velocity += 1;
update();
}
}
My whole approach to this might be wrong but it seems right in my head so help would be appreciated! :)
*note oh is an objecthandler class I made to run the game loop in a different thread that has an array of ornaments
public class ObjectHandler implements Runnable {
private int size;
private Ornament[] list;
private GUI game;
public ObjectHandler(int size, GUI game) {
....
list = new Ornament[size];
//init object list
for(int i = 0; i < size; i++) {
list[i] = new Ornament(game.getFrameX(), game.getFrameY(), game.getStartingVel());
game.add(list[i]);
}
}
public Ornament getOrnament(int index) { return list[index]; }
public void run() {
while(true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) { e.printStackTrace(); }
game.loadBackground();
for(int i = 0; i < size; i++) {
if(list[i].getY() >= game.getFrameY())
list[i].reset();
else
list[i].update();
}
}
}
}
Thank you all for your help!
I used Gilbert Le Blanc's method to get this to work.
I removed the JComponent off of the Ornament class and instead created a class that inherits JPanel
ublic class GamePanel extends JPanel{
private Ornament[] objectList;
......
public GamePanel(GUI game) {
....
MouseListener ml = new MouseListener();
addMouseListener(ml);
this.setBounds(0, 0, 500, 500);
}
I then added a paint component and rendered each Ornament in the objectList array using a for loop
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
.....
for(int i = 0; i < objectList.length; i++) {
Color c = new Color(objectList[i].r, objectList[i].g, objectList[i].b);
g2.setColor(c);
g2.fillOval(objectList[i].getX(), objectList[i].getY(), 50, 50);
}
}
}
Furthemore I added the mouselistener to the JPanel component. Using the same technique for mouse to object collision and it worked!
class MouseListener extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent e)
{
if(!gameOver) {
for(int i = 0; i < objectList.length; i++) {
int distance = (int)(Math.sqrt(((e.getX() - objectList[i].getX()) * (e.getX() - objectList[i].getX())) + ((e.getY() - objectList[i].getY()) * (e.getY() - objectList[i].getY()))));
if(distance <= 50) {
game.incScore();
objectList[i].reset();
}
}
...
}
}
Shoutout to hfontanez and Gilbert Le Blanc for the help! :)
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am learning Java. And I have a problem, certainly basic.
The menubar is displayed twice, and the drawn lines only appear on a quarter of the page.
Do you think there is a relation between the Panel and the JMenuBar ?
Do you think the problem is related to the repaint() method ?
Here is the code :
Class panel:
public class Panel extends JPanel {
private String colorName = "All";
private Color color = Color.RED;
private String shape = "Circle";
private int size1 = 30;
private int x = 0, y = 0;
private boolean allow = false;
#Override
public void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
if (allow == true) {
if (colorName == "Red")
g.setColor(Color.RED);
else if (colorName == "Blue")
g.setColor(Color.BLUE);
else if (colorName == "All") {
int r = (int) ((Math.random()) * 256);
int v = (int) ((Math.random()) * 256);
int b = (int) ((Math.random()) * 256);
color = new Color(r, v, b);
g.setColor(color);
}
if (shape == "Circle")
g.fillOval(x, y, size1, size1);
if (shape == "Square")
g.fillRect(x, y, size1, size1);
}
repaint();
}
public String getColorName() {
return colorName;
}
public void setColorName(String colorName) {
this.colorName = colorName;
}
public boolean isAllow() {
return allow;
}
public void setAllow(boolean allow) {
this.allow = allow;
}
public String getShape() {
return shape;
}
public void setForme(String forme) {
this.shape = shape;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getSize1() {
return size1;
}
public void setSize1(int size1) {
this.size1 = size1;
}
}
Class frame :
public class Frame extends JFrame{
JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("File");
JMenu edit = new JMenu("Edit");
Panel p = new Panel();
public Frame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setSize(400,400);
this.setTitle("Test");
this.addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent e) {
int a = e.getX() - (p.getSize1()/2);
int b = e.getY() - (p.getSize1());
p.setX(a);
p.setY(b);
p.setAllow(true);
}
});
this.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
int a = e.getX() - (p.getSize1()/2);
int b = e.getY() - (p.getSize1());
p.setX(a);
p.setY(b);
p.setAllow(true);
}
});
mb.add(file);
mb.add(edit);
this.setJMenuBar(mb);
this.setLayout(new BorderLayout());
this.add(p, BorderLayout.CENTER);
this.setVisible(true);
}
public static void main(String[] args) {
new Frame();
}
}
Can you help me please?
You've a very bad typographical bug in your code:
#Override
public void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponents(g);
should be:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Please note the difference in the super call since paintComponents != paintComponent
Also, don't compare Strings using == or !=. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two object references are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here.
And so, not:
if (colorName == "Red") {
// ....
}
but rather:
if (colorName.equalsIgnoreCase("Red")) {
// ....
}
Also, never call repaint() within a painting method. Also, don't randomize the painting or change object state within paintComponent since you do not have control over when or if the method will be called. Randomize in a listener, such as the mouse listener, and if you need animation separate from what the mouse listener provides, use a Swing Timer
ALSO
This:
public int getX() {
// ...
}
Overrides a key method of JPanel inherited from the Component class, that is key to placement of the JPanel, same for getY(). Rename those methods ASAP
I am creating a program in Java, and would like to make my own button class as opposed to using a JButton. I've got all the aesthetics sorted out but I'm not sure how to get the mouse pressed event in Java.
This is my code:
// Button.java
package cella;
import java.awt.Color;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
public class Button extends MouseAdapter {
int x, y, w, h;
String ph, val;
boolean mouseDown;
Color LIGHTGRAY = new Color(200, 200, 200);
public Button(int xt, int yt, int wt, int ht, String pht, String valt) {
x = xt;
y = yt;
w = wt;
h = ht;
ph = pht;
val = valt;
mouseDown = false;
}
public void draw(Graphics g, Point mouse) {
if (contains(mouse)) {
g.setColor(Color.GRAY);
} else {
g.setColor(LIGHTGRAY);
}
g.fillRect(x, y, w, h);
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
g.drawString(ph, x + 5, y + h - 5);
}
private boolean contains(Point pos) {
if (pos.x > x && pos.x < x + w && pos.y > y && pos.y < y + h) {
return true;
} else {
return false;
}
}
public boolean pressed(Point pos) {
if (contains(pos) && mouseDown) {
System.out.println("Pressed");
return true;
}
else return false;
}
}
The boolean mouseDown will be set to true when the mouse is pressed and then false when released however i can't find a way to catch these events, mouseListener gives errors about needing abstract classes when i try to implement it. Thanks for any help you can give me.
Full code
Try this.
JButton button = new JButton("Click!");
button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.NOBUTTON) {
textArea.setText("No button clicked...");
} else if (e.getButton() == MouseEvent.BUTTON1) {
textArea.setText("Button 1 clicked...");
}
}
});
See available methods
Hope this help!
You can add a listener to your button that handles the event.
JButton button = new JButton("Click for Stuff");
button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
switch(e.getButton())
{
case MouseEvent.NOBUTTON : // do stuff on button release
break;
case MouseEvent.BUTTON1 : // do stuff on click
break;
}
}
});
I know this question is a few years old, but I thought my input might be useful to someone down the road trying to accomplish the same task, considering I have some experience in custom UIs.
If you want a fully non-JComponent button, then you're going to need to also program your mouselistener and a UI Object Registry and a render/update function all operating on their required threads. I've done that, complete with NumberInputFields, Buttons, PasswordFields, TextFields, TextAreas, Graphics, and a variety of other UI objects. You don't want to unless you're going for a radically different look and feel than what is already supplied with very different functionality (for instance, my TextArea and TextField took in BitLines made up of TextBits rather than Strings, which allowed for each character to individually be formatted or colored or sized, complete with customized hover and click events). If such a different result is desired, you would do well to look into everything that goes into making a full UI within a Canvas object. If not, you have a couple other options.
Option 1: Extend the JButton class like has already been suggested. This is the easiest and likely the best option for you. It's fairly simple, and you can make that button be whatever you want it to be (within reason, of course).
Option 2: Create your own custom look and feel by extending the BasicLookAndFeel class. This is more complex and may take a bit of time and research, but in the end you can format all of your program to have a consistent L&F throughout, giving a satisfying and unique look to your software.
Here's an example of what it can take to make a button with basic functionality, completely separate from the JComponent class. Please note that this does NOT include the many background classes required to make this operate, such as the registry, the renderer, the animation and image loaders, the listeners, etc.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import dev.blue.neuron.storage.Animation;
public class Button extends UIObject {
private Animation whileDown;
private Animation whileUp;
private int tooltipTimer = 0;
private boolean showTooltip = false;
private boolean useTooltip = false;
protected boolean showingClicked = false;
protected boolean isSelected;
private boolean showID;
private int fontSize;
private Color color = Color.BLACK;
public Button(String id, boolean showID, boolean useTooltip, int fontSize, int x, int y, int width, int height,
int animationSpeed, Animation whileDown, Animation whileUp) {
this.id = id;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.whileDown = whileDown;
this.whileUp = whileUp;
this.bounds = new Rectangle(x, y, width, height);
this.showID = showID;
this.fontSize = fontSize;
this.useTooltip = useTooltip;
}
public void render(Graphics g) {
animate();
this.whileUp.render(g);
this.whileDown.render(g);
if (this.showID) {
g.setFont(new Font("Helvetica", 1, this.fontSize));
g.setColor(this.color);
g.drawString(this.id, this.x + this.width / 2 - g.getFontMetrics().stringWidth(this.id) / 2,
(int) ((this.y + this.height / 2) + g.getFontMetrics().getHeight() / 3.5D));
}
if (this.showTooltip && this.useTooltip) {
g.setFont(new Font("Helvetica", 0, 12));
g.setColor(Color.GRAY);
g.drawString(this.id, this.x, (int) (this.y + g.getFontMetrics().getHeight() * 1.5D));
}
}
public void setColor(Color color) {
this.color = color;
}
public void update() {
if (this.hovering) {
this.tooltipTimer++;
} else if (this.showingClicked) {
this.showingClicked = false;
}
if (this.tooltipTimer >= 50)
this.showTooltip = true;
runOnUpdate();
}
public void runOnUpdate() {
}
public void onMouseMove(Point p) {
if (this.bounds.contains(p)) {
if (!this.hovering) {
this.hovering = true;
runOnHover();
}
} else if (this.hovering) {
this.hovering = false;
this.showTooltip = false;
this.tooltipTimer = 0;
runOnStopHover();
}
}
private void animate() {
if (this.showingClicked) {
if (!this.whileDown.isRunning()) {
this.whileUp.end();
this.whileDown.run();
}
} else if (!this.whileUp.isRunning()) {
this.whileDown.end();
this.whileUp.run();
}
}
public boolean onClick(int button, Point p) {
if (this.bounds.contains(p)) {
runClick();
return true;
}
return false;
}
public void runOnMissedClick() {
}
public boolean onMouseDown(int button, Point p) {
if (this.bounds.contains(p)) {
(App.getInstance().getMouseManager()).clickedObject = this;
runMouseDown();
this.showingClicked = true;
return true;
}
return false;
}
public boolean onMouseUp(int button, Point p) {
if ((App.getInstance().getMouseManager()).clickedObject == this)
(App.getInstance().getMouseManager()).clickedObject = null;
if (!this.bounds.contains(p))
runOnMissedClick();
if (this.showingClicked) {
this.showingClicked = false;
if (this.bounds.contains(p)) {
runMouseUp();
onClick(button, p);
return true;
}
return false;
}
return false;
}
public void onType(KeyEvent e) {
}
public void onKeyPressed(KeyEvent e) {
}
public Animation getWhileUpAnim() {
return this.whileUp;
}
public Animation getWhileDownAnim() {
return this.whileDown;
}
public void setWhileUpAnim(Animation whileUp) {
this.whileUp = whileUp;
}
public void setWhileDownAnim(Animation whileDown) {
this.whileDown = whileDown;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
}
I have a large program that I will post some classes of and hopefully you guys can find the problem. Basically, sometimes when I start it, it creates the game just fine, and others the background is up a few pixels to the north and west directions leaving very unsightly whitespace. I cannot seem to find the missing piece of code that decides whether not it does this. It honestly feel like some kind of rendering glitch on my machine. At any rate, I have put a background getX and getY method in for debugging and have noticed that whether the background is fully stretched to the screen(its a custom background so the pixel height and width match perfectly), or its up and to the left, the background still reads that it is displaying at (0,0). I will post all the methods from the main thread to the creating of the background in the menu. I will leave notes indicating the path it takes through this code that gets it to creating the background. Thank you for your help and I will check in regularly for edits and more information.
EDIT: added background.java
EDIT2: added pictures explaining problem
Menu.java *ignore the FileIO code, the main point is the creation of a new GamePanel()
public class Menu {
private static File file;
public static void main(String[] args) throws IOException {
file = new File("saves.txt");
if(file.exists()){
FileIO.run();
FileIO.profileChoose();
}
else{
FileIO.profileCreate();
FileIO.run();
}
JFrame window = new JFrame("Jolly Jackpot Land");
window.setContentPane(new GamePanel());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
Next is the GamePanel.java
public class GamePanel extends JPanel implements Runnable, KeyListener {
// ID
private static final long serialVersionUID = 1L;
// Dimensions
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
// Thread
private Thread thread;
private boolean running;
private int FPS = 30;
private long targetTime = 1000 / FPS;
// Image
private BufferedImage image;
private Graphics2D g;
// Game State Manager
private GameStateManager gsm;
public GamePanel() {
super();
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
private void init() {
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
gsm = new GameStateManager();
}
#Override
public void run() {
init();
long start;
long elapsed;
long wait;
// Game Loop
while (running) {
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - (elapsed / 1000000);
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void update() {
gsm.update();
}
private void draw() {
gsm.draw(g);
}
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
g2.dispose();
}
#Override
public void keyPressed(KeyEvent k) {
gsm.keyPressed(k.getKeyCode());
}
#Override
public void keyReleased(KeyEvent k) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
}
This calls for the creation of a new GameStateManager object in its init() method and the class for that is here.
GameStateManager.java
public class GameStateManager {
private ArrayList<GameState> gameStates;
private int currentState;
public static final int MENUSTATE = 0;
public static final int SLOTGAMESTATE = 1;
public static final int DICEGAMESTATE = 2;
public static final int ROULETTEGAMESTATE = 3;
public static final int LEADERBOARDSTATE = 4;
public static final int SETTINGSSTATE = 5;
public static final int HELPSTATE = 6;
public GameStateManager() {
gameStates = new ArrayList<GameState>();
currentState = 0;
gameStates.add(new MenuState(this));
gameStates.add(new SlotGameState(this));
gameStates.add(new DiceGameState(this));
gameStates.add(new RouletteGameState(this));
gameStates.add(new LeaderboardState(this));
gameStates.add(new SettingsState(this));
gameStates.add(new HelpState(this));
}
public void setState(int state){
currentState = state;
gameStates.get(currentState).init();
currentState = 0;
}
public int getState() {
return currentState;
}
public void update() {
gameStates.get(currentState).init();
}
public void draw(java.awt.Graphics2D g){
gameStates.get(currentState).draw(g);
}
public void keyPressed(int k){
gameStates.get(currentState).keyPressed(k);
}
public void keyReleased(int k) {
gameStates.get(currentState).keyReleased(k);
}
}
GameState is an abstract class I have so its not worth posting, it only contains init(), draw(), etc. This next class is the last and final class and is called because GameStateMananger starts at MENUSTATE or 0, and when GSM is initialized it initializes its current state, thus taking us to the class MenuState
MenuState.java
public class MenuState extends GameState {
private Background bg;
public FontMetrics fontMetrics;
private int choice = 0;
private String[] options = { "Slot Machine", "Dice Toss", "Roulette Wheel", "Leaderboards", "Settings", "Help",
"Quit" };
private Color titleColor;
private Font titleFont;
private Font font;
public MenuState(GameStateManager gsm) {
this.gsm = gsm;
try {
bg = new Background("/Backgrounds/happybg.png");
titleColor = Color.WHITE;
titleFont = new Font("Georgia", Font.PLAIN, 28);
} catch (Exception e) {
e.printStackTrace();
}
font = new Font("Arial", Font.PLAIN, 12);
}
#Override
public void init() {
}
#Override
public void update() {
}
#Override
public void draw(Graphics2D g) {
Canvas c = new Canvas();
fontMetrics = c.getFontMetrics(font);
// Draw BG
bg.draw(g);
// Draw title
g.setColor(titleColor);
g.setFont(titleFont);
String title = "Jolly Jackpot Land!";
g.drawString(title, 36, 60);
g.setFont(font);
for (int i = 0; i < options.length; i++) {
if (i == choice)
g.setColor(Color.RED);
else
g.setColor(Color.WHITE);
g.drawString(options[i], 30, 120 + i * 15);
}
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.PLAIN, 10));
g.drawString("v1.1", 165, 235);
Object[] a = { ("Name: " + Player.getName()), ("Gil: " + Player.getGil()),
("Personal Best: " + Player.getPersonalBest()), ("Winnings: " + Player.getWinnings()),
("Wins: " + Player.getWins()), ("Losses: " + Player.getLosses()),
("Win/Loss Ratio: " + String.format("%.2f", Player.getRatio()) + "%") };
g.setFont(font);
if (Player.getName() != null) {
for (int x = 0; x < a.length; x++) {
g.drawString(a[x].toString(), GamePanel.WIDTH - fontMetrics.stringWidth(a[x].toString()) - 30,
120 + x * 15);
}
}
}
private void select() {
if (choice == 0) {
// Slots
gsm.setState(GameStateManager.SLOTGAMESTATE);
}
if (choice == 1) {
// Dice
gsm.setState(GameStateManager.DICEGAMESTATE);
}
if (choice == 2) {
// Roulette
gsm.setState(GameStateManager.ROULETTEGAMESTATE);
}
if (choice == 3) {
// Leaderboards
gsm.setState(GameStateManager.LEADERBOARDSTATE);
}
if (choice == 4) {
// Settings
gsm.setState(GameStateManager.SETTINGSSTATE);
}
if (choice == 5) {
// Help
gsm.setState(GameStateManager.HELPSTATE);
}
if (choice == 6) {
// Quit
System.exit(0);
}
}
#Override
public void keyPressed(int k) {
if (k == KeyEvent.VK_ENTER) {
select();
}
if (k == KeyEvent.VK_UP) {
choice--;
if (choice == -1) {
choice = options.length - 1;
}
}
if (k == KeyEvent.VK_DOWN) {
choice++;
if (choice == options.length) {
choice = 0;
}
}
}
#Override
public void keyReleased(int k) {
}
}
Background.java
public class Background {
private BufferedImage image;
private double x;
private double y;
public Background(String s) {
try {
image = ImageIO.read(getClass().getResourceAsStream(s));
} catch (Exception e) {
e.printStackTrace();
}
}
public void setPosition(double x, double y) {
this.setX(x);
this.setY(y);
}
public void draw(Graphics2D g) {
g.drawImage(image, 0, 0, null);
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
This is where it waits for input in the game loop basically. I know this is a lot of code, but a lot of it is skimming till a method call takes you to the next class. I just can't figure out why it only happens sometimes, if it was consistent I could debug it. Any help would be extremely appreciated.
These are both from clicking the .jar of the above program, exact same .jar, exact same source code, different result. I am bewildered.
So I'm trying to write a tile-grid based game and came up with a quite unusual solution. I filled a 2D JPanel Array with JLabels with an ImageIcon as tile. Everything works so far but I did not find any way to render this activly.
I've tryied some methods for active rendering I found on the Internet, but they did not work on my idea. Do you have some ideas how to realize this without rewrite everything to Canvas or something similar?
Here's my code:
Window
public class Win extends JFrame {
private static final long serialVersionUID = 1L;
private BufferStrategy bs;
public Win(int x, int y) {
this.setSize(x, y);
this.setVisible(true);
this.setResizable(false);
this.setIgnoreRepaint(true);
this.createBufferStrategy(2);
setBs(getBufferStrategy());
}
public BufferStrategy getBs() {
return bs;
}
public void setBs(BufferStrategy bs) {
this.bs = bs;
}
}
"Draw"
public class Field extends JPanel {
private static final long serialVersionUID = 5257799495742189076L;
private int x = 0;
private int y = 0;
private JPanel backPanel[][] = new JPanel[19][19];
private BufferedImage images[] = new BufferedImage[100];
private JLabel image[][] = new JLabel[19][19];
public Field() {
this.setLayout(new GridLayout(20, 20));
this.setIgnoreRepaint(true);
}
// Creates Panel Grid & Draws floor
public void setPanels() {
for (int h = 0; h < 19; h++) {
for (int w = 0; w < 19; w++) {
backPanel[h][w] = new JPanel();
backPanel[h][w].setLayout(new GridLayout(1, 1));
image[h][w] = new JLabel(new ImageIcon(images[0]));
backPanel[h][w].add(image[h][w]);
this.add(backPanel[h][w]);
}
}
}
// Loads the Textures
public void getTextures() throws IOException {
for (int i = 0; i < 1; i++) {
images[i] = ImageIO.read(new File("texture.png"));
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(images[1], 0, 0, null);
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
Game Loop
public class GameLoop implements Runnable {
private boolean runFlag = true;
#Override
public void run() {
Field field = new Field();
Win window = new Win(640, 640);
window.add(field);
try {
field.getTextures();
} catch (IOException e) {
e.printStackTrace();
}
while (runFlag) {
try {
field.setPanels();
window.getBs().show();
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
runFlag = false;
}
}
Some alternatives:
Shuffle the components and do removeAll(), add(), and validate() as shown here.
Shuffle the contents and do setIcon(), as shown here.
In either case,
Use javax.swing.Timer to pace the animation, as shown here and here.
Consider TexturePaint to fill the icons, as shown here.