How to wait for user input in applet textfield - java

How can i get my program to wait until the user inputs something into a textfield before my program checks if it is equal.
When i searched online I only saw results for Jtextfields not textfields and idk know if the same things will work for both. Also they were all really complicated and beyond my level. Is there a simpler way or someone willing to explain the more complicated way. Below is the necessary code.
The textfield is called Answer and i assign ananswer to the input, then compare it to realanswer
public void getquestion (int level, Graphics g)
{
Answer.setVisible (true);
double realanswer;
super.paint (g);
int shape = 1;
if (shape == 1)
{
double radius = 0;
double height = 0;
double diameter = 0;
double volume = 0;
double surfacearea = 0;
double radius2 = 0;
double height2 = 0;
realanswer = 0;
switch (level)
{
case 1:
g.drawImage (cylinder, 100, 150, this);
radius = 1 + (int) (Math.random () * 10);
height = 1 + (int) (Math.random () * 10);
g.drawString ("The Height of the Cylinder is " + height, 400, 100);
g.drawString ("The Radius of the Cylinder is " + radius, 400, 120);
g.drawString ("What is the volume of the Cylinder?", 100, 140);
realanswer = Math.round(Math.PI * radius * radius * height);
break;
default:
height2 = 1 + (Math.random () * 100);
radius2 = 1 + (Math.random () * 100);
height = height2 + (Math.random () * 100);
radius = radius2 + (Math.random () * 100);
break;
}
if (realanswer == ananswer)
{
g.drawImage (mathmeme1, 100, 150, this);
}
else
{
g.drawImage (fail1, 100, 150, this);
}
}
}
public void actionPerformed (ActionEvent evt)
{
ananswer = Integer.parseInt (Answer.getText ());
}

Related

JPanel drawn with extra width

