Overlapping background Graphics in a Memory Game Applet - java

Okay I have been working on this memory game applet in java for a while now and I have all the sorting and matching algorithms all figured out, I am just having a wretched time trying to get my GUI to function properly. Whenever I click on one of the "cards" to "flip", I end up with a column of the cards being created while their backs counterparts remain under the cards until you go over it with the cursor. It is all very frustrating as I am not quite sure why half of this is happening or how to stop it. Here is my Display class:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.*;
public class Display extends JPanel implements MouseListener {
private String[] Colors = Card.validColors();
private String[] Shapes = Card.validShapes();
private Component[] place;
private JButton[][] buttonGrid= new JButton[6][6];
private Rectangle[][] triggers = new Rectangle[6][6];
private Board game;
private Polygon star = new Polygon();
private Card pick;
private boolean turnPhase2 = false;
private Font serifNames = new Font(Font.SERIF, Font.PLAIN, 18);
private Font serifCards = new Font(Font.SERIF, Font.ROMAN_BASELINE, 36);
private JPanel panel = new JPanel();
public Display() {
this.setBackground(Color.BLACK);
this.setLayout(new GridBagLayout());
panel.setSize(590, 410);
panel.setLayout(new GridLayout(6, 6, 10, 10));
panel.setOpaque(false);
generateStar();
buildBoard();
fillButtonArray();
this.addMouseListener(this);
this.add(panel);
System.out.println(getFontMetrics(serifCards));
System.out.println(getFontMetrics(serifNames));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
place = panel.getComponents();
for (int i = 0; i < place.length; i++) {
paintBack(g, place[i].getX() + 25, place[i].getY() + 35);
}
displayNames(g);
displayTurn(g);
if (game.flippedCard() != null) {
int[] xy = game.flippedCardLocation();
paintCard(g, game.flippedCard(), xy[0], xy[1]);
}
}
/**
* This method builds the game board.
*
*
*/
private void buildBoard() {
game = new Board(buildDeck());
}
/**
* This method creates a "deck" of cards with which we can create the game board.
*
* #return deck Returns the deck of Card objects in the form of an ArrayList.
*/
private ArrayList<Card> buildDeck() {
ArrayList<Card> deck = new ArrayList<Card>();
for (int i = 0; i < Colors.length; i++) {
for (int s = 0; s < Shapes.length; s++) {
Card first = new Card(Shapes[s], Colors[i]);
Card second = new Card(Shapes[s], Colors[i]);
deck.add(first);
deck.add(second);
}
}
System.out.println(deck.size());
return deck;
}
private void fillButtonArray() {
for (int i = 0; i < 6; i++) {
for (int n = 0; n < 6; n++) {
JButton button = new JButton();
button.setPreferredSize(new Dimension(90, 60));
button.addMouseListener(this);
button.setOpaque(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
buttonGrid[i][n] = button;
}
}
fillGrid();
}
private void fillGrid() {
panel.setBounds(25, 35, panel.getSize().width, panel.getSize().height);
int count = 0;
for (int i = 0; i < 6; i++) {
for (int s = 0; s < 6; s++) {
panel.add(buttonGrid[i][s]);
place = panel.getComponents();
int x = panel.getComponent(count).getBounds().x;
int y = panel.getComponent(count).getBounds().y;
Rectangle rect = new Rectangle(x, y, 90, 60);
triggers[i][s] = rect;
}
}
}
private void paintBack(Graphics g, int x, int y) {
g.setColor(Color.WHITE);
g.drawRoundRect(x, y, 90, 60, 2, 4);
g.fillRoundRect(x, y, 90, 60, 2, 4);
g.setColor(Color.BLACK);
g.setFont(serifCards);
g.drawString("M", x + 28, y + 42);
}
private void paintCard(Graphics g, Card card, int x, int y) {
g.setColor(Color.GRAY);
g.drawRoundRect(x, y, 90, 60, 2, 4);
g.fillRoundRect(x, y, 90, 60, 2, 4);
String color = card.getColor();
String shape = card.getShape();
if (shape.equals("Star")) {
g.setColor(pickColor(color));
star.translate(x + 25, y + 10);
g.drawPolygon(star);
g.fillPolygon(star);
}
else if (shape.equals("Circle")) {
g.setColor(pickColor(color));
g.drawOval(x + 25, y + 10, 40, 40);
g.fillOval(x + 25, y + 10, 40, 40);
}
else if (shape.equals("Square")) {
g.setColor(pickColor(color));
g.drawRect(x + 25, y + 10, 40, 40);
g.fillRect(x + 25, y + 10, 40, 40);
}
}
private void displayNames(Graphics g) {
g.setFont(serifNames);
int[] scores = game.getCurrentScores();
for (int i = 0; i < scores.length; i++) {
if (i == 0) {
g.setColor(Color.CYAN);
g.drawString("Cyan: " + scores[i], 10, 24);
}
else if (i == 1) {
g.setColor(Color.ORANGE);
g.drawString("Orange: " + scores[i], 560, 24);
}
else if (i == 2) {
g.setColor(Color.MAGENTA);
g.drawString("Magenta: " + scores[i], 10, 470);
}
else {
g.setColor(Color.WHITE);
g.drawString("White: " + scores[i], 569, 470);
}
}
}
private void displayTurn(Graphics g) {
int player = game.getCurrentPlayer();
if (player == 0) {
g.setColor(Color.CYAN);
String str = "Cyan's Turn";
g.drawString(str, 640 / 2 - 48, 24);
//System.out.println(getFontMetrics(serifNames).stringWidth(str) / 2 + " Cyan");
}
else if (player == 1) {
g.setColor(Color.ORANGE);
String str = "Orange's Turn";
g.drawString(str, 640 / 2 - 52, 24);
//System.out.println(getFontMetrics(serifNames).stringWidth(str) / 2 + " Orange");
}
else if (player == 2) {
g.setColor(Color.MAGENTA);
String str = "Magenta's Turn";
g.drawString(str, 640 / 2 - 57, 24);
//System.out.println(getFontMetrics(serifNames).stringWidth(str) / 2 + " Magenta");
}
else {
g.setColor(Color.WHITE);
String str = "White's Turn";
g.drawString(str, 640 / 2 - 47, 24);
//System.out.println(getFontMetrics(serifNames).stringWidth(str) / 2 + " White");
}
}
private void findTrigger(int x, int y) {
for (int i = 0; i < 6; i++) {
if () {
}
for (int s = 0; s < 6; s++) {
Rectangle rectTest = triggers[i][s];
if (x >= rectTest.getMinX() &&
x <= rectTest.getMaxX() &&
y >= rectTest.getMinY() &&
y <= rectTest.getMaxY()) {
Graphics g = getGraphics();
paintCard(g, game.flip(i,s), buttonGrid[i][s].getBounds().x, buttonGrid[i][s].getBounds().y);
break;
}
}
}
}
private void generateStar() {
star.addPoint(20, 0);
star.addPoint(25, 15);
star.addPoint(40, 15);
star.addPoint(28, 24);
star.addPoint(32, 40);
star.addPoint(20, 30);
star.addPoint(8, 40);
star.addPoint(12, 24);
star.addPoint(0, 15);
star.addPoint(15, 15);
}
private Color pickColor(String color) {
if (color.equals("Black")) {
return Color.BLACK;
}
if (color.equals("Yellow")) {
return Color.YELLOW;
}
if (color.equals("Green")) {
return Color.GREEN;
}
if (color.equals("Blue")) {
return Color.BLUE;
}
if (color.equals("Red")) {
return Color.RED;
}
if (color.equals("Purple")) {
return new Color(128, 0, 255);
}
return null;
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse Clicked");
int x = e.getX();
System.out.println(x + " is x");
int y = e.getY();
System.out.println(y + " is Y");
System.out.println(panel.getWidth() + 25);
System.out.println(panel.getHeight() + 35);
System.out.println("Finding the trigger rectangle");
findTrigger(x, y);
}
#Override
public void mouseEntered(MouseEvent e) {
//System.out.println("Mouse Entered");
}
#Override
public void mouseExited(MouseEvent e) {
//System.out.println("Mouse Exited");
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Mouse Pressed");
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("Mouse Released");
}
}
Some side notes is that the actual game is handled by the board object and has all the methods needed to create and run a multiplayer memory game and the Card object only contains two strings of the shape and color of what is to be matched by the game. And finally the last class is the Memory class which I will provide:
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JApplet;
public class Memory extends JApplet {
private Display _theDisplay;
final int width = 640;
final int height = 480;
private Action reDraw = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
repaint();
}
};
public Memory() {
_theDisplay = new Display();
}
public void init() {
setSize(width, height);
setBackground(Color.BLACK);
this.add(_theDisplay);
}
}
Please any tips would be incredibly helpful, thanks in advance!

