I'm trying to print out a maze. I'm new to Java Swing graphics, and my initial thought was to add JPanel components of each cell to the JFrame. I get garbage results when I run this code.
Is there any way I can change this code minimally so that all the panels are printed? Note that CurrPos, Wall, Unvisited, and Visited are subclasses of JFrame, which implement the painComponent method.
Here's the code:
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawMaze {
public final int WIDTH = 500;
public final int HEIGHT = 500;
JFrame frame;
public void initializeMaze(){
frame = new JFrame("Maze");
frame.getContentPane().setLayout(null);
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void drawMaze(String[][] maze, int[] currPosArray) {
//frame.removeAll();
addMazeContentsToList(maze, currPosArray);
frame.setVisible(true);
}
private void addMazeContentsToList(String[][] maze, int[] currPosArray) {
for (int i = 0; i<7; i++){
for (int j = 0; j<9; j++){
if ((i%2 == 1 && j%2 == 0) ||(i%2 == 0 && j%2 == 1) ){
Wall wall = drawWall(i, j);
frame.add(wall);
wall.repaint();
}
else if (i%2 ==0 && j%2 ==0){
if (i==currPosArray[0] && j==currPosArray[1]){
CurrPos currPos = drawCurrPos(i/2, j/2);
frame.add(currPos);
currPos.repaint();
}
else{
if (maze[i][j].equals("Unexplored")){
Unvisited unvisited = drawUnvisited(i/2,j/2);
frame.add(unvisited);
unvisited.repaint();
}
else{
Visited visited = drawVisited(i/2,j/2);
frame.add(visited);
visited.repaint();
}
}
}
}
}
}
private Visited drawVisited(int i, int j) {
int x = (int) Math.floor((i/4.0)*WIDTH);
int y = (int) Math.floor((j/5.0)*HEIGHT);
int width = (int) Math.floor(WIDTH/4.0);
int height = (int) Math.floor(HEIGHT/5.0);
return new Visited(x, y, width, height);
}
private Unvisited drawUnvisited(int i, int j) {
int x = (int) Math.floor((i/4.0)*WIDTH);
int y = (int) Math.floor((j/5.0)*HEIGHT);
int width = (int) Math.floor(WIDTH/4.0);
int height = (int) Math.floor(HEIGHT/5.0);
//System.out.println(x);
//System.out.println(y);
System.out.println(width);
System.out.println(height);
return new Unvisited(x, y, width, height);
}
private CurrPos drawCurrPos(int i, int j) {
int x = (int) Math.floor((i/4.0)*WIDTH);
int y = (int) Math.floor((j/5.0)*HEIGHT);
int width = (int) Math.floor(WIDTH/4.0);
int height = (int) Math.floor(HEIGHT/5.0);
return new CurrPos(x, y, width, height);
}
private Wall drawWall(int i, int j) {
//vertical wall
if (i%2 ==1){
int relativeX = (i+1)/2;
int relativeY = j/2;
int width = (int) Math.floor((1/4.0)*WIDTH*(0.2));
int height = (int) Math.floor((1/5.0)*HEIGHT);
int x = (int) Math.floor(((relativeX/4.0)*WIDTH - width*0.5));
int y = (int) (Math.floor((relativeY/5.0)*HEIGHT));
return new Wall(x, y, width, height);
}
//horizontal wall
else{
int relativeX = i/2;
int relativeY = (j+2)/2;
int width = (int) Math.floor((1/4.0)*WIDTH);
int height = (int) Math.floor((1/5.0)*HEIGHT*(0.2));
int x = (int) (Math.floor((relativeY/4.0)*WIDTH));
int y = (int) Math.floor(((relativeX/5.0)*HEIGHT - height*0.5));
return new Wall(x, y, width, height);
}
}
}
Related
This is a maze solver and I am trying to find a path through the maze. The Map is generated using Prim's algorithm and the position class which is added at the end.
I am trying to find an optimal path through the randomly generated maze using BFS, A*, or DFS but I seem to be doing something wrong.
//impoted by wildcard
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class MazeGenerator extends Canvas {
private final Random rand = new Random(); //random variable
private static int WIDTH;
private static int HEIGHT;
private int TILE_WIDTH = 15;
private int TILE_HEIGHT = 15;
private static LinkedList <position> maze = new LinkedList<>(); // maze
private static Map<position, Color> colors = new HashMap<>();
// paint class to draw out the maze
public void paint(Graphics g) {
super.paint(g);
g.translate(5, 5);
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, WIDTH * TILE_WIDTH, HEIGHT * TILE_HEIGHT);
g.setColor(Color.LIGHT_GRAY);
g.drawLine(0, 0, 0, HEIGHT * TILE_HEIGHT);
g.drawLine(0, 0, WIDTH * TILE_WIDTH, 0);
g.drawLine(WIDTH * TILE_WIDTH, 0, WIDTH * TILE_WIDTH, HEIGHT * TILE_HEIGHT);
g.drawLine(0, HEIGHT * TILE_HEIGHT, WIDTH * TILE_WIDTH, HEIGHT * TILE_HEIGHT);
LinkedList <position> mazeSteped = maze;
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
int current = (y * WIDTH) + x;
int lower = ((y + 1) * WIDTH) + x;
if(!mazeSteped.contains(new position(current, lower)))
g.drawLine(x * TILE_WIDTH, (y + 1) * TILE_HEIGHT, (x + 1) * TILE_WIDTH, (y + 1) * TILE_HEIGHT);
if(!mazeSteped.contains(new position(current, current + 1)))
g.drawLine((x + 1) * TILE_WIDTH, y * TILE_HEIGHT, (x + 1) * TILE_WIDTH, (y + 1) * TILE_HEIGHT);
if(colors.containsKey(new position(x, y)))
{
g.setColor(colors.get(new position(x, y)));
g.fillRect(x * TILE_WIDTH, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
g.setColor(Color.LIGHT_GRAY);
}
}
}
}
// Prim's algorithm
public void generate(int Width, int Height)
{
LinkedList<Integer> visited = new LinkedList<>();
LinkedList<position> toVisit = new LinkedList<>();
visited.add(0);
toVisit.add(new position(0, 1));
toVisit.add(new position(0, Width));
while(toVisit.size() > 0)
{
int randomIndex = rand.nextInt(toVisit.size());
position nextPath = toVisit.remove(randomIndex);
if(visited.contains(nextPath.end))
continue;
if(nextPath.start > nextPath.end)
maze.add(new position(nextPath.end, nextPath.start));
else
maze.add(nextPath);
visited.add(nextPath.end);
//this is showing all four directions that the random variable can generate towards.
int above = nextPath.end - Width;
if(above > 0 && !visited.contains(above))
toVisit.add(new position(nextPath.end, above));
int left = nextPath.end - 1;
if(left % Width != Width - 1 && !visited.contains(left))
toVisit.add(new position(nextPath.end, left));
int right = nextPath.end + 1;
if(right % Width != 0 && !visited.contains(right))
toVisit.add(new position(nextPath.end, right));
int below = nextPath.end + Width;
if(below < Width * Height && !visited.contains(below))
toVisit.add(new position(nextPath.end, below));
}
}
public static void main(String[] args)
{
MazeGenerator mazeGen = new MazeGenerator();
int Height = 30;
HEIGHT = Height;
int Width = 30;
WIDTH = Width;
mazeGen.generate(Width, Height);
mazeGen.setSize(16*Width, 17*Height);
JFrame frame = new JFrame("Maze Generator");
frame.add(mazeGen);
frame.setSize(16*Width, 17*Height);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//position or vector class that keeps track of position.
public class position{
public int start;
public int end;
public position(int start, int end){
this.start = start;
this.end = end;
}
public String toString(){
return "(" + start + ", " + end + ")";
}
public boolean equals(Object obj){
if(!(obj instanceof position))
return false;
position pos = (position) obj;
return pos.start == start && pos.end == end;
}
public int hashCode(){
return this.toString().hashCode();
}
public static void main(String [] args) {
position my = new position(1,1);
System.out.println(new position(1,1));
}
}
https://github.com/yuchinchenTW/MazeGenerate/tree/master
try this maze generator
using depth-first search and Recursive division method
The recursive division method can prevent stackoverflow on recursion
https://en.wikipedia.org/wiki/Maze_generation_algorithm
I am trying to add a square to the canvas when a mouse key is pressed and i want it to remain on the canvas when the mouse key is released, but it disappears when is released the key. Can anybody help me, what am i doing wrong?
int squareSize = 6;
final float DIFF_SIZE = 1;
final int MIN_COLOUR = 1;
final int MAX_COLOUR = 10;
final float INIT_RED = 100, INIT_GREEN = 50, INIT_BLUE = 80;
final float FINAL_RED = 255, FINAL_GREEN = 200, FINAL_BLUE = 250;
final float MAX_SIZE = 40;
final float X_SPACING = 10;
final float Y_SPACING = 10;
float squareX, squareY;
void setup() {
size(600, 600);
}
void draw() {
squareX = mouseX - squareSize / 2;
squareY = mouseY - squareSize / 2;
background(255);
drawRowsOfBlocks();
}
void drawOneBlock() {
rect(squareX, squareY, squareSize, squareSize);
for (int i = MIN_COLOUR; mousePressed && i <= MAX_COLOUR / 10; i++)
{
float redValue = INIT_RED + (i - MIN_COLOUR) / (MAX_COLOUR - MIN_COLOUR)(FINAL_RED - INIT_RED);
float greenValue = INIT_GREEN + (i - MIN_COLOUR) / (MAX_COLOUR - MIN_COLOUR)(FINAL_GREEN - INIT_GREEN);
float blueValue = INIT_BLUE + (i - MIN_COLOUR) / (MAX_COLOUR - MIN_COLOUR) * (FINAL_BLUE - INIT_BLUE);
fill(redValue, greenValue, blueValue);
rect(squareX, squareY, squareSize, squareSize);
squareSize += DIFF_SIZE;
}
if (squareSize > MAX_SIZE) {
squareSize = 6;
}
}
void drawRowsOfBlocks() {
drawOneBlock();
for (int i = 1; keyPressed && i <= 2; i++) {
drawOneBlock();
float squareY2;
squareY2 = squareY + squareSize + Y_SPACING;
squareY = squareY2;
}
}
Create a class which can handle a rectangle. The calls needs a method to draw the rectangle (Draw()) and a method to update the position and size of the rectangle (Update()):
final int DIFF_SIZE = 1;
final int MIN_SIZE = 6;
final int MAX_SIZE = 40;
final float INIT_RED = 100, INIT_GREEN = 50, INIT_BLUE = 80;
final float FINAL_RED = 255, FINAL_GREEN = 200, FINAL_BLUE = 250;
class Rectangle {
int pos_x, pos_y, size;
color col;
Rectangle(int px, int py, int s, color c) {
col = c;
pos_x = px; pos_y = py;
size = s;
}
void Update(int px, int py, int inc_size) {
pos_x = px; pos_y = py;
size += inc_size;
if (size > MAX_SIZE)
size = MIN_SIZE;
float w = float(size - MIN_SIZE) / float(MAX_SIZE - MIN_SIZE);
float redValue = INIT_RED + w * (FINAL_RED - INIT_RED);
float greenValue = INIT_GREEN + w * (FINAL_GREEN - INIT_GREEN);
float blueValue = INIT_BLUE + w * (FINAL_BLUE - INIT_BLUE);
col = color(int(redValue), int(greenValue), int(blueValue));
}
void Draw() {
fill(col);
rect(pos_x-size/2, pos_y-size/2, size, size);
}
}
Use ArrayList to store all the drawn rectangles:
ArrayList<Rectangle> rectangles = new ArrayList<Rectangle>();
Add a global, boolean state (drawingRect) which indicates if the mouse button is currently pressed. Set the state and add new rectangle at the end of the list when the mousePressed() event occurs. rest the state when the mouseReleased() event occurs
boolean drawingRect = false;
void mousePressed() {
drawingRect = true;
color col = color(int(INIT_RED), int(INIT_GREEN), int(INIT_BLUE));
rectangles.add(new Rectangle(mouseX, mouseY, MIN_SIZE, col));
}
void mouseReleased() {
drawingRect = false;
}
Use the method .Update(), to change the location and size of the last rectangle in the list as long as the state drawingRect indicates that a mouse button is pressed.
Continuously draw all te rectangles in a loop:
void setup() {
size(600, 600);
}
void draw() {
if (drawingRect && rectangles.size() > 0) {
Rectangle lastRect = rectangles.get(rectangles.size()-1);
lastRect.Update(mouseX, mouseY, DIFF_SIZE);
}
background(255);
for (int i = 0; i < rectangles.size(); i++) {
Rectangle rect = rectangles.get(i);
rect.Draw();
}
}
I need help figuring out how to draw a checkerboard/quilt like pattern in a nested for loop using draw method in java. My Lab assignment reads as follows.
You must create a QuiltPattern Class and declare two objects of that class. The constructor for this class will accept a parameter that sets a characteristic of the object (like the color), Alternate those objects when drawing the quilt. Make sure that your quilt contains at least 5 blocks across and 7 down. Your QuiltPattern class should include a method called Draw() that draws the pattern on the screen at a specific location. You must use nested loops to draw the quilt.
I have everything mostly written, but I'm having trouble getting a quiltlike/checkerboard like object drawn. I can't seem to get it to line up and so far I only have two rows that are offset. Any help or suggestions to get this to work in a nested loop would be much appreciated. I've been trying to find something similar to this and I haven't have much luck. What am I doing wrong?
This is my QuiltPanel:
import javax.swing.*;
import java.awt.*;
public class QuiltPanel extends JPanel
{
int x = 0, y = 0, count = 0;
private Quilt squareOne, squareTwo;
public QuiltPanel()
{
squareOne = new Quilt(25, Color.blue, x+50, y);
squareTwo = new Quilt(25, Color.green, x+25, y);
setPreferredSize(new Dimension(750, 500));
setBackground(Color.black);
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
for ( count = 0; count <= 10; count = count+1)
{ if ( count % 2 == 0)
{ if ( count <= 5)
{ squareOne.draw(page);
squareOne = new Quilt(25, Color.blue, x, y);
}
else
{ squareOne.draw(page);
squareOne = new Quilt(25, Color.blue, x, y+25);
}
}
else
{ if ( count <= 5)
{ squareTwo.draw(page);
squareTwo = new Quilt(25, Color.green, x, y);
}
else
{ squareTwo.draw(page);
squareTwo = new Quilt(25, Color.green, x, y+25);
}
}
x=x+25;
}
}
}
This is my Quilt Class:
import java.awt.*;
public class Quilt
{
private int height, width, x, y;
private Color color;
public Quilt(int size, Color newColor, int upperX, int upperY)
{
width = size;
height = size;
color = newColor;
x = upperX;
y = upperY;
}
public void draw(Graphics page)
{
page.setColor(color);
page.fillRect(x, y, width, height);
}
public void setHeight(int size)
{
height = size;
}
public void setWidth(int size)
{
width = size;
}
public void setColor(Color newColor)
{
color = newColor;
}
public void setX(int upperX)
{
x = upperX;
}
public void setY(int upperY)
{
y = upperY;
}
public int getHeight()
{
return height;
}
public int getWidth()
{
return width;
}
public Color getColor()
{
return color;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
And if you need it my QuiltPattern (JFrame):
import javax.swing.*;
import java.awt.*;
public class QuiltPattern
{
public static void main(String[] args)
{
JFrame frame = new JFrame("QuiltPattern");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new QuiltPanel());
frame.getContentPane().add(new QuiltPanel());
frame.pack();
frame.setVisible(true);
}
}
Your Quilt class should be QuiltPattern class. So I just copied and pasted that code from Quilt to QuiltPattern, as it's said in the program that QuiltPattern will do the drawing and it will have 2 objects with different drawing properties.
It's always best to keep the Main class separate. I have created a new class QuiltMain to initialize the Frame and Panel. (It's all your code).
Changed the constructor of QuiltPattern (previously Quilt) to accept 2 arguments color and size as location of square should logically be passed to the draw() method itself.
And finally the loop to create the checkerboard pattern. There are in general 3 options.
Options 1.
int initX = getWidth() / 2 - (columnCount * squareSide) / 2;
int initY = getHeight() / 2 - (rowCount * squareSide) / 2;
int squareCount = rowCount * columnCount;
for(int i = 0; i < squareCount; i++) {
int rowI = squareCount / rowCount;
int colJ = squareCount % columnCount;
//draw at (initX + colJ * squareSide, initY + colI * squareSide)
}
Option 2.
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
for(int colJ = -rowCount/2; colJ < rowCount/2; colJ++) { //condition will include <= when rowCount is odd
for(int rowI = -columnCount/2; rowI < columnCount/2; rowI++) {//condition will include <= when columnCount is odd
//draw at (centerX + colJ * squareSide, centerY + colI * squareSide)
}
Option 3:
int initX = getWidth() / 2 - (columnCount * squareSide) / 2;
int initY = getHeight() / 2 - (rowCount * squareSide) / 2;
for(int colJ = 0; colJ < rowCount; colJ++) {
for(int rowI = 0; rowI < columnCount; rowI++) {
//draw at (initX + colJ * squareSide, initY + colI * squareSide)
}
I went with the option 3 as it seemed easiest and most suitable one.
Working code:
QuiltMain
import javax.swing.JFrame;
public class QuiltMain {
public static void main(String[] args) {
JFrame frame = new JFrame("QuiltPattern");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new QuiltPanel());
frame.getContentPane().add(new QuiltPanel());
frame.pack();
frame.setVisible(true);
}
}
QuiltPattern
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class QuiltPattern {
private int height, width, x, y;
private Color color;
public QuiltPattern(int size, Color newColor) {
width = size;
height = size;
color = newColor;
}
public void draw(Graphics page, int x, int y) {
page.setColor(color);
page.fillRect(x, y, width, height);
}
public void setHeight(int size) {
height = size;
}
public void setWidth(int size) {
width = size;
}
public void setColor(Color newColor) {
color = newColor;
}
public void setX(int upperX) {
x = upperX;
}
public void setY(int upperY) {
y = upperY;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public Color getColor() {
return color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
QuiltPanel
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
class QuiltPanel extends JPanel {
int x = 0, y = 0;
int rowCount = 7;
int columnCount = 5;
private QuiltPattern squareOne, squareTwo;
public QuiltPanel() {
squareOne = new QuiltPattern(25, Color.blue);
squareTwo = new QuiltPattern(25, Color.green);
setPreferredSize(new Dimension(750, 500));
setBackground(Color.black);
}
public void paintComponent(Graphics page) {
super.paintComponent(page);
int count = 0;
int squareSide = squareOne.getWidth();
boolean firstOne = true;
int quiltWidth = columnCount * squareSide;
int quiltHeight = rowCount * squareSide;
int initX = (getWidth() - quiltWidth) / 2;
int initY = (getHeight() - quiltHeight) / 2;
for(int colJ = 0; colJ < columnCount; colJ++) {
for(int rowI = 0; rowI < rowCount; rowI++) {
int x = colJ * squareSide + initX;
int y = rowI * squareSide + initY;
if(firstOne) {
squareOne.draw(page, x, y);
} else {
squareTwo.draw(page, x, y);
}
firstOne = !firstOne;
}
}
}
}
I have a problem with a hexagonal grid. I found this code you can see below on Internet, so it's not mine. There are two public classes: hexgame which generates the grid and hexmech which draws and fills every single hexagon. What I'd like to do is basically insert an image into a specific hexagon, but I don't know how to code this and in which part of the classes I should put it. Am I thinking the wrong way?
Thank you very much for your help!
Hexgame
package hex;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class hexgame
{
private hexgame() {
initGame();
createAndShowGUI();
}
final static Color COLOURBACK = Color.WHITE;
final static Color COLOURCELL = Color.WHITE;
final static Color COLOURGRID = Color.BLACK;
final static Color COLOURONE = new Color(255,255,255,200);
final static Color COLOURONETXT = Color.BLUE;
final static Color COLOURTWO = new Color(0,0,0,200);
final static Color COLOURTWOTXT = new Color(255,100,255);
final static Color COLOURSAFE = Color.WHITE;
final static Color COLOURDANGEROUS = Color.LIGHT_GRAY;
final static int EMPTY = 0;
final static int UNKNOWN = -1;
final static int SAFE = 1;
final static int DANGEROUS = 2;
final static int CLICKED = 3;
final static int COLUMN_SIZE = 23;
final static int ROW_SIZE = 14;
final static int HEXSIZE = 45;
final static int BORDERS = 15;
int[][] board = new int[COLUMN_SIZE][ROW_SIZE];
void initGame(){
hexmech.setXYasVertex(false);
hexmech.setHeight(HEXSIZE);
hexmech.setBorders(BORDERS);
for (int i=0;i<COLUMN_SIZE;i++) {
for (int j=0;j<ROW_SIZE;j++) {
board[i][j]=EMPTY;
}
}
board[5][5] = SAFE;
board[5][6] = SAFE;
board[5][7] = SAFE;
board[6][5] = SAFE;
board [6][6] = SAFE;
board[4][4] = UNKNOWN;
}
private void createAndShowGUI()
{
DrawingPanel panel = new DrawingPanel();
JFrame frame = new JFrame("Hex Testing 4");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Container content = frame.getContentPane();
content.add(panel);
frame.setSize(825, 630);
frame.setResizable(true);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
class DrawingPanel extends JPanel
{
public DrawingPanel()
{
setBackground(COLOURBACK);
MyMouseListener ml = new MyMouseListener();
addMouseListener(ml);
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setFont(new Font("TimesRoman", Font.PLAIN, 15));
super.paintComponent(g2);
for (int i=0;i<COLUMN_SIZE;i++) {
for (int j=0;j<ROW_SIZE;j++) {
if (board[i][j] != UNKNOWN)
hexmech.drawHex(i,j,g2);
}
}
for (int i=0;i<COLUMN_SIZE;i++) {
for (int j=0;j<ROW_SIZE;j++) {
if (board[i][j] != UNKNOWN)
hexmech.fillHex(i,j,board[i][j],g2);
}
}
}
class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Point p = new Point( hexmech.pxtoHex(e.getX(),e.getY()) );
if (p.x < 0 || p.y < 0 || p.x >= COLUMN_SIZE || p.y >= ROW_SIZE) return;
board[p.x][p.y] = CLICKED;
repaint();
}
}
}
}
Hexmech
package hex;
import java.awt.*;
import javax.swing.*;
public class hexmech
{
#define HEXEAST 0
#define HEXSOUTHEAST 1
#define HEXSOUTHWEST 2
#define HEXWEST 3
#define HEXNORTHWEST 4
#define HEXNORTHEAST 5
public final static boolean orFLAT= true;
public final static boolean orPOINT= false;
public static boolean ORIENT= orFLAT;
public static boolean XYVertex=true;
private static int BORDERS=50
private static int s=0; // length of one side
private static int t=0; // short side of 30o triangle outside of each hex
private static int r=0; // radius of inscribed circle (centre to middle of each side). r= h/2
private static int h=0; // height. Distance between centres of two adjacent hexes. Distance between two opposite sides in a hex.
public static void setXYasVertex(boolean b) {
XYVertex=b;
}
public static void setBorders(int b){
BORDERS=b;
}
public static void setSide(int side) {
s=side;
t = (int) (s / 2); //t = s sin(30) = (int) CalculateH(s);
r = (int) (s * 0.8660254037844);
h=2*r;
}
public static void setHeight(int height) {
h = height;
r = h/2; // r = radius of inscribed circle
s = (int) (h / 1.73205); // s = (h/2)/cos(30)= (h/2) / (sqrt(3)/2) = h / sqrt(3)
t = (int) (r / 1.73205); // t = (h/2) tan30 = (h/2) 1/sqrt(3) = h / (2 sqrt(3)) = r / sqrt(3)
}
public static Polygon hex (int x0, int y0) {
int y = y0 + BORDERS;
int x = x0 + BORDERS;
if (s == 0 || h == 0) {
System.out.println("ERROR: size of hex has not been set");
return new Polygon();
}
int[] cx,cy;
if (XYVertex)
cx = new int[] {x,x+s,x+s+t,x+s,x,x-t}; //this is for the top left vertex being at x,y. Which means that some of the hex is cutoff.
else
cx = new int[] {x+t,x+s+t,x+s+t+t,x+s+t,x+t,x}; //this is for the whole hexagon to be below and to the right of this point
cy = new int[] {y,y,y+r,y+r+r,y+r+r,y+r};
return new Polygon(cx,cy,6);
}
public static void drawHex(int i, int j, Graphics2D g2) {
int x = i * (s+t);
int y = j * h + (i%2) * h/2;
Polygon poly = hex(x,y);
g2.setColor(hexgame.COLOURCELL);
//g2.fillPolygon(hexmech.hex(x,y));
g2.fillPolygon(poly);
g2.setColor(hexgame.COLOURGRID);
g2.drawString(String.format("%c;%d", 'A'+i, j+1), x+20, y+40);
g2.drawPolygon(poly);
}
public static void fillHex(int i, int j, int n, Graphics2D g2) {
char c='o';
int x = i * (s+t);
int y = j * h + (i%2) * h/2;
/*if (n < 0) {
g2.setColor(hexgame.COLOURONE);
g2.fillPolygon(hex(x,y));
g2.setColor(hexgame.COLOURONETXT);
c = (char)(-n);
g2.drawString(""+c, x+r+BORDERS, y+r+BORDERS+4); //FIXME: handle XYVertex
//g2.drawString(x+","+y, x+r+BORDERS, y+r+BORDERS+4);
}
if (n > 0) {
g2.setColor(hexgame.COLOURTWO);
g2.fillPolygon(hex(x,y));
g2.setColor(hexgame.COLOURTWOTXT);
c = (char)n;
if (n==3) {
g2.setColor(hexgame.COLOURTWO);
g2.fillPolygon(hex(x,y));
g2.setColor(hexgame.COLOURTWOTXT);
}
}
public static Point pxtoHex(int mx, int my) {
Point p = new Point(-1,-1);
//correction for BORDERS and XYVertex
mx -= BORDERS;
my -= BORDERS;
if (XYVertex) mx += t;
int x = (int) (mx / (s+t));
int y = (int) ((my - (x%2)*r)/h);
int dx = mx - x*(s+t);
int dy = my - y*h;
if (my - (x%2)*r < 0) return p; // prevent clicking in the open halfhexes at the top of the screen
//System.out.println("dx=" + dx + " dy=" + dy + " > " + dx*r/t + " <");
//even columns
if (x%2==0) {
if (dy > r) { //bottom half of hexes
if (dx * r /t < dy - r) {
x--;
}
}
if (dy < r) { //top half of hexes
if ((t - dx)*r/t > dy ) {
x--;
y--;
}
}
} else { // odd columns
if (dy > h) { //bottom half of hexes
if (dx * r/t < dy - h) {
x--;
y++;
}
}
if (dy < h) { //top half of hexes
//System.out.println("" + (t- dx)*r/t + " " + (dy - r));
if ((t - dx)*r/t > dy - r) {
x--;
}
}
}
p.x=x;
p.y=y;
return p;
}
In your implementation of paintComponent(), invoke setClip() with a suitable Shape, such as Polygon. You can size and translate the Polygon to match the destination hexagon using the createTransformedShape() method of AffineTransform. Use the coordinates of the polygon's boundary as the basis for the coordinates used in your call to drawImage(). A related example using Ellipse2D is shown here.
Aloha,
i have trouble finding the error in my java code. In my opinion everything is fine and correct but the function is not executed correctly and I dont understand why. The function should detect the difference between the colors and calculate the arithmetic mean of them.
The resilt of it should be draw under the original picture. What did I miss, please help me?
package edge;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import javax.swing.JComponent;
import javax.swing.JFrame;
/**
*
* #author Alaska
*/
public class Edge extends JComponent {
final int W = 500;
final int H = 300;
Image m_TrgImg, m_SrcImg;
public Edge(JFrame father) {
try {
FileDialog diag = new FileDialog(father);
diag.setVisible(true);
m_SrcImg = getToolkit().getImage(diag.getDirectory() + diag.getFile()).getScaledInstance(W, H, Image.SCALE_SMOOTH);
MediaTracker mt = new MediaTracker(this);
mt.addImage(m_SrcImg, 0);
mt.waitForAll();
int[] srcPix = new int[W * H];
int[] trgPix = new int[W * H];
PixelGrabber grab = new PixelGrabber(m_SrcImg, 0, 0, W, H, srcPix, 0, W);
grab.getPixels();
MemoryImageSource imgProd = new MemoryImageSource(W, H, trgPix, 0, W);
m_TrgImg = createImage(imgProd);
detectEdges(srcPix, trgPix);
m_TrgImg.flush();
} catch (InterruptedException e) {
System.out.println(e);
}
}
#Override
public void paintComponent(Graphics g) {
g.drawImage(m_SrcImg, 0, 0, this);
g.drawImage(m_TrgImg, 0, H, this);
}
#Override
public Dimension getPreferredSize() {
return getMinimumSize();
}
#Override
public Dimension getMinimumSize() {
return new Dimension(W, H * 2);
}
private void detectEdges(int[] srcPix, int[] trgPix) {
for (int x = 0; x < W; ++x) {
for (int y = 0; y < H; ++y) {
trgPix[y * W + x] = compColor(srcPix, x, y);
}
}
}
private int getRed(int col) {
return (col >> 16) & 255;
}
private int getGreen(int col) {
return (col >> 8) & 255;
}
private int getBlue(int col) {
return col & 255;
}
private int compColor(int[] srcPix, int x, int y) {
int red = 0;
int green = 0;
int blue = 0;
int cnt = 0;
final int IDX = y * W + x;
final int RED = getRed(srcPix[IDX]);
final int GREEN = getGreen(srcPix[IDX]);
final int BLUE = getBlue(srcPix[IDX]);
for (int dx = -1; dx <= 1; ++dx) {
for (int dy = -1; dy <= 1; ++dy) {
if (dx != 0 || dy != 0) {
final int X = x + dx;
final int Y = y + dy;
final int LOCAL_IDX = Y * W + X;
if (0 <= X && X < W && 0 <= Y && Y < H) {
++cnt;
red += Math.abs(RED - getRed(srcPix[LOCAL_IDX]));
green += Math.abs(GREEN - getGreen(srcPix[LOCAL_IDX]));
blue += Math.abs(BLUE - getBlue(srcPix[LOCAL_IDX]));
}
}
}
}
return 0xff000000 | (255 - (red / cnt) << 16) | (255 - (green / cnt) << 8) | (255 - (blue / cnt));
}
public static void main(String[] args) throws Exception {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.getContentPane().add(new Edge(f));
f.pack();
f.setVisible(true);
}
}
You need to grab.grabPixels(), not grab.getPixels().
http://docs.oracle.com/javase/7/docs/api/java/awt/image/PixelGrabber.html
Also what trashgod said about Initial Threads. You need to create your GUI with SwingUtilities.invokeLater().
Edit
The method is executed correctly but you are getting all black values on the input because your pixel array contains only the initialized values which is 0.