UI is not Creating Shapes - java

I have a simple example that is supposed to create a set of green balls, but instead is only creating one. I want to create an ArrayList to hold the balls, but something is wrong. Please Help.
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.Random;
import javax.security.auth.x500.X500Principal;
import javax.swing.*;
public class MyBall extends JPanel{
Random rand = new Random();
int xr = rand.nextInt(400);
int yr = rand.nextInt(400);
int size = 10 ;
int x = xr ;
int y = yr ;
Ellipse2D.Double ball = new Ellipse2D.Double(0, 0, 30, 30);
ArrayList<Bubbles> balls = new ArrayList<Bubbles>();
Bubbles blobsOb = new Bubbles(x, y , size , Color.GREEN);
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 =(Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.BLUE);
g2.fill(ball);
g2.setColor(Color.green);
for (int j = 0 ; j < 10 ; j++)]{
for(int i = 0 ; i < 10; i++){
balls.add(blobsOb);
g.setColor(Color.green);
g.fillOval(x, y, size, size);
}
}
}
}
//SECOND CLASS
import javax.swing.*;
public class Main {
public static void main(String[] args) {
MyBall p = new MyBall();
JFrame f = new JFrame();
f.add(p);
f.setVisible(true);
f.setLocation(200,200);
f.setSize(400, 420);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//Third Class
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
// this class is for the properties of green balls
public class Bubbles extends Component {
public int x;
public int y;
public int size;
public Color color;
public static Bubbles blob = new Bubbles(250,250,100,Color.BLUE);
Bubbles(int x, int y, int size, Color c){
this.x = x;
this.y = y;
this.size = size;
this.color = c;
}
public void paint(Graphics g){
g.setColor(color);
g.fillOval(x, y, size, size);
}
}

You need to create new instance in every cycle
for(int j = 0; j < 10; j++){
for(int i = 0 ; i < 10; i++)
{
// ...
balls.add(new Bubbles(xr, yr , size , Color.GREEN));
}
}

I want to create array list which holds green balls but the problem
is I just get one green ball instead of (10) or more
First, this should be inside the loop:
Bubbles blobsOb = new Bubbles(x, y , size , Color.GREEN);
then you'll also need to insert the code below inside the loop to ensure that at each iteration there is a new generated random value.
int xr = rand.nextInt(400);
int yr = rand.nextInt(400);
int size = 10;
int x = xr ;
int y = yr ;
example:
for(int j = 0; j < 10; j++){
for(int i = 0 ; i < 10; i++)
{
int xr = rand.nextInt(400);
int yr = rand.nextInt(400);
int size = 10;
Bubbles blobsOb = new Bubbles(xr, yr , size , Color.GREEN);
balls.add(blobsOb);
g.setColor(Color.green);
g.fillOval(x, y, size, size);
}
}
you should always call .setVisible(true) after all the components have been added to the frame.
MyBall p = new MyBall();
JFrame f = new JFrame();
f.add(p);
f.setLocation(200,200);
f.setSize(400, 420);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Lastly but not least, you've added all the generated Bubble objects into the ArrayList ArrayList<Bubbles> balls = new ArrayList<Bubbles>(), However, you haven't used the balls ArrayList yet.

Related

Java AWT Graphics Class: Making Rows and Columns of Squares

I'm using the java.awt graphics class, and I'm trying to make rows and squares.
I can't seem to get the layout of the rows correctly.
I'm trying to code 8 rows with 3 columns each. However, I just get 2 rows with 12 columns.
If somebody can help me to create the outcome that I want, that would be greatly appreciated.
Here's my code:
g.setColor(Color.WHITE);
int x = 70;
int y = 80;
int w = 30;
int h = 35;
for(int row = 0; row < 3; row++) {
for(int col = 0; col < 4; col++) {
g.fillRect( x, y, w, h );
g.fillRect( x, y + h + 20, w, h );
x += w + 15;
}
System.out.println();
}
Here's the output: 2 rows, 12 columns of squares
Beware of how you are updating your position information. For example, you should only be updating the x position in the inner loop and resetting to 0 before entering the inner loop, and the y position should only be updated on each new row.
Alternatively, you could calculate the position directly, based on the row/column index and the row/column height, as demonstrated below.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private static int COLUMN_COUNT = 3;
private static int ROW_COUNT = 8;
private static int COLUMN_WIDTH = 30;
private static int ROW_HEIGHT = 35;
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(3 * COLUMN_WIDTH, 8 * ROW_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int columnWidth = getWidth() / 3;
int rowHeight = getHeight() / 8;
int x = 0;
int y = 0;
for (int row = 0; row < ROW_COUNT; row++) {
for (int col = 0; col < COLUMN_COUNT ; col++) {
if (col % 2 == 0) {
x = columnWidth * col;
y = rowHeight * row;
g2d.fillRect(x + 2, y + 2, columnWidth - 4, rowHeight - 4);
}
}
}
g2d.dispose();
}
}
}