Your graphics appear messed. Problems I see:
You call getGraphics() on a component to draw with its Graphics context, but please understand that a Graphics object obtained in this way will not persist, and can thus mess up or even cause a NPE to be thrown.
Better to do all-passive Graphics via your paintComponent(...) method. If you need any pre-made drawings, do these in BufferedImages, and draw the BufferedImages in the JComponent's paintComponent(...) method.
Rather than have your Display JPanel do all the painting of the cards and the backs, I suggest that each Card be its own separate object with its own state, that paints itself correctly depending on its state. You may wish to have this extend a JComponent, or have it be a logical entity that is then painted by your Display JPanel, up to you, but separate out the logic from the display to simplify your coding and debugging.
A major problem looks to be in your findTrigger(...) method and that is where you should concentrate your efforts. You should use the mouseClick to change the state of the logical Card (as described above) that is clicked and then call repaint() on the Display JPanel (this) if the Cards are painted in paintComponent(...).
Else if the Cards paint themselves, consider having them be JLabels and simply swap ImageIcons, likely the easiest way to "flip" cards.
Your main problem is that of a program mis-behavior. I have not seen the cause of this on a quick overview of your code, and suggest that you use a debugger or println statements to first and foremost try to isolate the problem.

Related

Make random character letters and display them one by one in the java swing