I have a Stratego board being drawn on a JPanel, being used to set up the player's pieces. After two different instances of these panels are correctly arranged by the players, the main board (that has the same format and layout, just will have different piece appearance and logical behavior) will show.
My issue is that the second input panel and the main board (which currently has no functionality or pieces on it) are SOMETIMES set up with extra width on the bottom and the right, causing the 10x10 grid to not take up the entire board space like it should.
The initial input panel for player 1 seems to be working fine, never having this problem. The second panel and the main panel only SOMETIMES have this issue, so I'm not entirely sure where this is stemming from.
Here is the main method which sets up the panels and stuff.
public class Core {
public static void main(String[] args) {
LogicInterpreter logic = new LogicInterpreter();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
InputFrame inputPlayer1 = new InputFrame(logic, 1, "red", 600, 600);
inputPlayer1.setLocation(dim.width / 2 - inputPlayer1.getSize().width/2,
dim.height / 2 - inputPlayer1.getSize().height / 2);
while(!logic.isSetUp1()){
//Just to make it work
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Now bring up board 2
InputFrame inputPlayer2 = new InputFrame(logic, 2, "blue", 600, 600);
inputPlayer2.setLocation(dim.width / 2 - inputPlayer2.getSize().width/2,
dim.height / 2 - inputPlayer2.getSize().height / 2);
while(!logic.isSetUp2()){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
openBoards(logic);
}
public static void openBoards(LogicInterpreter logic) {
try {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
MainBoard board = new MainBoard(logic);
board.setLocation(dim.width / 2 - board.getSize().width / 2, dim.height / 2 - board.getSize().height / 2);
} catch (Exception e) {
System.exit(1);
}
}
}
Also, here is the code inside the input panels. I'm not sure what is relevant, so I can't take stuff out. Sorry. I will withhold the main board setup code because it is really the same.
public class InputFrame extends JFrame {
private static final long serialVersionUID = 1L;
private LogicInterpreter holder;
private Panel2 jp;
private int height, width;
private Map<Integer, ArrayList<Integer>> lakeCoords = new HashMap<>();
private List<Piece> pieces = new ArrayList<>();
private int playernumber;
private String playerColor;
Piece selectedPiece;
Piece secondSelectedPiece;
boolean hidePieces = false;
JButton submit = new JButton("SUBMIT");
public void addCoords() {
lakeCoords.put(3, new ArrayList<Integer>(Arrays.asList(6, 5)));
lakeCoords.put(4, new ArrayList<Integer>(Arrays.asList(6, 5)));
lakeCoords.put(7, new ArrayList<Integer>(Arrays.asList(6, 5)));
lakeCoords.put(8, new ArrayList<Integer>(Arrays.asList(6, 5)));
}
public void createPieces() {
int y = 1;
if (playernumber == 2) {
y = 7;
}
List<Integer> openValues = new ArrayList<>();
openValues.add(1);
openValues.add(2);
openValues.add(11);
openValues.add(12);
for (int x = 0; x < 2; x++) {
openValues.add(3);
}
for (int x = 0; x < 3; x++) {
openValues.add(4);
}
for (int x = 0; x < 4; x++) {
openValues.add(5);
openValues.add(6);
openValues.add(7);
}
for (int x = 0; x < 5; x++) {
openValues.add(8);
}
for (int x = 0; x < 8; x++) {
openValues.add(9);
}
for (int x = 0; x < 6; x++) {
openValues.add(10);
}
Collections.sort(openValues);
System.out.println(openValues.size());
System.out.println(pieces.size());
for (int x = 1; x <= 10; x++) {
for (int z = y; z <= y + 3; z++) {
// 1x1 Marshal
// 2x1 General
// 3x2 Colonel
// 4x3 Major
// 5x4 Captain
// 6x4 Lieutenant
// 7x4 Sergeant
// 8x5 Miner
// 9x8 Scout
// 10x6 Bomb
// 11x1 Flag
// 12x1 Spy
Piece piece = new Piece(new Coords(x, z), openValues.get(0), playerColor);
openValues.remove(0);
pieces.add(piece);
}
}
}
public InputFrame(LogicInterpreter holder, int playerNumber, String playerColor, int height, int width) {
this.height = height;
this.width = width;
playernumber = playerNumber;
this.playerColor = playerColor;
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
addCoords();
this.holder = holder;
createPieces();
jp = new Panel2(height, width);
setResizable(false);
jp.setBackground(new Color(235, 202, 158));
setTitle("Player " + playerNumber + " Arrangement GUI || Click Submit When Ready");
jp.setPreferredSize(new Dimension(600, 600));
jp.setLayout(null);
jp.addMouseListener(new HandleMouse());
if(playernumber == 1)
submit.setBounds(width / 10 * 4, height / 10 * 7, width / 10 * 2, height / 10 * 2);
else
submit.setBounds(width / 10 * 4, height / 10, width / 10 * 2, height / 10 * 2);
submit.setFont(new Font("Arial", Font.BOLD, width * 20 / 600));
submit.setBackground(Color.LIGHT_GRAY);
submit.addActionListener(new CloseListener(this));
jp.add(submit);
getContentPane().add(jp);
pack();
setVisible(true);
}
class CloseListener implements ActionListener {
private InputFrame frame;
public CloseListener(InputFrame frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent event) {
// Do the stuff here before closing
hidePieces = true;
repaint();
if (playernumber == 1) {
holder.setP1Pieces(pieces);
JOptionPane.showMessageDialog(null, "Press When Ready for Next Player");
holder.setSetUp1(true);
} else {
holder.setP2Pieces(pieces);
JOptionPane.showMessageDialog(null, "Press When Player 1 is Ready");
holder.setSetUp2(true);
}
frame.dispose();
}
}
public class Panel2 extends JPanel {
private static final long serialVersionUID = 1L;
int height = 0;
int width = 0;
public Panel2(int height, int width) {
this.height = height;
this.width = width;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int x = 0; x < width; x += width / 10) {
for (int y = 0; y < height; y += height / 10) {
boolean fill = false;
for (Entry<Integer, ArrayList<Integer>> coords : lakeCoords.entrySet()) {
if ((coords.getKey() - 1 == x / 60 && coords.getValue().get(0) - 1 == y / 60)
|| (coords.getKey() - 1 == x / 60 && coords.getValue().get(1) - 1 == y / 60)) {
fill = true;
break;
}
}
if (fill) {
g.setColor(Color.BLUE);
g.fillRect(x, y, width / 10, height / 10);
g.setColor(Color.BLACK);
g.drawRect(x, y, width / 10, height / 10);
} else {
g.setColor(Color.BLACK);
g.drawRect(x, y, width / 10, height / 10);
}
}
}
if(hidePieces){
for (Piece piece : pieces) {
try {
g.drawImage(ImageIO.read(new File(playerColor + "_pieces/" + (playerColor.equals("blue") ? "Blue" : "Red") + "_Strat_Piece"
+ ".png")), piece.getX() * width / 10 - width / 10,
piece.getY() * height / 10 - height / 10, width / 10, height / 10, null);
} catch(Exception e){}
}
} else {
for (Piece piece : pieces) {
g.drawImage(piece.getImage(), piece.getX() * width / 10 - width / 10,
piece.getY() * height / 10 - height / 10, width / 10, height / 10, null);
}
if (selectedPiece != null) {
g.setColor(Color.BLUE);
g.drawImage(selectedPiece.getImage(), selectedPiece.getX() * width / 10 - width / 10,
selectedPiece.getY() * height / 10 - height / 10, width / 10, height / 10, null);
g.drawRect(selectedPiece.getX() * width / 10 - width / 10,
selectedPiece.getY() * height / 10 - height / 10, width / 10, height / 10);
}
}
}
}
private class HandleMouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Coords coordinates = holder.getClickedBox(x, y, width, height);
boolean found = false;
boolean move = false;
for (Piece piece : pieces) {
if (piece.getX() == coordinates.getX() && piece.getY() == coordinates.getY()) {
found = true;
if (selectedPiece == null) {
selectedPiece = piece;
} else {
move = true;
secondSelectedPiece = piece;
}
}
}
if (move) {
pieces.remove(selectedPiece);
pieces.remove(secondSelectedPiece);
Coords storage = selectedPiece.getCoords();
selectedPiece.setCoords(secondSelectedPiece.getCoords());
secondSelectedPiece.setCoords(storage);
pieces.add(selectedPiece);
pieces.add(secondSelectedPiece);
selectedPiece = null;
secondSelectedPiece = null;
} else if (!found) {
if (selectedPiece != null) {
selectedPiece = null;
}
}
repaint();
}
}
}
Did you check how many pixels are "sometimes" added?
When i call setResizable(true) on my jframe, i notice that "sometimes" there are 10 pixels more, both in width and height, than i expect.
If this is your case, i answered a similar question here.
I was able to solve the problem using a 'trick', calling pack more than one time.
In the answer i also linked another similar question (this one), where i wasn't able to find another solution, but there some users described the bug.