Java - Hexagon location in grid

Im searching for an algorythem to get the location of a hexagon in a grid.
I found this one but it doesnt seam to work:
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
}
}
The output is kind of strange:
output
This is the window-creating class(just a test class):
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Grid extends JPanel {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
int width = 2;
int height = 4;
int x = 100;
int y = 100;
Hexagon[][] grid = new Hexagon[width][height];
JFrame f = new JFrame();
Container cp = f.getContentPane();
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
cp.add(grid[i][j]);
}
}
f.setLayout(null);
f.setBounds(100, 100, 300, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
The Hexagon.java class:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.swing.JButton;
public class Hexagon extends JButton {
public static final int S = 50;
public static final int A = (int) (Math.sqrt(3)*(S/2));
private static final long serialVersionUID = 1L;
private final int x, y;
private final Polygon shape;
public Hexagon(int x, int y) {
this.x = x;
this.y = y;
this.shape = initHexagon();
setSize(2*S, 2*A);
setLocation(x-S, y-A);
setContentAreaFilled(false);
}
private Polygon initHexagon() {
Polygon p = new Polygon();
p.addPoint(x+(S/2), y-A);
p.addPoint(x+S, y);
p.addPoint(x+(S/2), y+A);
p.addPoint(x-(S/2), y+A);
p.addPoint(x-S, y);
p.addPoint(x-(S/2), y-A);
return p;
}
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.drawPolygon(this.shape);
}
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(4));
g2.drawPolygon(this.shape);
}
public boolean contains(int x, int y) {
return this.shape.contains(x, y);
}
}
As i said, this class worked just fine using non-rectangular shapes.
There was no clipping or such.
You've posted your definition of Hexagon too late, so I copy-pasted a modified version of a similar class from my collection of code snippets.
Here is one way to generate a hexagonal grid:
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.function.*;
public class Hexagons extends JPanel {
private static final long serialVersionUID = 1L;
/** Height of an equilateral triangle with side length = 1 */
private static final double H = Math.sqrt(3) / 2;
static class Hexagon {
final int row;
final int col;
final double sideLength;
public Hexagon(int r, int c, double a) {
this.row = r;
this.col = c;
this.sideLength = a;
}
double getCenterX() {
return 2 * H * sideLength * (col + (row % 2) * 0.5);
}
double getCenterY() {
return 3 * sideLength / 2 * row;
}
void foreachVertex(BiConsumer<Double, Double> f) {
double cx = getCenterX();
double cy = getCenterY();
f.accept(cx + 0, cy + sideLength);
f.accept(cx - H * sideLength, cy + 0.5 * sideLength);
f.accept(cx - H * sideLength, cy - 0.5 * sideLength);
f.accept(cx + 0, cy - sideLength);
f.accept(cx + H * sideLength, cy - 0.5 * sideLength);
f.accept(cx + H * sideLength, cy + 0.5 * sideLength);
}
}
public static void main(String[] args) {
final int width = 50;
final int height = 50;
final Hexagon[][] grid = new Hexagon[height][width];
for(int row = 0; row < height; row++) {
for(int col = 0; col < width; col++) {
grid[row][col] = new Hexagon(row, col, 50);
}
}
JFrame f = new JFrame("Hexagons");
f.getContentPane().setLayout(new GridLayout());
f.getContentPane().add(new JComponent() {
#Override public void paint(Graphics g) {
g.setColor(new Color(0xFF, 0xFF, 0xFF));
g.fillRect(0,0,1000,1000);
g.setColor(new Color(0,0,0));
final int[] xs = new int[6];
final int[] ys = new int[6];
for (Hexagon[] row : grid) {
for (Hexagon h: row) {
final int[] i = {0};
h.foreachVertex((x, y) -> {
xs[i[0]] = (int)((double)x);
ys[i[0]] = (int)((double)y);
i[0]++;
});
g.drawPolygon(xs, ys, 6);
g.drawString(
"(" + h.row + "," + h.col + ")",
(int)(h.getCenterX() - 15),
(int)(h.getCenterY() + 12)
);
}
}
}
});
f.setBounds(0, 0, 500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
try {
Thread.sleep(100);
} catch (Throwable e) {
} finally {
f.repaint();
}
}
}
It produces the following output:
Sorry for the lack of anti-aliasing. A few hints:
Height H of an equilateral triangle with unit side length is sqrt(3) / 2
The six offsets from the center are (0, +1), (H, +1/2), (H, -1/2), (0, -1), (-H, -1/2), (-H, +1/2), everything times side length.
Distance between rows is 1.5, distance between columns is 2 * H (times scaling constant = side length).
Every odd row is shifted by (0, H) (times scaling constant).
The position of (row,col)-th hexagon is (1.5 * row, 2 * H * (col + 0.5 * (row % 2))) (times constant).
If you want to rotate the hexagons such that two of their sides are horizontal, you have to flip rows and columns.