I tried to make random letters but only with three letters, and I want to display them one by one in the window I made when the "random" button was pressed, but when I pressed the random button, the loop didn't stop. and in the same way I tried with the CLI it gave me the results I expected. I've tried it many times but it doesn't work. Please help?
Below is the complete source code of my program:
package testGrafik;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestRandom extends JFrame {
public TestRandom() {
setTitle("Test Game");
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
Board board = new Board();
getContentPane().add(board);
}
public static void main(String[] args) {
new TestRandom();
}
public class Board extends JPanel implements MouseListener,
MouseMotionListener {
int x;
int y;
public boolean isMouseMoving = false;
public boolean isClicked = false;
public char[] character = {'S', 'O', 'I'};
public Random rand = new Random();
public Board() {
x = 0;
y = 0;
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.DARK_GRAY);
g.fillRect(x, y, 500, 500);
// draw box
g.setColor(Color.LIGHT_GRAY);
g.fillRect(x + 10, y + 10, 70, 40);
if (isMouseMoving == true) {
g.setColor(Color.cyan);
g.fillRect(x + 10, y + 10, 70, 40);
}
//draw string
g.setColor(Color.BLACK);
g.setFont(new Font("Tahoma", Font.BOLD, 15));
g.drawString("Click", x + 25, y + 35);
if (isClicked == true) {
char c = character[rand.nextInt(character.length)];
String convertString = String.valueOf(c);
g.setColor(Color.WHITE); // border color
g.setFont(new Font("Tahoma", Font.PLAIN, 30)); //
String.valueOf(hrf)
g.drawString(convertString, x + 500 / 2, y + 500 / 2); //
border boax t4 huruf muncul
System.out.println("Latter: " + convertString);
}
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if (mx > x + 10 && mx < x + 10 + 70 && my > y + 10 && my < y +
10 + 40) {
isClicked = true;
System.out.println("YOU CKLIK ON THE BOX");
} else {
isClicked = false;
System.out.println("You click outside the box");
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if (mx > x + 10 && mx < x + 10 + 70 && my > y + 10 && my < y +
10 + 40) {
isMouseMoving = true;
} else {
isMouseMoving = false;
}
}
}
}
and below is the code that I tried with CLI:
package testGrafik;
import java.util.Random;
public class TestRandomCLI {
public static void main(String[] args) {
char[] character = {'S', 'O', 'I'};
Random rand = new Random();
char c = character[rand.nextInt(character.length)];
String convertString = String.valueOf(c);
System.out.println("Latter: " + convertString);
}
}
This happens because you call JComponent#repaint() method inside JComponent#paintComponent(). When you call repaint(), paintComponent will be called. Then again, repaint() will be called...and you got the point.
The solution:
Call repaint() only 1 time, when the user clicks.
#Override
public void mouseClicked(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if (mx > x + 10 && mx < x + 10 + 70 && my > y + 10 && my < y + 10 + 40) {
isClicked = true;
System.out.println("YOU CKLIK ON THE BOX");
repaint(); //Only 1 call after call
} else {
isClicked = false;
System.out.println("You click outside the box");
}
}
and of course remove it from paintComponent()
if (isClicked == true) {
char c = character[rand.nextInt(character.length)];
String convertString = String.valueOf(c);
g.setColor(Color.WHITE); // border color
g.setFont(new Font("Tahoma", Font.PLAIN, 30)); //
g.drawString(convertString, x + 500 / 2, y + 500 / 2); //
System.out.println("Latter: " + convertString);
}
//repaint();
}

Why anything is drawn on the screen?

