Relatively new to Java, coding for a school project.
I'm using JFrame and JComponent, drawing patterns and strings and all that fun stuff.
Currently, I have a class written that extends JComponent. This is the class where I am defining most of my shapes. The issue is that I initialized my Jframe
(Code: JFrame myFrame = new JFrame() ) in the main of one class, but I need to access myFrame.getWidth() in the JComponent class that I'm working in.
How can I access variables getWidth() and getHeight() in "public class MyJComponent extends JComponent" , when I defined myFrame in 'public class Lab2' ??
Edit for code:
public class Lab2 {
public static void main(String[] args) {
System.out.println("Hello Java");
JFrame myFrame = new JFrame();
myFrame.setSize(500, 500);
myFrame.setTitle("Color Test");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyJComponent myComponent = new MyJComponent(500, 500);
myFrame.add(myComponent);
myFrame.getContentPane().setBackground(Color.white); //sets background color.
myFrame.setVisible(true); // setVisible() *after* add() is the norm
//Deciding geometry of hidden shape. paintComponent is called once per run, this is called afterwards.
}
}
/**/
public class MyJComponent extends JComponent {
int[] circleX;
int[] circleY;
int[] circleR;
final int MIN_RADIUS = 5;
final int MAX_RADIUS = 15;
final int MIN_SEPARATION = 1;
final int MAX_ATTEMPTS = 5000;
final int MAX_CIRCLES = 1000;
Random rand;
int initialWidth;
int initialHeight;
int numCircles; // actual number of circles drawn
// are circles at index i and index j separated by *<= tolerance* pixels?
boolean twoCirclesOverlap(int i, int j, int tolerance) {
double distanceBetweenCenters =
Math.sqrt((circleX[i] - circleX[j]) * (circleX[i] - circleX[j]) +
(circleY[i] - circleY[j]) * (circleY[i] - circleY[j]));
return (distanceBetweenCenters <= (circleR[i] + circleR[j] + tolerance));
}
// are any existing circles separated from the proposed one at index i by *<= tolerance* pixels?
boolean anyCirclesOverlap(int i, int tolerance) {
for (int j = 0; j < i; j++) {
if (twoCirclesOverlap(i, j, tolerance)) {
return true;
}
}
return false;
}
// attempt to randomly place the largest-possible circle that does not overlap any existing one
boolean tryToPlaceCircle(int i) {
for (int j = 0; j < MAX_ATTEMPTS; j++) {
// pick a random position, set initial radius to minimum
circleX[i] = rand.nextInt(initialWidth);
circleY[i] = rand.nextInt(initialHeight);
circleR[i] = MIN_RADIUS;
// grow circle until it touches another or reaches max size
while (!anyCirclesOverlap(i, MIN_SEPARATION) && circleR[i] < MAX_RADIUS)
circleR[i]++;
// it was touching from the start -- must try again
if (circleR[i] == MIN_RADIUS) {
continue;
}
// grew to max size -- well done
else if (circleR[i] == MAX_RADIUS) {
return true;
}
// grew some, but then touched
else {
circleR[i]--; // retract to the step before touch
return true;
}
}
// all attempts failed
return false;
}
MyJComponent(int width, int height) {
circleX = new int[MAX_CIRCLES];
circleY = new int[MAX_CIRCLES];
circleR = new int[MAX_CIRCLES];
initialWidth = width;
initialHeight = height;
rand = new Random();
numCircles = 0;
while (numCircles < MAX_CIRCLES && tryToPlaceCircle(numCircles)) {
numCircles++;
}
}
//Override paintComponent
public void paintComponent(Graphics g) {
for (int i = 0; i < numCircles; i++) {
g.drawOval(circleX[i] - circleR[i], circleY[i] - circleR[i], 2 * circleR[i], 2 * circleR[i]);
}
}
//Shape decision
public void shapeDecision() {
double randomShapeDecider = Math.random();
if (randomShapeDecider > .50) {
//shape is circle, define it's properties
hiddenCircleDiameter = myFrame.getWidth();
}
else {
//shape is rectangle
hiddenRectangleWidth = myFrame.getWidth();
}
}
}
Related
So this is the class where I create the circles which works fine.
public class CircleAnimations {
private ArrayList<Circle> circles; // the circles to animate
private int size; // canvas width and height (will be square)
private Random rng; // use to make random numbers
/** create a drawing pane of a particular size */
public CircleAnimations(int s) {
circles = new ArrayList<>();
size = s;
rng = new Random();
//don't mess with this
StdDraw.setCanvasSize(size, size); // set up drawing canvas
StdDraw.setXscale(0, size); // <0, 0> is bottom left. <size-1, size-1> is top right
StdDraw.setYscale(0, size);
}
public void drawCircle() {
for (int i = 0; i < circles.size(); i++) {
circles.get(i).draw();
}
}
public void addCircle() {
circles.add(new Circle(rng.nextInt(size - 1), rng.nextInt(size - 1), rng.nextInt(75),
new Color(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255))));
circles.add(new Circle(rng.nextInt(size - 1), rng.nextInt(size - 1), rng.nextInt(75),
new Color(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255))));
circles.add(new Circle(rng.nextInt(size - 1), rng.nextInt(size - 1), rng.nextInt(75),
new Color(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255))));
drawCircle();
}
public void removeClicked() {
addCircle();
while (circles.size() > 0) {
for (int i = circles.size() - 1; i > 0; i--) {
double mouseXPos = StdDraw.mouseX();
double mouseYPos = StdDraw.mouseY();
if (StdDraw.isMousePressed()) {
if (mouseXPos < circles.get(i).getX() + circles.get(i).getRadius()
|| mouseXPos > circles.get(i).getX() - circles.get(i).getRadius()) {
if (mouseYPos < circles.get(i).getY() + circles.get(i).getRadius()
|| mouseYPos > circles.get(i).getX() - circles.get(i).getRadius()) {
circles.remove(i);
drawCircle();
}
}
}
}
}
}
}
The method for deleting the circle which was clicked on isn't working for some reason.
I made the game already and wanted to make my GUI look better with rectangles not with jlabels and now I´ve come to realize that only the last rectangle that is drawn is shown on the GUI
I already tried it with different layouts
my GUI class:
public class GUI_N
{
private Spiel spiel;
private KeyEvent e;
private String beste;
private int beste1;
private DrawingComponent[][] feld;
GUI_N(){
feld = new DrawingComponent[4][4];
spiel = new Spiel();
beste1 = 0;
beste = "Highscore: "+beste1;
JFrame g=new JFrame("2048 - Main");
g.setSize(500,500);
g.setFocusable(true); //wichtig für KeyListener
g.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int i = 0;
int j = 0;
int h = 0;
int l = 0;
while(i<4)
{
while(j<4)
{
if(i==0){
h = 50;
}else if(i==1){
h = 100;
}else if(i==2){
h = 150;
}else if(i==3){
h = 200;
}
if(j==0){
l = 50;
}else if(j==1){
l = 100;
}else if(j==2){
l = 150;
}else if(j==3){
l = 200;
}
feld[i][j] = new DrawingComponent(l,h,50,50);
feld[i][j].setBounds(l,h,50,50);
j++;
}
j=0;
i++;
}
i = 0;
j = 0;
while(i<4)
{
while(j<4)
{
g.add(feld[i][j]);
j++;
}
j=0;
i++;
}
//g.getContentPane().setBackground(new Color(20, 40, 50));
g.setVisible(true);
}
public static void main(String[] args) {
new GUI_N();
}
}
my rectangle class:
public class DrawingComponent extends JComponent
{
private Graphics2D g2;
private int wert;
private int x;
private int y;
private int w;
private int h;
public DrawingComponent(int px,int py,int pw,int ph)
{
x=px;
y=py;
w=pw;
h=ph;
}
public void paintComponent(Graphics g)
{
g2 = (Graphics2D) g;
Rectangle rect1 = new Rectangle(x,y,w,h);
g2.setColor(Color.RED);
g2.fill(rect1);
}
public void setWert(int x)
{
wert = x;
}
public int getWert()
{
return wert;
}
}
as I said only the last drawn rectangle is shown.
How do I achieve this?
Right now you're adding the rectangles directly to your frame. You should have a JPanel layer in between, to which you can give a LayoutManager (GridLayout would be a good one to look at) to arrange all your rectangles.
So you would have something like this:
JFrame g = new JFrame("2048 - Main");
// GridLayout (on next line) takes number of rows and columns
JPanel panel = new JPanel(new GridLayout(4, 4));
// ... add all the rectangles to the panel here
g.add(panel);
And then you would add your rectangles to the panel, not the frame. As you add them, they will automatically go into place in the grid.
panel.add(feld[i][j]);
Also, if you use GridLayout, it will resize and fit the components to the grid dynamically, so it may save you some code as well, since you wouldn't need to hardcode their sizes in the GUI class.
So am working on a School Project, and I want to draw a game board made out of Rectangles which are saved in an array. I managed to do that, but only the last drawn Rectangle Stays on the Panel. I'm really desperate and i don't know where my mistake is.
The Field is a 4x5 field. The Coordinates saved in the Tile Class:
the first two represent the upper left Corner
the last two represent the bottom right corner of it
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class quoVadis{
public static void main(String[] args) {
new Frame();
}
}
class Tile {
Random rGen = new Random();
int sX,sY,eX,eY;
Color farbe;
public Tile(int sX, int sY,int eX,int eY){
this.sX = sX;
this.sY = sY;
this.eX = eX;
this.eY = eY;
farbe = new Color(rGen.nextInt(156)+100,rGen.nextInt(156)+100,rGen.nextInt(156)+100);
}
}
class Frame extends JFrame{
private Game game;
final int GAMESIZE = 400;
final int PANELSIZE = GAMESIZE/5;
public Frame() {
super("Quo Vadis");
this.setSize(GAMESIZE, GAMESIZE*5/4);
this.setLocation(50, 50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game = new Game(GAMESIZE, PANELSIZE);
game.setLayout(null);
game.setBackground(Color.WHITE);
this.getContentPane().add(game);
this.setVisible(true);
}
}
class Game extends JPanel{
int GAMESIZE;
int PANELSIZE;
private Tile field[][]=new Tile[4][5];
Random rGen = new Random(4711);
Tile stein;
public Game(int g, int p) {
GAMESIZE = g;
PANELSIZE = p;
// The Mistake has to be in this following Part:
int idx=0;
for(Tile i:levels){
for(int j = i.sX; j <= i.eX; j++){
for(int k = i.sY; k <= i.eY; k++){
field[j][k] = levels[idx];
}
}
idx++;
}
for(int k = 0; k <= 4; k++){
for(int j = 0; j <= 3; j++){
if(field[j][k]==null)continue;
stein=field[j][k];
draw((field[j][k].sX * PANELSIZE) , (field[j][k].sY * PANELSIZE) , ((((field[j][k].eX-field[j][k].sX) + 1) * PANELSIZE) -1), ((((field[j][k].eY-field[j][k].sY)+ 1) * PANELSIZE) -1));
}
}
this.setVisible(true);
}
int rx, ry,rdx,rdy;
private void draw(int a, int b, int c, int d){
rx=a;
ry=b;
rdx=c;
rdy=d;
repaint(rx,ry,rdx,rdy);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(stein.farbe);
g.fillRect(rx, ry, rdx, rdy);
}
Tile[] levels = {
new Tile(1,0,2,1),
new Tile(0,0,0,1),
new Tile(3,0,3,1),
new Tile(0,2,0,3),
new Tile(1,2,2,2),
new Tile(3,2,3,3),
new Tile(0,4,0,4),
new Tile(1,3,1,3),
new Tile(2,3,2,3),
new Tile(3,4,3,4),
};
}
I already checked the Position of the Rectangles in numbers and they are correct in every way so they do not overlap or something like that.
Sorry for my bad english, it's not my primary language.
You need to draw each rectangle inside of your paintComponent method every time.
Currently you are calling your draw method for one rectangle then you call repaint and draw that single rectangle. paintComponent will redraw the entire panel each time it is called. This means that it will on preserve the last rectangle (the rest were "repainted over".
You want to loop through all of your tiles and use the drawRect method to draw them inside of your paintComponent method so they will be drawn every time.
public void paintComponent(Graphics g) {
super.paintComponent(g)
for(int k = 0; k <= 4; k++){
for(int j = 0; j <= 3; j++){
if(field[j][k]==null)continue;
stein=field[j][k];
g.setColor(stein.farbe);
g.fillRect((field[j][k].sX * PANELSIZE) , (field[j][k].sY * PANELSIZE) , ((((field[j][k].eX-field[j][k].sX) + 1) * PANELSIZE) -1), ((((field[j][k].eY-field[j][k].sY)+ 1) * PANELSIZE) -1));
}
}
}
I have a chessboard, made by overriding the paint() method of a class extending Panel. I highlight all the possible squares a chess piece can go to on the board, and store the pixel values of the upper left corners of the highlighted squares in the:
private ArrayList<Integer> highlightedSquares = new ArrayList<Integer>();
topLeftVal is an array with all of the top left corner values of the squares. In the mouseClicked method of the mouseAdapter, I want to know when a highlighted square (and only a highlighted square) is clicked, and then call repaint(). However, for some reason the program also accepts many squares that are not highlighted.
Here is the code (I apologize for the formatting):
public void mouseClicked(MouseEvent e){
clickPointX = e.getX();
clickPointY = e.getY();
//iterate through highlightedSquares and if the clicked pt is in one of them, repaint
int q = 0;
int xCoor = 0, yCoor = 0;
for(int a : highlightedSquares){
if(q % 2 == 0)
xCoor = a;
else{
yCoor = a;
if((xCoor <= clickPointX) && (clickPointX <= (xCoor + 80)) && (yCoor <= clickPointY) && (clickPointY <= (yCoor + 80))){ //I think this line is causing the problem?
_pixX=xCoor;
_pixY=yCoor;
for(int i = 0; i < topLeftVal.length;i++){
if(topLeftVal[i] == _pixX)
_x = i;
if(topLeftVal[i] == _pixY)
_y = i;
}
repaint();
break;
} //end of if inside else
} //end of else
q++;
} //end of foreach
} //end of mouseClicked
Here is an example implementation where I defined two classes -- Board and Square. Board is derived from JPanel. Square represents a single square on the board. My mouse click listener displays a message which indicates whether or not the clicked upon square is highlighted. Hopefully this will give you a good idea of how to modify your code to achieve the desired result.
public class TestMain {
public static void main(String[] args) throws Exception {
new TestMain().run();
}
public void run() {
// create and show a JFrame containing a chess board
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Board board = new Board();
board.getSquare(2, 4).setHighlighted(true);
board.getSquare(3, 4).setHighlighted(true);
window.getContentPane().add(board, BorderLayout.NORTH);
window.pack();
window.setVisible(true);
}
// *** Board represents the chess board
private class Board extends JPanel {
// *** the constructor creates the squares and adds a mouse click listener
public Board() {
setPreferredSize(new Dimension(squareSize * 8, squareSize * 8));
// create the squares
boolean rowStartRedFlag = true;
for (int row = 0; row < 8; row++) {
boolean redFlag = rowStartRedFlag;
for (int column = 0; column < 8; column++) {
squares [row] [column] = new Square(this, row, column, redFlag);
redFlag = !redFlag;
}
rowStartRedFlag = !rowStartRedFlag;
}
// add mouse click listener
this.addMouseListener(new MouseClickListener());
}
// *** mouse click listener
private class MouseClickListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
Square square = getSquareAt(e.getX(), e.getY());
String msg = square.isHighlighted() ? "Square is highlighted" : "Square is not highlighted";
JOptionPane.showMessageDialog(null, msg);
}
}
// ** override paint
#Override
public void paint(Graphics g) {
draw ((Graphics2D) g);
}
// *** draw every square on the board
public void draw(Graphics2D g) {
for (int row = 0; row < squares.length; row++) {
for (int column = 0; column < squares [row].length; column++) {
squares [row] [column].draw(g);
}
}
}
// *** get square given row and column
public Square getSquare(int row, int column) {
return squares [row] [column];
}
// *** get square from coords
public Square getSquareAt(int x, int y) {
int column = getColumnAtX(x);
int row = getRowAtY(y);
return squares [row] [column];
}
// *** get column # given x
public int getColumnAtX(int x) {
int column = x / squareSize;
return Math.min(Math.max(column, 0), 7);
}
// *** get row # given x
public int getRowAtY(int y) {
int row = y / squareSize;
return Math.min(Math.max(row, 0), 7);
}
// ** get left x given column
public int getLeftFromColumn(int column) {
return column * squareSize;
}
// ** get top y give row
public int getTopFromRow(int row) {
return row * squareSize;
}
// *** get size of square side
public int getSquareSize() {
return squareSize;
}
private int squareSize = 25; // length of square side
private Square [][] squares = new Square [8][8];
}
// *** Squalre represents one square on the board
private class Square {
// ** constructor creates the square
public Square(Board board, int row, int column, boolean redFlag) {
this.board = board;
this.column = column;
this.row = row;
if (redFlag) {
color = Color.RED;
colorHighlighted = Color.PINK;
} else {
color = Color.BLACK;
colorHighlighted = Color.LIGHT_GRAY;
}
}
// ** set highlight flag
public void setHighlighted(boolean value) {
highlighted = value;
}
// *** see if square is highlighted
public boolean isHighlighted() {
return highlighted;
}
// *** draw the square
public void draw(Graphics2D g) {
Color fillColor = highlighted ? colorHighlighted : color;
g.setColor(fillColor);
int x = board.getLeftFromColumn(column);
int y = board.getTopFromRow(row);
int size = board.getSquareSize();
g.fillRect(x, y, size, size);
}
private Board board;
private Color color;
private Color colorHighlighted;
private int column;
private boolean highlighted = false;
private int row;
}
}
I explained that horridly in the title, and I apologize, am very new to java and don't quite understand some of it yet.
Anyway,
My cat animation runs to the middle of the screen, scratches twice, then continues to run to the end, is there anyway to write a method that will take an INT NUM and make the cat scratch x amount of times? Not sure how to go about doing this.
Any help would be great,
Here is my current code
/** Run the animation. */
public void nekoRun() {
moveIn();
scratch();
//scratch2(5);
moveOut();
}
/* Move Neko to the centre of the panel. */
private void moveIn() {
for (int i = 0; i < getWidth()/2; i+=10) {
xPos = i;
// swap images
if (currentImage == nekoPics[0])
currentImage = nekoPics[1];
else
currentImage = nekoPics[0];
repaint();
pause(150);
}
}
private void scratch() {
for (int i = 0; i < 10; i++) {
// Swap images.
currentImageIndex = nextImageList[currentImageIndex];
currentImage = nekoPics[currentImageIndex];
repaint();
pause(150);
}
}
private void moveOut() {
for (int i = xPos; i < getWidth(); i+=10) {
xPos = i;
// swap images
if (currentImage == nekoPics[0])
currentImage = nekoPics[1];
else
currentImage = nekoPics[0];
repaint();
pause(150);
}
}