Nesting parabolic curves from straight lines

I am having trouble replicating the picture for my assignment. I would appreciate any tips or solutions. I believe I have the general idea down, but I am having a hard time figuring out the math to replicate the image and doing everything in a single loop.
My program needs to meet these criteria:
Match the Image
Generate a random color for each pair of parabolic curve
Work with any width or height
Use a single loop to draw the entire figure.
Here is the image:
This is what I have tried so far
public static final int WIDTH = 500;
public static final int HEIGHT = 500;
public static final int LINE_INCREMENT = 5;
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(WIDTH, HEIGHT);
Graphics g = panel.getGraphics();
int d = 0;
int iterations = HEIGHT/LINE_INCREMENT;
Random rand = new Random();
int red = 0, green = 0, blue = 0;
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
for(int y = 0; y < iterations; y++) {
g.drawLine(0, d, d, HEIGHT);
g.drawLine(WIDTH, d, d, 0);
d += LINE_INCREMENT;
}
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
d = 0;
for (int x = 0; x < iterations/2; x++) {
g.drawLine(WIDTH/4, d + HEIGHT/4, d + WIDTH/4, HEIGHT - HEIGHT/4);
g.drawLine(d + WIDTH/4, WIDTH/4, WIDTH - WIDTH/4, d + WIDTH/4);
d += LINE_INCREMENT;
}
}
The output:
The way to implement it is by overriding paintComponent:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ParabolicCurves extends JFrame {
private static final int SIZE = 600;
private static final int LINE_INCREMENT = 5;
private static final int NUM_OF_PATTERNS = 4;
private Random rand = new Random();
ParabolicCurves() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel panel = new DrawingPanel(SIZE);
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
}
class DrawingPanel extends JPanel{
public DrawingPanel(int size) {
setPreferredSize(new Dimension(size, size));
setBackground(Color.WHITE);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int red, green, blue, delta , iterations;
int height, width ,startX, startY, endX, endY ;
Rectangle boundingRrectangle = getBounds();
for(int pattern = 0 ; pattern < NUM_OF_PATTERNS; pattern++) {
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
height = (int) boundingRrectangle.getHeight();
width = (int) boundingRrectangle.getWidth();
startX = (int) boundingRrectangle.getX();
startY = (int) boundingRrectangle.getY();
endX = startX+width;
endY = startY+ height;
iterations = Math.min(width, height)/LINE_INCREMENT;
delta = 0;
for (int x = 0; x < iterations ; x++) {
g.drawLine(startX, startY+delta, startX+delta, endY);
g.drawLine(endX, startY+delta, startX+delta, startY);
delta += LINE_INCREMENT;
}
//change bounding rectangle
boundingRrectangle = new Rectangle(startX+(width/4),
startY+(width/4), width/2, height/2);
}
}
}
public static void main(String[] args) {
new ParabolicCurves();
}
}
Output:

Button To Reset The View Of JFrame

I have to write a program that will generate 20 random circles with random radius lengths. If any of these circles intersect with another, the circle must be blue, and if it does not intersect, the color is red. I must also place a button on the JFrame. If this button is pressed, it needs to clear out the JFrame, and generate a new set of 20 circles following the same color rules. I am extremely new to Java Swing and am really stuck. I have everything working except the button. I cannot get a new set of circles to generate. Any help would be greatly appreciated. Thank You.
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class IntersectingCircles extends JPanel
{
private int[] xAxis = new int [20]; // array to hold x axis points
private int[] yAxis = new int [20]; // array to hold y axis points
private int[] radius = new int [20]; // array to hold radius length
public static void main (String[] args)
{
JFrame frame = new JFrame("Random Circles");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new IntersectingCircles());
frame.pack();
frame.setVisible(true);
}
public IntersectingCircles()
{
setPreferredSize(new Dimension(1000, 800)); // set window size
Random random = new Random();
// Create coordinates for circles
for (int i = 0; i < 20; i++)
{
xAxis[i] = random.nextInt(700) + 100;
yAxis[i] = random.nextInt(500) + 100;
radius[i] = random.nextInt(75) + 10;
}
}
public void paintComponent(Graphics g)
{
// Add button to run again
JButton btnAgain = new JButton("Run Again");
btnAgain.setBounds(850, 10, 100, 30);
add(btnAgain);
btnAgain.addActionListener(new ButtonClickListener());
// Determine if circles intersect, create circles, color circles
for (int i = 0; i < 20; i++)
{
int color = 0;
for (int h = 0; h < 20; h++)
{
if(i != h)
{
double x1 = 0, x2 = 0, y1 = 0, y2 = 0, d = 0;
x1 = (xAxis[i] + radius[i]);
y1 = (yAxis[i] + radius[i]);
x2 = (xAxis[h] + radius[h]);
y2 = (yAxis[h] + radius[h]);
d = (Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1)*(y2 - y1))));
if (d > radius[i] + radius[h] || d < (Math.abs(radius[i] - radius[h])))
{
color = 0;
}
else
{
color = 1;
break;
}
}
}
if (color == 0)
{
g.setColor(Color.RED);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
else
{
g.setColor(Color.BLUE);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
}
}
private class ButtonClickListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String action = e.getActionCommand();
if(action.equals("Run Again"))
{
new IntersectingCircles();
}
}
}
}
Suggestions:
Give your class a method that creates the random circles and calls repaint()
This method should create the circles and add them into an ArrayList.
Consider using Ellipse2D to represent your circles, and so you'd have an ArrayList<Ellipse2D>.
Call this method in your class constructor.
Call it again in the button's ActionListener.
Never add button's or change the state of your class from within your paintComponent method. This method is for drawing the circles and drawing them only and nothing more. Your way you will be creating the button each time the paintComponent method is called, so you could be potentially needlessly creating many JButtons
and needlessly slowing down your time-critical painting method.
Instead add the button in the constructor.
Be sure to call super.paintComponent(g) in your paintComponent method as its first call. This will clear the old circles when need be.
Also in paintComponent, iterate through the ArrayList of circles, drawing each one.
After some searching on this website, i found what i needed. Everything seems to work now. Thanks.
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class IntersectingCircles extends JPanel
{
private int[] xAxis = new int [20]; // array to hold x axis points
private int[] yAxis = new int [20]; // array to hold y axis points
private int[] radius = new int [20]; // array to hold radius length
public static void main (String[] args)
{
JFrame frame = new JFrame("Random Circles");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(1000, 800));
ActionListener runAgain = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent c)
{
frame.getContentPane().add(new IntersectingCircles());
frame.pack();
}
};
JButton btnAgain = new JButton("Run Again");
btnAgain.setBounds(850, 10, 100, 30);
btnAgain.addActionListener(runAgain);
frame.add(btnAgain);
frame.getContentPane().add (new IntersectingCircles());
frame.pack();
frame.setVisible(true);
}
public IntersectingCircles()
{
Random random = new Random();
// Create coordinates for circles
for (int i = 0; i < 20; i++)
{
xAxis[i] = random.nextInt(700) + 100;
yAxis[i] = random.nextInt(500) + 100;
radius[i] = random.nextInt(75) + 10;
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// Determine if circles intersect, create circles, color circles
for (int i = 0; i < 20; i++)
{
int color = 0;
for (int h = 0; h < 20; h++)
{
if(i != h)
{
double x1 = 0, x2 = 0, y1 = 0, y2 = 0, d = 0;
x1 = (xAxis[i] + radius[i]);
y1 = (yAxis[i] + radius[i]);
x2 = (xAxis[h] + radius[h]);
y2 = (yAxis[h] + radius[h]);
d = (Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1)*(y2 - y1))));
if (d > radius[i] + radius[h] || d < (Math.abs(radius[i] - radius[h])))
{
color = 0;
}
else
{
color = 1;
break;
}
}
}
if (color == 0)
{
g.setColor(Color.RED);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
else
{
g.setColor(Color.BLUE);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
}
}
}
private class ButtonClickListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
Maybe you can have a try...