I´m trying to do a simple 7 segment display and to test it I want to make a simple animation which displays the numbers in order with a separation between number draw of 1 second and this must run indefinitely but I cannot figure out how to draw the display itself (Implementing the animation, without the animation I know how to print the numbers one by one).
PD: I give you all the source code just for you to have it if anyone needs it but the "animation" is located on line 120 where I define the Thread to run the animation.
Source code:
public class MainWindow extends JFrame {
private JPanel contentPane;
private CustomRectangle custRect = null;
private JButton btnCancel;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow frame = new MainWindow();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainWindow() {
getContentPane().setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setSize(400, 400);
contentPane = new JPanel();
contentPane.setLayout(null);
custRect = new CustomRectangle(getContentPane().getSize());
getContentPane().add(custRect);
getContentPane().add(getBtnCancel(), BorderLayout.SOUTH);
}
private Color complementaryColor(Color background) {
int alpha = background.getAlpha();
int red = background.getRed();
int blue = background.getBlue();
int green = background.getGreen();
// find compliments
red = (~red) & 0xff;
blue = (~blue) & 0xff;
green = (~green) & 0xff;
return new Color(red, green, blue, alpha);
}
private JButton getBtnCancel() {
if (btnCancel == null) {
btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
btnCancel.setBackground(null);
btnCancel.setBorder(null);
btnCancel.setForeground(complementaryColor(getContentPane().getBackground()));
btnCancel.setFocusPainted(false);
}
return btnCancel;
}
private class CustomRectangle extends JComponent {
private byte[] nums = new byte[] { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B };
private double mainWidth = 0.0;
private double mainHeight = 0.0;
private Graphics2D g2d = null;
public CustomRectangle(Dimension size) {
mainWidth = size.getWidth();
mainHeight = size.getHeight();
}
public byte[] getNums() {
return nums;
}
#Override
public void paintComponent(Graphics g) {
g2d = (Graphics2D) g;
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
int seconds = calendar.get(Calendar.SECOND);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Thread th = new Thread() {
public void run() {
while(true) {
for(int i = 0; i < nums.length; i++)
generalCall(nums[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};th.start();
}
public void generalCall(byte val) {
drawAHoursHigh(val);
drawBHoursHigh(val);
drawCHoursHigh(val);
drawDHoursHigh(val);
drawEHoursHigh(val);
drawFHoursHigh(val);
drawGHoursHigh(val);
}
private Color getColor(byte val, int shift) {
int r = 255;
int g = 0;
int b = 0;
int a = 255 * (val >> shift) & 1;
System.out.println("R: " + r + " G: " + g + " B: " + b + " Alpha: " + a);
if (a == 0)
return new Color(15, 15, 15);
else
return new Color(r, g, b);
}
private void drawAHoursHigh(byte val) {
System.out.print("A: ");
Shape a = new RoundRectangle2D.Double(60, 20, 78, 18, 10, 10);
g2d.setColor(getColor(val, 6));
g2d.fill(a);
g2d.draw(a);
}
private void drawBHoursHigh(byte val) {
System.out.print("B: ");
Shape b = new RoundRectangle2D.Double(140, 40, 18, 98, 10, 10);
g2d.setColor(getColor(val, 5));
g2d.fill(b);
g2d.draw(b);
}
private void drawCHoursHigh(byte val) {
System.out.print("C: ");
Shape c = new RoundRectangle2D.Double(140, 160, 18, 98, 10, 10);
g2d.setColor(getColor(val, 4));
g2d.fill(c);
g2d.draw(c);
}
private void drawDHoursHigh(byte val) {
System.out.print("D: ");
Shape d = new RoundRectangle2D.Double(60, 260, 78, 18, 10, 10);
g2d.setColor(getColor(val, 3));
g2d.fill(d);
g2d.draw(d);
}
private void drawEHoursHigh(byte val) {
System.out.print("E: ");
Shape e = new RoundRectangle2D.Double(40, 160, 18, 98, 10, 10);
g2d.setColor(getColor(val, 2));
g2d.fill(e);
g2d.draw(e);
}
private void drawFHoursHigh(byte val) {
System.out.print("F: ");
Shape f = new RoundRectangle2D.Double(40, 40, 18, 98, 10, 10);
g2d.setColor(getColor(val, 1));
g2d.fill(f);
g2d.draw(f);
}
private void drawGHoursHigh(byte val) {
System.out.print("G: ");
Shape g = new RoundRectangle2D.Double(60, 140, 78, 18, 10, 10);
g2d.setColor(getColor(val, 0));
g2d.fill(g);
g2d.draw(g);
}
}
}
First, go read:
Performing Custom Painting
Painting in AWT and Swing
for more information on how painting works in Swing.
Next, go read:
Concurrency in Swing
to get a better understanding of the concurrency issue in Swing - the short version, Swing is NOT thread safe and is single threaded. This raises a number of issues when you want to perform repeated actions that update the UI.
Then, go read How to Use Swing Timers for a feasible solution.
Let's start identifying the core problems...
This...
contentPane = new JPanel();
contentPane.setLayout(null);
is generally a bad idea, but you're not using it anyway, so it's just white noise
This...
custRect = new CustomRectangle(getContentPane().getSize());
is erroneous, because at the time you request the size of he contentPane, it's not been realised or layout on the screen, so it's result is 0x0. You shouldn't be relying on this anyway and if you want to know the size of the container, request it when you actually need it.
Next...
private Graphics2D g2d = null;
You should never maintain a reference to any graphics context you didn't create. In Swing, the context is shared amongst all the components been painted, meaning that it could be dirty, with other content, or clipped to exclude the area you want painted.
And finally....
#Override
public void paintComponent(Graphics g) {
g2d = (Graphics2D) g;
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
int seconds = calendar.get(Calendar.SECOND);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Thread th = new Thread() {
public void run() {
while(true) {
for(int i = 0; i < nums.length; i++)
generalCall(nums[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};th.start();
}
😱
paintComponent will be called when ever Swing thinks your component needs to be repainted, when first realised, this could be a number of times in quick succession, meaning you now have a number of Threads running.
Paint should do one job, paint the current context of the component, nothing else. In your case, a Swing Timer would be a more viable and safer solution.
And, cleaned up, it might look something like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
public class MainWindow extends JFrame {
private CustomRectangle custRect = null;
private JButton btnCancel;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow frame = new MainWindow();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainWindow() {
getContentPane().setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
custRect = new CustomRectangle();
getContentPane().add(custRect);
getContentPane().add(getBtnCancel(), BorderLayout.SOUTH);
}
private Color complementaryColor(Color background) {
int alpha = background.getAlpha();
int red = background.getRed();
int blue = background.getBlue();
int green = background.getGreen();
// find compliments
red = (~red) & 0xff;
blue = (~blue) & 0xff;
green = (~green) & 0xff;
return new Color(red, green, blue, alpha);
}
private JButton getBtnCancel() {
if (btnCancel == null) {
btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
btnCancel.setBackground(null);
btnCancel.setBorder(null);
btnCancel.setForeground(complementaryColor(getContentPane().getBackground()));
btnCancel.setFocusPainted(false);
}
return btnCancel;
}
private class CustomRectangle extends JComponent {
private byte[] nums = new byte[]{0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B};
public CustomRectangle() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
}
public byte[] getNums() {
return nums;
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int i = 0; i < nums.length; i++) {
generalCall(g2d, nums[i]);
}
}
public void generalCall(Graphics2D g2d, byte val) {
drawAHoursHigh(g2d, val);
drawBHoursHigh(g2d, val);
drawCHoursHigh(g2d, val);
drawDHoursHigh(g2d, val);
drawEHoursHigh(g2d, val);
drawFHoursHigh(g2d, val);
drawGHoursHigh(g2d, val);
}
private Color getColor(byte val, int shift) {
int r = 255;
int g = 0;
int b = 0;
int a = 255 * (val >> shift) & 1;
System.out.println("R: " + r + " G: " + g + " B: " + b + " Alpha: " + a);
if (a == 0) {
return new Color(15, 15, 15);
} else {
return new Color(r, g, b);
}
}
private void drawAHoursHigh(Graphics2D g2d, byte val) {
System.out.print("A: ");
Shape a = new RoundRectangle2D.Double(60, 20, 78, 18, 10, 10);
g2d.setColor(getColor(val, 6));
g2d.fill(a);
g2d.draw(a);
}
private void drawBHoursHigh(Graphics2D g2d, byte val) {
System.out.print("B: ");
Shape b = new RoundRectangle2D.Double(140, 40, 18, 98, 10, 10);
g2d.setColor(getColor(val, 5));
g2d.fill(b);
g2d.draw(b);
}
private void drawCHoursHigh(Graphics2D g2d, byte val) {
System.out.print("C: ");
Shape c = new RoundRectangle2D.Double(140, 160, 18, 98, 10, 10);
g2d.setColor(getColor(val, 4));
g2d.fill(c);
g2d.draw(c);
}
private void drawDHoursHigh(Graphics2D g2d, byte val) {
System.out.print("D: ");
Shape d = new RoundRectangle2D.Double(60, 260, 78, 18, 10, 10);
g2d.setColor(getColor(val, 3));
g2d.fill(d);
g2d.draw(d);
}
private void drawEHoursHigh(Graphics2D g2d, byte val) {
System.out.print("E: ");
Shape e = new RoundRectangle2D.Double(40, 160, 18, 98, 10, 10);
g2d.setColor(getColor(val, 2));
g2d.fill(e);
g2d.draw(e);
}
private void drawFHoursHigh(Graphics2D g2d, byte val) {
System.out.print("F: ");
Shape f = new RoundRectangle2D.Double(40, 40, 18, 98, 10, 10);
g2d.setColor(getColor(val, 1));
g2d.fill(f);
g2d.draw(f);
}
private void drawGHoursHigh(Graphics2D g2d, byte val) {
System.out.print("G: ");
Shape g = new RoundRectangle2D.Double(60, 140, 78, 18, 10, 10);
g2d.setColor(getColor(val, 0));
g2d.fill(g);
g2d.draw(g);
}
}
}

Coordinates in paint

When you click in a box, it should create a circle in that box from the designated coordinate. Unless if its already there then its removed. How do I get currentx and currenty coordinates into the fill oval?
public class Grid extends Applet{
boolean click;
public void init()
{
click = false;
addMouseListener(new MyMouseListener());
}
public void paint(Graphics g)
{
super.paint(g);
g.drawRect(100, 100, 400, 400);
//each box
g.drawRect(100, 100, 100, 100);
g.drawRect(200, 100, 100, 100);
g.drawRect(300, 100, 100, 100);
g.drawRect(400, 100, 100, 100);
//2y
g.drawRect(100, 200, 100, 100);
g.drawRect(200, 200, 100, 100);
g.drawRect(300, 200, 100, 100);
g.drawRect(400, 200, 100, 100);
//3y1x
g.drawRect(100, 300, 100, 100);
g.drawRect(200, 300, 100, 100);
g.drawRect(300, 300, 100, 100);
g.drawRect(400, 300, 100, 100);
//4y1x
g.drawRect(100, 400, 100, 100);
g.drawRect(200, 400, 100, 100);
g.drawRect(300, 400, 100, 100);
g.drawRect(400, 400, 100, 100);
if (click)
{
g.fillOval(currentx, currenty, 100, 100); // problem HERE
}
}
private class MyMouseListener implements MouseListener
{
public void mouseClicked(MouseEvent e)
{
int nowx = e.getX();
int nowy = e.getY();
nowx = nowx / 100;
String stringx = Integer.toString(nowx);
stringx = stringx+"00";
int currentx = Integer.parseInt(stringx);
nowy = nowy /100;
String stringy = Integer.toString(nowy);
stringy = stringy+"00";
int currenty = Integer.parseInt(stringy);
click = true;
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
}
Your main problem is, painting in Swing/AWT is destructive, that is, each time your paint method is called, you are expected to repaint the current state of the component.
In that case, what you really need is some way to model the state of the game so when paint is called, you can repaint it in some meaningful way. This a basic concept of a Model-View-Controller paradigm, where you separate the responsibility of the program into separate layers.
The problem then becomes, how do you translate from the view to model?
The basic idea is take the current x/y coordinates of the mouse and divide it by the cell size. You also need to ensure that the results are within the expected ranges, as you could get a result which is beyond the columns/rows of grids
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
protected static final int CELL_COUNT = 3;
private int[][] board;
private int[] cell;
private boolean isX = true;
public TestPane() {
board = new int[CELL_COUNT][CELL_COUNT];
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int[] cell = getCellAt(e.getPoint());
if (board[cell[0]][cell[1]] == 0) {
board[cell[0]][cell[1]] = isX ? 1 : 2;
isX = !isX;
repaint();
}
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
cell = getCellAt(e.getPoint());
repaint();
}
});
}
protected int[] getCellAt(Point p) {
Point offset = getOffset();
int cellSize = getCellSize();
int x = p.x - offset.x;
int y = p.y - offset.y;
int gridx = Math.min(Math.max(0, x / cellSize), CELL_COUNT - 1);
int gridy = Math.min(Math.max(0, y / cellSize), CELL_COUNT - 1);
return new int[]{gridx, gridy};
}
protected Point getOffset() {
int cellSize = getCellSize();
int x = (getWidth() - (cellSize * CELL_COUNT)) / 2;
int y = (getHeight() - (cellSize * CELL_COUNT)) / 2;
return new Point(x, y);
}
protected int getCellSize() {
return Math.min(getWidth() / CELL_COUNT, getHeight() / CELL_COUNT) - 10;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Point offset = getOffset();
int cellSize = getCellSize();
if (cell != null) {
g2d.setColor(new Color(0, 0, 255, 128));
g2d.fillRect(
offset.x + (cellSize * cell[0]),
offset.y + (cellSize * cell[1]),
cellSize,
cellSize);
}
g2d.setColor(Color.BLACK);
FontMetrics fm = g2d.getFontMetrics();
for (int col = 0; col < CELL_COUNT; col++) {
for (int row = 0; row < CELL_COUNT; row++) {
int value = board[col][row];
int x = offset.x + (cellSize * col);
int y = offset.y + (cellSize * row);
String text = "";
switch (value) {
case 1:
text = "X";
break;
case 2:
text = "O";
break;
}
x = x + ((cellSize - fm.stringWidth(text)) / 2);
y = y + ((cellSize - fm.getHeight()) / 2) + fm.getAscent();
g2d.drawString(text, x, y);
}
}
int x = offset.x;
int y = offset.y;
for (int col = 1; col < CELL_COUNT; col++) {
x = offset.x + (col * cellSize);
g2d.drawLine(x, y, x, y + (cellSize * CELL_COUNT));
}
x = offset.x;
for (int row = 1; row < CELL_COUNT; row++) {
y = offset.x + (row * cellSize);
g2d.drawLine(x, y, x + (cellSize * CELL_COUNT), y);
}
g2d.dispose();
}
}
}
First off, if you want to truncate a number to the nearest 100, e.g. 142 becomes 100, all you have to do is:
num = (num/100)*100;
this is because when you divide 2 integers it automatically truncates it, and you can just multiply it back to get the number. And what I think you want in this case is to create some field variables and some accessor methods. At the top of your MouseListener class, you will need to add:
private int mouseX=0;
private int mouseY=0;
then to be able to access these variables from outside of the mouselistener class you will need to add accessor methods:
public int getMouseX(){
return mouseX;
}
in your Grid Class, you can add the field:
private MyMouseListener listener;
and then initialize it in your init by doing:
listener = new MyMouseListener();
addMouseListener(listener);
then you can do the same for mouseY, and finally from your paint method you can then call:
int mouseX = listener.getMouseX();
int mouseY = listener.getMouseY();
and from there it is as simple as doing if statements or switch statements to find which box you clicked in!

How to move the image inside the JApplet in vertical line?

I have displayed an image(ball) inside the JApplet, now I want the image to move in a vertical way (up and down). The problem is I don't know how to do it.
Could someone has an idea about this matter?
You need to set the position of that image to some calculated value (means you caculate the vertical position using time, speed and maybe other restrictions).
How you'd set that position depends on how you draw the image.
Example, based on drawing in the applet's (or a nested component's) paint(Graphics g) method:
//first calculate the y-position
int yPos += timeSinceLastPaint * speed; //increment the position
if( (speed > 0 && yPos > someMaxY) || (speed < 0 && yPos <0 ) ) {
speed *= -1; //if the position has reached the bottom (max y) or the top invert the direction
}
//in your paint(Graphics g) method:
g.drawImage(image, yPos, x, null);
Then you'd have to constantly repaint the applet.
More information on animations in applets can be found here: http://download.oracle.com/javase/tutorial/uiswing/components/applet.html
another example for javax.swing.Timer with moving Ojbects created by paintComponent(Graphics g), and I have lots of Start, not some blurred Mikado :-)
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class AnimationBackground {
private Random random = new Random();
private JFrame frame = new JFrame("Animation Background");
private final MyJPanel panel = new MyJPanel();
private JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER);
private JPanel stopPanel = new JPanel();
private JPanel startPanel = new JPanel();
public AnimationBackground() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
panel.setBackground(Color.BLACK);
for (int i = 0; i < 50; i++) {
Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155)));
star.setxIncr(-3 + random.nextInt(7));
star.setyIncr(-3 + random.nextInt(7));
panel.add(star);
}
panel.setLayout(new GridLayout(10, 1));
label.setForeground(Color.WHITE);
panel.add(label);
stopPanel.setOpaque(false);
stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.stopAnimation();
}
}));
panel.add(stopPanel);
startPanel.setOpaque(false);
startPanel.add(new JButton(new AbstractAction("Start moving...") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.startAnimation();
}
}));
panel.add(startPanel);
frame.add(panel);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AnimationBackground aBg = new AnimationBackground();
}
});
}
private class Star extends Polygon {
private static final long serialVersionUID = 1L;
private Point location = null;
private Color color = Color.YELLOW;
private int xIncr, yIncr;
static final int WIDTH = 500, HEIGHT = 500;
Star(Point location) {
int x = location.x;
int y = location.y;
this.location = location;
this.addPoint(x, y + 8);
this.addPoint(x + 8, y + 8);
this.addPoint(x + 11, y);
this.addPoint(x + 14, y + 8);
this.addPoint(x + 22, y + 8);
this.addPoint(x + 17, y + 12);
this.addPoint(x + 21, y + 20);
this.addPoint(x + 11, y + 14);
this.addPoint(x + 3, y + 20);
this.addPoint(x + 6, y + 12);
}
public void setColor(Color color) {
this.color = color;
}
public void move() {
if (location.x < 0 || location.x > WIDTH) {
xIncr = -xIncr;
}
if (location.y < 0 || location.y > WIDTH) {
yIncr = -yIncr;
}
translate(xIncr, yIncr);
location.setLocation(location.x + xIncr, location.y + yIncr);
}
public void setxIncr(int xIncr) {
this.xIncr = xIncr;
}
public void setyIncr(int yIncr) {
this.yIncr = yIncr;
}
public Color getColor() {
return color;
}
}
private class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Star> stars = new ArrayList<Star>();
private Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Star star : stars) {
star.move();
}
repaint();
}
});
public void stopAnimation() {
if (timer.isRunning()) {
timer.stop();
}
}
public void startAnimation() {
if (!timer.isRunning()) {
timer.start();
}
}
#Override
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
MyJPanel() {
this.setPreferredSize(new Dimension(512, 512));
}
public void add(Star star) {
stars.add(star);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Star star : stars) {
g.setColor(star.getColor());
g.fillPolygon(star);
}
}
}
}
How to move the image inside the JApplet ..?
Pretty much exactly the same way you might do it in a JFrame, JComponent or JPanel or...
Or to put that another way, nothing to do with applets and everything to do with Graphics2D. For more details, see the 2D Graphics Trail of the Java Tutorial.
When you've figured how to move an image and paint it to a Graphics2D, implement that logic in a JComponent or JPanel's paintComponent(Graphics) method and drop the component with moving image into a JApplet or JFrame (or a JPanel etc.).
For the animation side of it, use a javax.swing.Timer as seen in this example. This example does not extend any component. Instead, it creates a BufferedImage and adds it to a JLabel that is displayed to the user. When the timer fires, the code grabs the Graphics object of the image, and proceeds from there to draw the bouncing lines.
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
class LineAnimator {
public static void main(String[] args) {
final int w = 640;
final int h = 480;
final RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
hints.put(
RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY
);
final BufferedImage bi = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);
final JLabel l = new JLabel(new ImageIcon(bi));
final BouncingLine[] lines = new BouncingLine[100];
int factor = 1;
for (int ii=0; ii<lines.length; ii++) {
lines[ii] = new BouncingLine(w*factor,h*factor);
}
final Font font = new Font("Arial", Font.BOLD, 30);
ActionListener al = new ActionListener() {
int count = 0;
long lastTime;
String fps = "";
private final BasicStroke stroke = new BasicStroke(6);
public void actionPerformed(ActionEvent ae) {
count++;
Graphics2D g = bi.createGraphics();
g.setRenderingHints(hints);
g.setColor(new Color(55,12,59));
g.fillRect(0,0,w,h);
g.setStroke(stroke);
for (int ii=0; ii<lines.length; ii++) {
lines[ii].move();
lines[ii].paint(g);
}
if ( System.currentTimeMillis()-lastTime>1000 ) {
lastTime = System.currentTimeMillis();
fps = count + " FPS";
count = 0;
}
g.setColor(Color.YELLOW);
g.setFont(font);
g.drawString(fps,5,h-5);
l.repaint();
g.dispose();
}
};
Timer timer = new Timer(25,al);
timer.start();
JOptionPane.showMessageDialog(null, l);
//System.exit(0);
timer.stop();
}
}
class BouncingLine {
private final Color color;
private static final Random random = new Random();
Line2D line;
int w;
int h;
int x1;
int y1;
int x2;
int y2;
BouncingLine(int w, int h) {
line = new Line2D.Double(random.nextInt(w),random.nextInt(h),random.nextInt(w),random.nextInt(h));
this.w = w;
this.h = h;
this.color = new Color(
random.nextInt(255)
,random.nextInt(255)
,random.nextInt(255)
,64+random.nextInt(128)
);
x1 = (random.nextBoolean() ? 1 : -1);
y1 = (random.nextBoolean() ? 1 : -1);
x2 = -x1;
y2 = -y1;
}
public void move() {
int tx1 = 0;
if (line.getX1()+x1>0 && line.getX1()+x1<w) {
tx1 = (int)line.getX1()+x1;
} else {
x1 = -x1;
tx1 = (int)line.getX1()+x1;
}
int ty1 = 0;
if (line.getY1()+y1>0 && line.getY1()+y1<h) {
ty1 = (int)line.getY1()+y1;
} else {
y1 = -y1;
ty1 = (int)line.getY1()+y1;
}
int tx2 = 0;
if (line.getX2()+x2>0 && line.getX2()+x2<w) {
tx2 = (int)line.getX2()+x2;
} else {
x2 = -x2;
tx2 = (int)line.getX2()+x2;
}
int ty2 = 0;
if (line.getY2()+y2>0 && line.getY2()+y2<h) {
ty2 = (int)line.getY2()+y2;
} else {
y2 = -y2;
ty2 = (int)line.getY2()+y2;
}
line.setLine(tx1,ty1,tx2,ty2);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(color);
//line.set
g2.draw(line);
}
}
Update 1
I want to do it in JApplet(1) using the image(2), is it possible(3)?
The examples by mKorbel and myself feature either an image in a JLabel or custom rendering in a JPanel. In our case, we added the components to a JOptionPane & a JFrame. Either example could be just as easily added to a JApplet, or a JDialog, or as part of another panel, or.. See the Laying Out Components Within a Container lesson & Using Top-Level Containers in the Java Tutorial for more details.
Instead of the stars or lines in our examples, ..paint your image. My example goes so far as to demonstrate how to get the position to bounce around within the bounds of the container.
Sure it is possible, but "Batteries not included". Our intention is to give you some ideas that you can then adapt to your bouncing ball applet. I doubt anyone is going to create an example for you, using balls, in an applet. Though if you post an SSCCE that shows your intent and what you tried, I (and others) would often run with that source. If you want more specific answers, ask a more specific SSCCE. ;)
I want to do it in JApplet.
Why not both? You can have a hybrid application/applet as shown in this animation.