How to bend an Image in java

Is there any way to bend a BufferedImage in Java?
I thought that if I crop the image into smaller pieces and rotate them then I would essentially bend the image, but it doesn't seem to work.
Here is the method I created:
/**
* This is a recursive method that will accept an image the point where the bending will start and the point where the bending will end, as well as the angle of bending
*
* #param original:the original image
* #param startingPoint: the point where the bending should start
* #param endingPoint: the point where the bending should end
* #param radiands: the angle
* #return the bent image
*/
public static BufferedImage getBentImage(BufferedImage original, int startingPoint, int endingPoint, double radians) {
if (startingPoint >= endingPoint)
return original;
int type = BufferedImage.TYPE_INT_ARGB;
int width = original.getWidth();
int height = original.getHeight();
BufferedImage crop = original.getSubimage(0, 0, startingPoint, height);
BufferedImage crop0 = original.getSubimage(startingPoint, 0, width - startingPoint, height);
BufferedImage bendCrop = new BufferedImage(width, height, type);
BufferedImage image = new BufferedImage(width, height, type);
AffineTransform rotation = new AffineTransform();
rotation.translate(0, 0);
rotation.rotate(radians);
Graphics2D g = bendCrop.createGraphics();
g.drawImage(crop0, rotation, null);
g.dispose();
g = image.createGraphics();
g.drawImage(crop, 0, 0, null);
g.drawImage(bendCrop, startingPoint, 0, null);
g.dispose();
return getBentImage(image, startingPoint + 1, endingPoint, radians);
}
This is the original Image:
And this is the result of this getBentImage(image, 200, 220, Math.toRadians(1)):
I was expecting something closer to:
Any ideas on how to actually implement a getBentImage() method?
As suggested in the comments, a simple approach is to divide the image into 3 parts:
Identical to the original.
Bent according to the bending transformation.
Constant diagonal continuation.
Here is a quick and a bit messy example that shows the original shape and the resulting shape below it. I just used a label icon for the images instead of doing custom painting. (Also I didn't adhere to the Java naming conventions with final variables because it's math and not typical coding.)
Since there are quite a few variables in the calculation code, I added a sketch at the end that shows what the variables represent.
public class Main extends JFrame {
static BufferedImage image;
public static void main(String[] args) {
try {
image = ImageIO.read(ClassLoader.getSystemResource("img.png"));
} catch (IOException e) {
e.printStackTrace();
}
new Main();
}
public Main() {
getContentPane().setLayout(new BorderLayout(5, 10));
BufferedImage img2 = transform(15, 100, 300);
JLabel label1 = new JLabel(new ImageIcon(image));
label1.setHorizontalAlignment(JLabel.LEFT);
label1.setOpaque(true);
label1.setBackground(Color.YELLOW);
add(label1, BorderLayout.NORTH);
JLabel label2 = new JLabel(new ImageIcon(img2));
label2.setHorizontalAlignment(JLabel.LEFT);
label2.setOpaque(true);
label2.setBackground(Color.CYAN);
add(label2);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
static BufferedImage transform(int t, int x1, int x2) {
final double TH = Math.toRadians(t);
final int D = x2 - x1;
final int W = image.getWidth();
final int H = image.getHeight();
final int dD = (int) (D / (2 * TH) * Math.sin(2 * TH));
final int dH = (int) (D / TH * Math.pow(Math.sin(TH), 2));
final int pH = (int) ((W - x2) * Math.tan(2 * TH));
final int width = W - (D - dD);
final int height = (int) (H + dH + pH);
System.out.println(W + " " + H + " -> " + width + " " + height);
BufferedImage img2 = new BufferedImage(width, height, image.getType());
for (int x = 0; x < x1; x++) {
for (int y = 0; y < H; y++) {
int rgb = image.getRGB(x, y);
img2.setRGB(x, y, rgb);
}
}
for (int x = x1; x < x2; x++) {
for (int y = 0; y < H; y++) {
int rgb = image.getRGB(x, y);
int dx = (int) (D / (2 * TH) * Math.sin(2 * (x-x1) * TH / D));
int dy = (int) (D / TH * Math.pow(Math.sin((x-x1) * TH / D), 2));
img2.setRGB(x1 + dx, y + dy, rgb);
}
}
for (int x = x2; x < W; x++) {
for (int y = 0; y < H; y++) {
int rgb = image.getRGB(x, y);
int dp = (int) ((x - x2) * Math.tan(2 * TH));
img2.setRGB(x - (D - dD), y + dH + dp, rgb);
}
}
return img2;
}
}
As for the calculations, I'll leave it for you as homework; it's just geometry/trigonometry which belongs on Math.SE more than on SO. If you can't figure it out I'll give you a direction.
Note that this method might not be fast at all and could certainly be optimized, I'll leave that to you also. Oh, and rounding doubles to ints carelessly, so the result is not pixel-perfect.
I dont know what you mean by bending but essentially you have a rectangle and you break one piece of it and rotate it:
so the algorithm is as follows:
rotate line(x, 0, width-1, 0)
rotate line(x, height-1, width-1, height-1)
connect the pieces
So essentially you are looking for rotate line.

PieChart in java not showing

My piechart in java isn't showing, for my class we are to make a piechart using graphics and the values are user-input based. even after trying to input any values, my piechart would not show up at all.
What am i doing wrong?
My code:
package ass15;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.HeadlessException;
import javax.swing.JFrame;
public class PieChart extends JFrame {
private int iNorth, iSouth, iEast, iWest, iMidWest;
public PieChart(int North, int South, int East, int West, int MidWest) throws HeadlessException {
super("Assignment 15");
this.iNorth = North;
this.iSouth = South;
this.iEast = East;
this.iWest = West;
this.iMidWest = MidWest;
}
public void Paint(Graphics g) {
//Integer to percent
double dNorth,dSouth,dEast,dWest,dMidWest, total;
dNorth = 0.00 + iNorth;
dSouth = 0.00 + iSouth;
dEast = 0.00 + iEast;
dWest = 0.00 + iWest;
dMidWest = 0.00 + iMidWest;
total = dNorth + dSouth + dEast + dWest + dMidWest;
//initial arc
int startAngle = 0;
double curValue = 0.00;
startAngle = (int) (curValue * 360/total);
int arcAngle = (int) (dNorth * 360/total);
g.setColor(Color.red);
g.fillArc(50, 50, 100, 100, startAngle, arcAngle);
//new arc
curValue += dNorth;
startAngle = (int) (curValue * 360/total);
arcAngle = (int) (dSouth * 360/total);
g.setColor(Color.green);
g.fillArc(50, 50, 50, 50, startAngle, arcAngle);
//new arc
curValue += dSouth;
startAngle = (int) (curValue * 360/total);
arcAngle = (int) (dEast * 360/total);
g.setColor(Color.blue);
g.fillArc(50, 50, 50, 50, startAngle, arcAngle);
//new arc
curValue += dEast;
startAngle = (int) (curValue * 360/total);
arcAngle = (int) (dWest * 360/total);
g.setColor(Color.magenta);
g.fillArc(50, 50, 50, 50, startAngle, arcAngle);
//new arc
curValue += dWest;
startAngle = (int) (curValue * 360/total);
arcAngle = (int) (dMidWest * 360/total);
g.setColor(Color.yellow);
g.fillArc(50, 50, 50, 50, startAngle, arcAngle);
//background circle
g.setColor( Color.black );
g.drawArc( 50, 50, 50, 50, 0, 360 );
}
}
and my main is:
package ass15;
import java.util.StringTokenizer;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class TestPieChart {
public static void main(String[] args) {
int north,south,east,west,midwest;
String token;
String in = "";
in = JOptionPane.showInputDialog("Input sales for regions");
StringTokenizer stk = new StringTokenizer(in, ",");
token = stk.nextToken().trim();
north = Integer.parseInt(token);
token = stk.nextToken().trim();
south = Integer.parseInt(token);
token = stk.nextToken().trim();
east = Integer.parseInt(token);
token = stk.nextToken().trim();
west = Integer.parseInt(token);
token = stk.nextToken().trim();
midwest = Integer.parseInt(token);
PieChart pi = new PieChart(north,south,east,west,midwest);
pi.setVisible(true);
pi.setSize(500, 500);
}
}
It was a stupid mistake...
ANSWER:
the method
Paint(Graphics g)
should be
paint(Graphics g)
did not realize that until i played with the code.

Change Hue of Picture in Graphics

Ok so i need help changing the hue of this slider. I cant seem to figure it out. Please no #override. I need something that will run on Ready to Program. The hue will change back to normal when the slider is back at 0. I dont need to get too complex. Just a simple Hue slider will be great. Thanks!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.applet.Applet;
import javax.swing.event.*;
import java.applet.*;
public class test extends Applet implements ActionListener, ChangeListener
{
//Widgets, Panels
JSlider slider;
Panel flow;
int colorr;
int colorg;
int colorb;
int stars;
//House Coordinates, initialized to 1. (Top Right and No Scaling)
public void init ()
{ //Set Up Input Fields for House Coordinates
resize (380, 240);
setBackground (new Color (102, 179, 255));
slider = new JSlider ();
slider.setValue (0);
slider.setBackground (new Color (102, 179, 255));
slider.setForeground (Color.white);
slider.setMajorTickSpacing (20);
slider.setMinorTickSpacing (5);
slider.setPaintTicks (true);
slider.addChangeListener (this);
//Set up layout, add widgets
setLayout (new BorderLayout ());
flow = new Panel (new FlowLayout ());
flow.add (slider);
add (flow, "South");
}
public void paint (Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
Color color1 = getBackground ();
Color color2 = color1.darker ();
int x = getWidth ();
int y = getHeight () - 30;
GradientPaint gp = new GradientPaint (
0, 0, color1,
0, y, color2);
g2d.setPaint (gp);
g2d.fillRect (0, 0, x, y);
stars (10, 10);
}
public void stars (int x, int y)
{
Graphics g = getGraphics ();
//sun
g.setColor (new Color (139, 166, 211));
g.fillOval (-200, 170, 1000, 400);
g.setColor (new Color (206, 75, 239));
g.fillOval (x, y, 10, 10); //First medium star
g.drawLine (x + 5, y, x + 5, 0);
g.drawLine (x, y + 5, 0, y + 5);
g.drawLine (x + 5, y + 10, x + 5, y + 20);
g.drawLine (x + 10, y + 5, x + 20, y + 5);
g.fillOval (x + 80, y + 30, 12, 12); //Middle medium star
g.drawLine (x + 86, y + 30, x + 86, y + 18);
g.drawLine (x + 80, y + 36, x + 68, y + 36);
g.drawLine (x + 92, y + 36, x + 104, y + 36);
g.drawLine (x + 86, y + 42, x + 86, y + 52);
colorr = (int) (Math.random () * 255) + 1;
colorg = (int) (Math.random () * 255) + 1;
colorb = (int) (Math.random () * 255) + 1;
int randomx = (int) (Math.random () * 300) + 10;
int randomy = (int) (Math.random () * 150) + 10;
stars = 50; //Change for more stars
int ax[] = new int [stars];
int ay[] = new int [stars];
for (int i = 0 ; i < stars ; i++)
{
g.setColor (new Color (colorr, colorg, colorb));
colorr = (int) (Math.random () * 255) + 1;
colorg = (int) (Math.random () * 255) + 1;
colorb = (int) (Math.random () * 255) + 1;
while ((randomx > 88 && randomx < 116) && (randomy < 65 && randomy > 15))
{
randomx = (int) (Math.random () * 300) + 10;
randomy = (int) (Math.random () * 150) + 10;
}
while ((randomx > 0 && randomx < 25) && (randomy > 5 && randomy < 35))
{
randomx = (int) (Math.random () * 300) + 10;
randomy = (int) (Math.random () * 150) + 10;
}
g.drawOval (randomx, randomy, 5, 5);
randomx = (int) (Math.random () * 300) + 10;
randomy = (int) (Math.random () * 150) + 10;
}
g.setColor (Color.white);
g.drawLine (320, 0, 315, 40);
g.drawLine (320, 0, 325, 40);
g.drawLine (320, 120, 315, 80);
g.drawLine (320, 120, 325, 80);
g.drawLine (260, 60, 300, 55);
g.drawLine (260, 60, 300, 65);
g.drawLine (380, 60, 340, 55);
g.drawLine (380, 60, 340, 65);
fillGradOval (280, 20, 80, 80, new Color (254, 238, 44), new Color (255, 251, 191), g);
g.setColor (new Color (255, 251, 191));
fillGradOval (300, 40, 40, 40, new Color (255, 251, 191), new Color (254, 238, 44), g);
}
public void fillGradOval (int X, int Y, int H2, int W2, Color c1, Color c2, Graphics g)
{
g.setColor (c1);
g.fillOval (X, Y, W2, H2);
Color Gradient = c1;
float red = (c2.getRed () - c1.getRed ()) / (W2 / 2);
float blue = (c2.getBlue () - c1.getBlue ()) / (W2 / 2);
float green = (c2.getGreen () - c1.getGreen ()) / (W2 / 2);
int scale = 1;
int r = c1.getRed ();
int gr = c1.getGreen ();
int b = c1.getBlue ();
while (W2 > 10)
{
r = (int) (r + red);
gr = (int) (gr + green);
b = (int) (b + blue);
Gradient = new Color (r, gr, b);
g.setColor (Gradient);
W2 = W2 - 2 * scale;
H2 = H2 - 2 * scale;
X = X + scale;
Y = Y + scale;
g.fillOval (X, Y, W2, H2);
}
}
public void actionPerformed (ActionEvent e)
{
}
public void stateChanged (ChangeEvent e)
{
JSlider source = (JSlider) e.getSource ();
if (!source.getValueIsAdjusting ())
{
}
}
}
I wasn't sure what 'color' you were referring to, so I made some guesses. Here is an hybrid application/applet (much easier for development and testing) that links the color of the bottom panel, as well as the bottom color of the gradient paint, to a hue as defined using the slider.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/* <applet code=HueSlider width=380 height=240></applet> */
public class HueSlider extends JApplet
{
public void init() {
add(new HueSliderGui());
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
HueSliderGui hsg = new HueSliderGui();
JOptionPane.showMessageDialog(null, hsg);
}
};
SwingUtilities.invokeLater(r);
}
}
class HueSliderGui extends JPanel implements ChangeListener {
//Widgets, Panels
JSlider slider;
JPanel flow;
int colorr;
int colorg;
int colorb;
Color bg = new Color (102, 179, 255);
int stars;
//House Coordinates, initialized to 1. (Top Right and No Scaling)
Dimension prefSize = new Dimension(380, 240);
HueSliderGui() {
initGui();
}
public void initGui()
{
//Set Up Input Fields for House Coordinates
// an applet size is set in HTML
//resize (380, 240);
setBackground (bg);
slider = new JSlider ();
slider.setValue (0);
slider.setBackground (new Color (102, 179, 255));
slider.setForeground (Color.white);
slider.setMajorTickSpacing (20);
slider.setMinorTickSpacing (5);
slider.setPaintTicks (true);
slider.addChangeListener (this);
//Set up layout, add widgets
setLayout (new BorderLayout ());
flow = new JPanel (new FlowLayout ());
flow.add (slider);
add (flow, "South");
validate();
}
#Override
public Dimension getPreferredSize() {
return prefSize;
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Color color1 = getBackground ();
Color color2 = color1.darker ();
int x = getWidth ();
int y = getHeight () - 30;
GradientPaint gp = new GradientPaint (
0, 0, color1,
0, y, flow.getBackground());
g2d.setPaint (gp);
g2d.fillRect (0, 0, x, y);
stars (10, 10, g2d);
}
public void stars (int x, int y, Graphics g)
{
// Graphics g = getGraphics (); we should never call getGraphics
//sun
g.setColor (new Color (139, 166, 211));
g.fillOval (-200, 170, 1000, 400);
g.setColor (new Color (206, 75, 239));
g.fillOval (x, y, 10, 10); //First medium star
g.drawLine (x + 5, y, x + 5, 0);
g.drawLine (x, y + 5, 0, y + 5);
g.drawLine (x + 5, y + 10, x + 5, y + 20);
g.drawLine (x + 10, y + 5, x + 20, y + 5);
g.fillOval (x + 80, y + 30, 12, 12); //Middle medium star
g.drawLine (x + 86, y + 30, x + 86, y + 18);
g.drawLine (x + 80, y + 36, x + 68, y + 36);
g.drawLine (x + 92, y + 36, x + 104, y + 36);
g.drawLine (x + 86, y + 42, x + 86, y + 52);
colorr = (int) (Math.random () * 255) + 1;
colorg = (int) (Math.random () * 255) + 1;
colorb = (int) (Math.random () * 255) + 1;
int randomx = (int) (Math.random () * 300) + 10;
int randomy = (int) (Math.random () * 150) + 10;
stars = 50; //Change for more stars
int ax[] = new int [stars];
int ay[] = new int [stars];
for (int i = 0 ; i < stars ; i++)
{
g.setColor (new Color (colorr, colorg, colorb));
colorr = (int) (Math.random () * 255) + 1;
colorg = (int) (Math.random () * 255) + 1;
colorb = (int) (Math.random () * 255) + 1;
while ((randomx > 88 && randomx < 116) && (randomy < 65 && randomy > 15))
{
randomx = (int) (Math.random () * 300) + 10;
randomy = (int) (Math.random () * 150) + 10;
}
while ((randomx > 0 && randomx < 25) && (randomy > 5 && randomy < 35))
{
randomx = (int) (Math.random () * 300) + 10;
randomy = (int) (Math.random () * 150) + 10;
}
g.drawOval (randomx, randomy, 5, 5);
randomx = (int) (Math.random () * 300) + 10;
randomy = (int) (Math.random () * 150) + 10;
}
g.setColor (Color.white);
g.drawLine (320, 0, 315, 40);
g.drawLine (320, 0, 325, 40);
g.drawLine (320, 120, 315, 80);
g.drawLine (320, 120, 325, 80);
g.drawLine (260, 60, 300, 55);
g.drawLine (260, 60, 300, 65);
g.drawLine (380, 60, 340, 55);
g.drawLine (380, 60, 340, 65);
fillGradOval (280, 20, 80, 80, new Color (254, 238, 44), new Color (255, 251, 191), g);
g.setColor (new Color (255, 251, 191));
fillGradOval (300, 40, 40, 40, new Color (255, 251, 191), new Color (254, 238, 44), g);
}
public void fillGradOval (int X, int Y, int H2, int W2, Color c1, Color c2, Graphics g)
{
g.setColor (c1);
g.fillOval (X, Y, W2, H2);
Color Gradient = c1;
float red = (c2.getRed () - c1.getRed ()) / (W2 / 2);
float blue = (c2.getBlue () - c1.getBlue ()) / (W2 / 2);
float green = (c2.getGreen () - c1.getGreen ()) / (W2 / 2);
int scale = 1;
int r = c1.getRed ();
int gr = c1.getGreen ();
int b = c1.getBlue ();
while (W2 > 10)
{
r = (int) (r + red);
gr = (int) (gr + green);
b = (int) (b + blue);
Gradient = new Color (r, gr, b);
g.setColor (Gradient);
W2 = W2 - 2 * scale;
H2 = H2 - 2 * scale;
X = X + scale;
Y = Y + scale;
g.fillOval (X, Y, W2, H2);
}
}
public void stateChanged (ChangeEvent e)
{
JSlider source = (JSlider) e.getSource ();
if (!source.getValueIsAdjusting ())
{
int i = source.getValue();
System.out.println(i);
float[] hsb = Color.RGBtoHSB(bg.getRed(),bg.getGreen(),bg.getBlue(),null);
int colorHue = Color.HSBtoRGB((float)i/100f, hsb[1], hsb[2]);
Color c = new Color(colorHue);
flow.setBackground(c);
this.repaint();
}
}
}