Drawing an assembled image to the JPanel

I am working on a program that I can use to present topics in front of my class. While MS Powerpoint and similar programs are nice, I feel like they are lacking in some areas. I am not trying to re-create these programs, I am only trying to make a program where I can type text into String arrays, add images, and position them all on the screen.
Currently my program opens a fullscreen dark window with a little X in the top left, which when clicked will close the program.
Here is the class file:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
static JFrame frame;
static MyPanel panel;
static MouseListener listener;
static final int letterWidth = 6;
static final int letterHeight = 9;
static final int letterRow = 10;
static final int letterCol = 11;
static final int letterNum = 110;
static String[] textA = {"Hello World,",
"Here is a test",
"of what I can do.",
"Isn't it neat?!"
};
static int textX = 100;
static int textY = 100;
public static void main(String[] args){
System.out.println("Welcome to Presenter");
System.out.println("Beginning loading");
frame = new JFrame();
panel = new MyPanel();
listener = new MouseListener(){
public void mouseClicked(MouseEvent arg0) {
if(arg0.getButton() ==MouseEvent.BUTTON1){
//Close button
int x = (int) MouseInfo.getPointerInfo().getLocation().getX();
int y = (int) MouseInfo.getPointerInfo().getLocation().getY();
if(x>20 && x<48 && y>20 && y<56){
frame.dispose();
System.exit(0);
}
}
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {}
public void mouseReleased(MouseEvent arg0) {}
};
frame.setUndecorated(true);
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.add(panel);
frame.addMouseListener(listener);
System.out.println("");
System.out.println("Loading Complete");
}
public static class MyPanel extends JPanel{
private static final long serialVersionUID = 1L;
HashMap<String, BufferedImage> iLetters;
static BufferedImage exitButton = new BufferedImage(28, 36, BufferedImage.TYPE_INT_ARGB);
static BufferedImage letters = new BufferedImage(120, 198, BufferedImage.TYPE_INT_ARGB);
Scanner lightbulb;
static boolean point = false;
int x;
int y;
BufferedImage textBox;
int boxW, boxH;
public MyPanel(){
//pictures
File a = new File("Exit.png");
try { exitButton = ImageIO.read(a); } catch (IOException e) {e.printStackTrace();}
a = new File("Letters.png");
try { letters = ImageIO.read(a); } catch (IOException e) {e.printStackTrace();}
//letter index
try { lightbulb = new Scanner(new File("letters.txt")); } catch (FileNotFoundException e) {e.printStackTrace();}
System.out.println("Files Read");
//create letters
System.out.println("Beginning tiling");
iLetters = new HashMap<String, BufferedImage>();
BufferedImage[] pics = new BufferedImage[letterNum];
int count = 0;
for(int x=0; x<letterCol; x++){
for(int y=0; y<letterRow; y++){
pics[count] = new BufferedImage(letterWidth, letterHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = pics[count++].createGraphics();
gr.drawImage(letters, 0, 0, letterWidth, letterHeight, letterWidth * y, letterHeight * x, letterWidth * y + letterWidth, letterHeight * x + letterHeight, null);
gr.dispose();
}
System.out.println("Row " + x + " tiled.");
}
System.out.println("Completed Tiling");
System.out.println("Beginning indexing");
int loc = 0;
String key = "";
while(lightbulb.hasNext()){
loc = lightbulb.nextInt()-1;
key = lightbulb.next();
iLetters.put(key, pics[loc]);
}
System.out.println("Indexing Complete");
System.out.println("Making Text Boxes");
makeTextBox(textA);
System.out.println("Text Boxes Made");
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(new Color(0, 0, 10));
g.drawImage(exitButton, 20, 20, null);
// g.drawImage(iLetters.get("A"), 100, 100, null);
drawTexts(g);
}
public void drawTexts(Graphics g){
g.drawImage(textBox, textX, textY, textX+(boxW*2), textY+(boxH*2), null);
}
public int findLongest(String[] text){
int longest = 0;
for(int i=0; i<text.length; i++){
if(text[i].length() > longest)
longest = text[i].length();
}
return longest;
}
public void makeTextBox(String[] text){
int longest = findLongest(text);
boxW = (longest*6)+(longest-1);
boxH = (text.length*9)+(text.length-1);
textBox = new BufferedImage(boxW, boxH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = textBox.createGraphics();
char[] line;
int drawX = 0;
int drawY = 0;
for(int i=0; i<text.length; i++){
line = text[i].toCharArray();
for(int j=0; j<line.length; j++){
if(j<line.length-1){
g2d.drawImage(iLetters.get(line[j]), drawX, drawY, null);
drawX += letterWidth + 1;
}
else{
g2d.drawImage(iLetters.get(line[j]), drawX, drawY, null);
}
}
if(i<text.length-1){
drawY += letterHeight + 1;
}
else{
drawY += letterHeight;
}
}
g2d.dispose();
}
}
}
The rest of the files needed for it to run are here http://www.mediafire.com/?jq8vi4dm3t4b6
2 PNGs and 1 text file.
The program runs fine with no errors. The only problem is the drawTexts() method. When the method is called, the lines of text do not appear anywhere on screen, when they should be appearing at (100, 100) at 2x the size of the letters in the file.
It's been a while since I did graphics. I remember needing to call repaint() somewhere, but I cannot remember if I need it here, and if I do, where it goes.
Okay, this might take some time...
There are 10 columns and 11 rows, these are around the wrong way...
static final int letterRow = 10;
static final int letterCol = 11;
I don't think you understand what gr.drawImage(letters, 0, 0, letterWidth, letterHeight, letterWidth * y, letterHeight * x, letterWidth * y + letterWidth, letterHeight * x + letterHeight, null); is actually doing, what you really want is BufferedImage#getSubImage...
BufferedImage subimage = letters.getSubimage(letterWidth * x, letterHeight * y, letterWidth, letterHeight);
You're reading the Letters.png file in row/column order, but building the mapping as if it was in column/row order...
Instead of...
for (int x = 0; x < letterCol; x++) {
for (int y = 0; y < letterRow; y++) {
You should be using...
for (int y = 0; y < letterRow; y++) {
for (int x = 0; x < letterCol; x++) {
The lightbulb Scanner is not reading the file...I'm don't use Scanner that often, but when I changed it to lightbulb = new Scanner(new BufferedReader(new FileReader("letters.txt"))); it worked...
In your makeTextBox method you are trying to retrieve the image using a char instead of String, this means the lookup fails as the two keys are incompatible. You need to use something more like...
BufferedImage img = iLetters.get(Character.toString(line[j]));
Also, on each new line, you are not resting the drawX variable, so the text just keeps running off...In fact, I just re-wrote the loop to look more like...
for (int i = 0; i < text.length; i++) {
line = text[i].toCharArray();
for (int j = 0; j < line.length; j++) {
BufferedImage img = iLetters.get(Character.toString(line[j]));
g2d.drawImage(img, drawX, drawY, null);
if (j < line.length - 1) {
drawX += letterWidth + 1;
}
}
drawX = 0;
if (i < text.length - 1) {
drawY += letterHeight + 1;
} else {
drawY += letterHeight;
}
}
And yes, it could be simplified more, but little steps...
There might be a bunch of other things, but that should get you a step closer...

Categories

Resources