repaint problem

I have a problem with my repaint in the method move. I dont know what to doo, the code is below
import java.awt.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
import java.lang.*;
public class bbb extends JPanel
{
public Stack<Integer> stacks[];
public JButton auto, jugar, nojugar;
public JButton ok, ok2;
public JLabel info = new JLabel("Numero de Discos: ");
public JLabel instruc = new JLabel("Presiona la base de las torres para mover las fichas");
public JLabel instruc2 = new JLabel("No puedes poner una pieza grande sobre una pequenia!");
public JComboBox numeros = new JComboBox();
public JComboBox velocidad = new JComboBox();
public boolean seguir = false, parar = false, primera = true;
public int n1, n2, n3;
public int click1 = 0;
public int opcion = 1, tiempo = 50;
public int op = 1, continuar = 0, cont = 0;
public int piezas = 0;
public int posx, posy;
public int no;
public bbb() throws IOException
{
stacks = new Stack[3];
stacks[0] = new Stack<Integer>();
stacks[1] = new Stack<Integer>();
stacks[2] = new Stack<Integer>();
setPreferredSize(new Dimension(1366, 768));
ok = new JButton("OK");
ok.setBounds(new Rectangle(270, 50, 70, 25));
ok.addActionListener(new okiz());
ok2 = new JButton("OK");
ok2.setBounds(new Rectangle(270, 50, 70, 25));
ok2.addActionListener(new vel());
add(ok2);
ok2.setVisible(false);
auto = new JButton("Automatico");
auto.setBounds(new Rectangle(50, 80, 100, 25));
auto.addActionListener(new a());
jugar = new JButton("PLAY");
jugar.setBounds(new Rectangle(100, 100, 70, 25));
jugar.addActionListener(new play());
nojugar = new JButton("PAUSE");
nojugar.setBounds(new Rectangle(100, 150, 70, 25));
nojugar.addActionListener(new stop());
setLayout(null);
info.setBounds(new Rectangle(50, 50, 170, 25));
info.setForeground(Color.white);
instruc.setBounds(new Rectangle(970, 50, 570, 25));
instruc.setForeground(Color.white);
instruc2.setBounds(new Rectangle(970, 70, 570, 25));
instruc2.setForeground(Color.white);
add(instruc);
add(instruc2);
add(jugar);
add(nojugar);
jugar.setVisible(false);
nojugar.setVisible(false);
add(info);
info.setVisible(false);
add(ok);
ok.setVisible(false);
add(auto);
numeros.setBounds(new Rectangle(210, 50, 50, 25));
numeros.addItem(1);
numeros.addItem(2);
numeros.addItem(3);
numeros.addItem(4);
numeros.addItem(5);
numeros.addItem(6);
numeros.addItem(7);
numeros.addItem(8);
numeros.addItem(9);
numeros.addItem(10);
add(numeros);
numeros.setVisible(false);
velocidad.setBounds(new Rectangle(150, 50, 100, 25));
velocidad.addItem("Lenta");
velocidad.addItem("Intermedia");
velocidad.addItem("Rapida");
add(velocidad);
velocidad.setVisible(false);
}
public void Mover(int origen, int destino)
{
for (int i = 0; i < 3; i++)
{
System.out.print("stack " + i + ": ");
for (int n : stacks[i])
{
System.out.print(n + ";");
}
System.out.println("");
}
System.out.println("de <" + origen + "> a <" + destino + ">");
stacks[destino].push(stacks[origen].pop());
System.out.println("");
this.validate();
this.repaint();
}
public void hanoi(int origen, int destino, int cuantas)
{
while (parar)
{
}
if (cuantas <= 1)
{
Mover(origen, destino);
}
else
{
hanoi(origen, 3 - (origen + destino), cuantas - 1);
Mover(origen, destino);
hanoi(3 - (origen + destino), destino, cuantas - 1);
}
}
public void paintComponent(Graphics g)
{
ImageIcon fondo = new ImageIcon("fondo.jpg");
g.drawImage(fondo.getImage(), 0, 0, 1366, 768, null);
g.setColor(new Color((int) (Math.random() * 254),
(int) (Math.random() * 255),
(int) (Math.random() * 255)));
g.fillRect(0, 0, 100, 100);
g.setColor(Color.white);
g.fillRect(150, 600, 250, 25);
g.fillRect(550, 600, 250, 25);
g.fillRect(950, 600, 250, 25);
g.setColor(Color.red);
g.fillRect(270, 325, 10, 275);
g.fillRect(270 + 400, 325, 10, 275);
g.fillRect(270 + 800, 325, 10, 275);
int x, y, top = 0;
g.setColor(Color.yellow);
x = 150;
y = 580;
for (int ii : stacks[0])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
x = 550;
y = 580;
for (int ii : stacks[1])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
x = 950;
y = 580;
for (int ii : stacks[2])
{
g.fillRect(x + ((ii * 125) / 10), y - (((ii) * 250) / 10), ((10 - ii) * 250) / 10, 20);
}
System.out.println("ENTRO");
setOpaque(false);
}
private class play implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
parar = false;
if (primera = true)
{
hanoi(0, 2, no);
primera = false;
}
}
}
private class stop implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
parar = true;
}
}
private class vel implements ActionListener //manual
{
public void actionPerformed(ActionEvent algo)
{
if (velocidad.getSelectedItem() == "Lenta")
{
tiempo = 150;
}
else if (velocidad.getSelectedItem() == "Intermedia")
{
tiempo = 75;
}
else
{
tiempo = 50;
}
ok2.setVisible(false);
jugar.setVisible(true);
nojugar.setVisible(true);
}
}
private class a implements ActionListener //auto
{
public void actionPerformed(ActionEvent algo)
{
auto.setVisible(false);
info.setVisible(true);
numeros.setVisible(true);
ok.setVisible(true);
op = 3;
}
}
private class okiz implements ActionListener //ok
{
public void actionPerformed(ActionEvent algo)
{
no = Integer.parseInt(numeros.getSelectedItem().toString());
piezas = no;
if (no > 0 && no < 11)
{
info.setVisible(false);
numeros.setVisible(false);
ok.setVisible(false);
for (int i = no; i > 0; i--)
{
stacks[0].push(i);
}
opcion = 2;
if (op == 3)
{
info.setText("Velocidad: ");
info.setVisible(true);
velocidad.setVisible(true);
ok2.setVisible(true);
}
}
else
{
}
repaint();
}
}
}
the code of the other class that calls the one up is below:
import java.awt.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.border.*;
import java.lang.*;
import java.awt.event.*;
public class aaa extends JPanel
{
private ImageIcon Background;
private JLabel fondo;
public static void main(String[] args) throws IOException
{
JFrame.setDefaultLookAndFeelDecorated(true);
final JPanel cp = new JPanel(new BorderLayout());
JFrame frame = new JFrame ("Torres de Hanoi");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize(550,550);
frame.setVisible(true);
bbb panel = new bbb();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Assuming that you see the progress in the println statements but not on the screen, it is because a call to repaint is not synchronous. Swing has a special thread for handling UI - called Event Dispatch Thread. A call to repaint is handled by that thread, but asynchronously - after all the current events scheduled on that thread have been processed.
When you call hanoi in your actionPerformed, that is done on the same UI thread. What happens is that until your recursion is fully done, repaint() calls are just queued. Once the recursion completes (and all stacks have been moved in the model), the UI thread processes all repaint() requests, painting - what i assume - the final state.
What you need to do is to separate the model processing into a separate worker thread. On every recursion step, issue a repaint() call and sleep for a few hundred milliseconds. This will allow the UI thread to repaint the current state of the model and let the user actually trace the progress.

Categories

Resources