Java Animations

I've started to take interest with making animations(slideshows, backgrounds etc) in Java. I know that JavaFX is much better for doing this, but I'm just to stubborn to bother switching over.
Here is what I got so far.
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BlurredLightCells extends JPanel {
private static final long serialVersionUID = 4610174943257637060L;
private Random random = new Random();
private ArrayList<LightCell> lightcells;
private float[] blurData = new float[500];
public static void main(String[] args) {
JFrame frame = new JFrame("Swing animated bubbles");
frame.setSize(1000, 750);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BlurredLightCells(60));
frame.setVisible(true);
}
public BlurredLightCells(int amtOfBCells) {
setSize(1000, 750);
/**
* Below we initiate all the cells that are going to be drawn on screen
*/
Arrays.fill(blurData, 1f / 20f);
lightcells = new ArrayList<LightCell>(amtOfBCells);
for (int i = 0; i < amtOfBCells; i++) {
/**
* Below we generate all the values for each cell(SHOULD be random for each one)
*/
int baseSpeed = random(0, 3);
int xSpeed = (int) Math.floor((Math.random() * (baseSpeed - -baseSpeed + baseSpeed)) + -baseSpeed);
int ySpeed = (int) Math.round((Math.random() * baseSpeed) + 0.5);
int radius = random(25, 100);
int x = (int) Math.floor(Math.random() * getWidth());
int y = (int) Math.floor(Math.random() * getHeight());
int blurrAmount = (int) (Math.floor(Math.random() * 10) + 5);
int alpha = (int) ((Math.random() * 15) + 3);
/**
* Now we draw a image, and apply transparency and a slight blur to it
*/
Kernel kernel = new Kernel(blurrAmount, blurrAmount, blurData);
BufferedImageOp op = new ConvolveOp(kernel);
BufferedImage circle = new BufferedImage(150, 150, BufferedImage.TYPE_INT_ARGB);
Graphics2D circlegfx = circle.createGraphics();
circlegfx.setColor(new Color(255, 255, 255, alpha));
circlegfx.fillOval(20, 20, radius, radius);
circle = op.filter(circle, null);
LightCell bubble = new LightCell(x, y, xSpeed, ySpeed, radius, getDirection(random.nextInt(3)), circle);
lightcells.add(bubble);
}
}
public int random(int min, int max) {
final int n = Math.abs(max - min);
return Math.min(min, max) + (n == 0 ? 0 : random.nextInt(n));
}
#Override
public void paint(Graphics g) {
int w = getWidth();
int h = getHeight();
final Graphics2D g2 = (Graphics2D) g;
GradientPaint gp = new GradientPaint(-w, -h, Color.LIGHT_GRAY, w, h, Color.DARK_GRAY);
g2.setPaint(gp);
g2.fillRect(0, 0, w, h);
long start = System.currentTimeMillis();
for (int i = 0; i < lightcells.size(); i++) {
LightCell cell = lightcells.get(i);
cell.process(g2);
}
System.out.println("Took " + (System.currentTimeMillis() - start) + " milliseconds to draw ALL cells.");
repaint();
}
public String getDirection(int i) {
switch (i) {
case 0:
return "right";
case 1:
return "left";
case 2:
return "up";
case 3:
return "down";
}
return "";
}
private class LightCell {
private int x, y, xSpeed, ySpeed, radius;
private String direction;
private BufferedImage image;
public LightCell(int x, int y, int xSpeed, int ySpeed, int radius, String direction, BufferedImage image) {
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.radius = radius;
this.direction = direction;
this.image = image;
}
public void process(Graphics g) {
switch (direction) {
case "right":
moveRight();
break;
case "left":
moveLeft();
break;
case "up":
moveUp();
break;
case "down":
moveDown();
break;
}
g.drawImage(image, x, y, null);
}
private void moveUp() {
x += xSpeed;
y -= ySpeed;
if (y + (radius / 2) < 0) {
y = getHeight() + (radius / 2);
x = (int) Math.floor(Math.random() * getWidth());
}
if ((x + radius / 2) < 0 || (x - radius / 2) > getWidth()) {
y = radius + (radius / 2);
x = (int) Math.floor(Math.random() * getWidth());
}
}
private void moveDown() {
x += xSpeed;
y += ySpeed;
if (y - (radius / 2) > getHeight()) {
y = 0 - (radius / 2);
x = (int) Math.floor(Math.random() * getWidth());
}
if ((x + radius / 2) < 0 || (x - radius / 2) > getWidth()) {
y = getHeight() + (radius / 2);
x = (int) Math.floor(Math.random() * getWidth());
}
}
private void moveRight() {
x += ySpeed;
y += xSpeed;
if (y - (radius / 2) > getHeight() || y + (radius / 2) < 0) {
x = 0 - (radius / 2);
y = (int) Math.floor(Math.random() * getHeight());
}
if ((x - radius / 2) > getWidth()) {
x = 0 - (radius / 2);
y = (int) Math.floor(Math.random() * getWidth());
}
}
private void moveLeft() {
x -= ySpeed;
y -= xSpeed;
if (y - (radius / 2) > getHeight() || y + (radius / 2) < 0) {
x = getWidth() + (radius / 2);
y = (int) Math.floor(Math.random() * getHeight());
}
if ((x + radius / 2) < 0) {
x = getWidth() + (radius / 2);
y = (int) Math.floor(Math.random() * getWidth());
}
}
}
}
If you run that, you will see the cells move at a very high speed, and if you look through the code, you see I call repaint() in the paint method in which I override. I know thats not good to do. But my question is, is their any other way in which I could draw each cell outside of the repaint() loop I have right now, because that causes other components to flash/flicker when I use this in a JFrame with other components.
FYI: Aventually I'd like to achieve something similar to this: Click Here
Thanks!
The issue of flicker is to do with the fact that top level containers are not double buffered. Instead of extending from JFrame (or other top level containers), you should consider using something more like JPanel and override it's paintComponent.
nb- Had it in my head that the OP was extending from JFrame...
Two issues could be causing the flickering. The first is overriding paint, the second is not calling super.paint(g) and the time between the updates. A better solution would be to override paintComponent and make sure you are calling super.paintComponent. Also using something like a javax.swing.Timer to schedule updates and regular intervals would also help...
Only call repaint when you want to encourage the RepaintManager to update you component. Don't call repaint from within any paintXxx method, this will cause a never ending loop of paint requests to schedule onto the event queue, eventually consuiming your CPU
I would avoid doing anything in your paintXxx methods that might take time to perform, this will slow down the rendering process. Instead, I would use a javax.swing.Timer for simple updates or for more complicated processing, a Thread which could be used to update the model before it is rendered to the screen.
This is an example of some simple optimisation process I did to take animation of 500 objects to 4500 with only a slight degration in the overall performance.
Updated
I changed you code slight and it works fine...
I changed your paint method to paintComponent and added super.paintComponent(g)
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
final Graphics2D g2 = (Graphics2D) g;
GradientPaint gp = new GradientPaint(-w, -h, Color.LIGHT_GRAY, w, h, Color.DARK_GRAY);
g2.setPaint(gp);
g2.fillRect(0, 0, w, h);
for (int i = 0; i < lightcells.size(); i++) {
LightCell cell = lightcells.get(i);
cell.process(g2);
}
}
And at the end of your constructor I added...
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
To update the UI on a regular bases...

Categories

Resources