I'm trying to implement the game dots and boxes by using 3 JLabel arrays:
the dots for the game board.
the vertical lines
the horizontal lines
the ide is when you click using MouseInputAdapter to get the coordinates of the mouse the it should check if the coordinates of mouse point are in one of the labels of the verticals or horizontal lines. But when I run the program my JPanel is completly empty. And other times when I run it and it's not empty all the labels just vanish after I click.
package gameframes;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.MouseInputAdapter;
import java.awt.Color;
public class LinesAndBoxesFrame extends JFrame {
JLabel[][] dots = new JLabel[8][8];
JLabel[][] herizontalLines = new JLabel[8][7];
JLabel[][] verticallLines = new JLabel[8][7];
public LinesAndBoxesFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(620, 640);
setLocationRelativeTo(null);
setVisible(true);
setLayout(null);
JPanel p=new JPanel();
p.setSize(600,600);
add(p);
for (int i = 0; i < dots.length; i++) {
for (int j = 0; j < dots.length; j++) {
dots[i][j] = new JLabel();
dots[i][j].setBounds(20 + i * (20 + 50), 20 + j * (20 + 50), 20, 20);
dots[i][j].setOpaque(true);
dots[i][j].setBackground(Color.red);
p.add(dots[i][j]);
p.repaint();
}
}
for (int i = 0; i < herizontalLines.length; i++) {
for (int j = 0; j < herizontalLines[0].length; j++) {
herizontalLines[i][j] = new JLabel();
herizontalLines[i][j].setBounds(40 + j * (20 + 50), 20 + i * (20 + 50), 50, 20);
herizontalLines[i][j].setOpaque(true);
herizontalLines[i][j].setBackground(Color.green);
herizontalLines[i][j].setVisible(false);
p.add(herizontalLines[i][j]);
p.repaint();
}
}
for (int i = 0; i < verticallLines.length; i++) {
for (int j = 0; j < verticallLines[0].length; j++) {
verticallLines[i][j] = new JLabel();
verticallLines[i][j].setBounds(20 + i * (20 + 50), 40 + j * (20 + 50), 20, 50);
verticallLines[i][j].setOpaque(true);
verticallLines[i][j].setBackground(Color.green);
verticallLines[i][j].setVisible(false);
p.add(verticallLines[i][j]);
p.repaint();
}
}
p.addMouseListener(new MouseInputAdapter() {
int count = 0;
#Override
public void mouseClicked(MouseEvent e) {
int mX = e.getX();
int mY = e.getY();
System.out.println(mX);
System.out.println(mY);
boolean b = false;
for (JLabel[] l : herizontalLines) {
for (JLabel l1 : l) {
b = checkBounds(l1, mX, mY);
if (b) {
l1.setVisible(true);
break;
}
}
}
if (!b) {
for (JLabel[] l : verticallLines) {
for (JLabel l1 : l) {
b = checkBounds(l1, mX, mY);
if (b) {
l1.setVisible(true);
break;
}
}
}
}
System.out.println(b + " metod finished! " + count);
p.revalidate();
p.repaint();
count++;
}
});
// add(p);
// repaint();
p.revalidate();
p.repaint();
}
public boolean checkBounds(JLabel l, int x, int y) {
return (x >= l.getX() && x <= l.getX() + l.getWidth()) && (y >= l.getY() && y <= l.getY() + l.getHeight());
}
public static void main(String[] args) {
new LinesAndBoxesFrame("Dots and Boxes");
}
}
Update:
I just needed to set the layout of my JPanel to null and that fixes it.
Related
I'm here to ask a little help with a problem I've had for many hours.
In practice, I would like to be able to pass the variables 'j' and 'k' through a method in a matrix. The problem lies in passing them, which, without understanding the reason, are not "captured" when they enter the if. In fact, if I try to print 'r' and 'c' before the if, they match. I do not understand where I'm wrong, because the other things inside the if work perfectly, but when I try to print 'r' and 'c' inside the if, they always turn out to be 0.
Buttons creation :
Integer[] x = {10, 70, 130, 190, 250, 310, 370}; Integer[] y = {80, 140, 200, 260, 320, 380};
for (int i = 0, k = 0, j = 0; i < 42; i++, j++) {
if (j % 7 == 0 && i != 0) { j = 0; k++; }
lblCircles[i] = new JLabel(new ImageIcon(this.getClass().getResource("vuoto.png")));
lblCircles[i].setBounds(x[j], y[k], 50, 50);
lblCircles[i].setName("vuota");
lblCircles[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
for (int i = 0; i < 42; i++) {
for (int j = 0; j < 6; j++) {
for (int k = 0; k < 7; k++)
if (e.getSource() == lblCircles[i] && choose == 1) lblClickedPlayer(lblCircles[i], j, k);
}
}
}
});
frame.getContentPane().add(lblCircles[i]);
}
The method :
public void lblClickedPlayer(JLabel lbl, int r, int c) {
if (n == 0 && "vuota".equals(lbl.getName())) {
n = 1;
lbl.setIcon(new ImageIcon(this.getClass().getResource("red.png")));
lbl.setName("piena");
tbl[r][c] = 1;
System.out.println("tbl[" + r + "][" + c + "] = " + tbl[r][c]);
} else if (n == 1 && "vuota".equals(lbl.getName())) {
n = 0;
lbl.setIcon(new ImageIcon(this.getClass().getResource("yellow.png")));
lbl.setName("piena");
tbl[r][c] = 2;
System.out.println("tbl[" + r + "][" + c + "] = " + tbl[r][c]);
}
}
Thanks in advance for the help.
Code for a test :
public class Prova {
public JFrame frame;
public JLabel[] lblCircles = new JLabel[42];
public String hostname;
public Font big = new Font("Comic Sans MS", Font.BOLD, 18);
public Integer[][] tbl = new Integer[6][7];
public int choose = 1, n = 0;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Prova window = new Prova();
window.frame.setVisible(true);
} catch (Exception e) { e.printStackTrace(); }
}
});
}
public Prova() { initialize(); }
private void initialize() {
frame = new JFrame();
baseFrame(frame, 430, 510);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(6, 7));
panel.setBackground(new Color(41, 41, 41));
panel.setBounds(10, 80, 410, 350);
frame.getContentPane().add(panel);
Integer[] x = {10, 70, 130, 190, 250, 310, 370}; Integer[] y = {80, 140, 200, 260, 320, 380};
for (int i = 0, k = 0, j = 0; i < 42; i++, j++) {
if (j % 7 == 0 && i != 0) { j = 0; k++; }
lblCircles[i] = new JLabel("test");
lblCircles[i].setBounds(x[j], y[k], 50, 50);
lblCircles[i].setForeground(Color.RED);
lblCircles[i].setFont(big);
lblCircles[i].setName("vuota");
lblCircles[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
for (int i = 0; i < 42; i++) {
for (int j = 0; j < 6; j++) {
for (int k = 0; k < 7; k++) {
if (e.getSource() == lblCircles[i] && choose == 1) lblClickedPlayer(lblCircles[i], j, k);
}
}
}
}
});
panel.add(lblCircles[i]);
}
}
public void baseFrame(JFrame baseFrame, int width, int height) {
baseFrame.getContentPane().setBackground(new Color(41, 41, 41));
baseFrame.setBounds(100, 100, width, height);
baseFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
baseFrame.getContentPane().setLayout(null);
baseFrame.setUndecorated(true);
baseFrame.setLocationRelativeTo(null);
baseFrame.setResizable(false);
baseFrame.setVisible(true);
baseFrame.setShape(new RoundRectangle2D.Double(0, 0, baseFrame.getWidth(), baseFrame.getHeight(), 30, 30));
}
public void lblClickedPlayer(JLabel lbl, int r, int c) {
if (n == 0 && "vuota".equals(lbl.getName())) {
n = 1;
lbl.setText("ok1");
lbl.setForeground(Color.GREEN);
lbl.setName("piena");
tbl[r][c] = 1;
System.out.println("tbl[" + r + "][" + c + "] = " + tbl[r][c]);
} else if (n == 1 && "vuota".equals(lbl.getName())) {
n = 0;
lbl.setText("ok2");
lbl.setForeground(Color.GREEN);
lbl.setName("piena");
tbl[r][c] = 2;
System.out.println("tbl[" + r + "][" + c + "] = " + tbl[r][c]);
}
}
}
You don't want those inner loops, since i is all you need. You can calculate the row and column from the i value easily by using int division and int remainder
int r = i / COLS;
int c = i % COLS;
For example
public class Prova {
private static final int ROWS = 6;
private static final int COLS = 7;
// ....
lblCircles[i].addMouseListener(new MouseAdapter() {
// better to use mousePressed, not mouseClicked
public void mousePressed(MouseEvent e) {
// no magic numbers such as 42 please.
for (int i = 0; i < lblCircles.length; i++) {
if (e.getSource() == lblCircles[i] && choose == 1) {
myLabelClicked(lblCircles[i], i);
}
}
}
});
and
public void myLabelClicked(JLabel label, int i) {
int r = i / COLS;
int c = i % COLS;
if (n == 0 && "vuota".equals(label.getName())) {
n = 1;
label.setText("ok1");
label.setForeground(Color.GREEN);
label.setName("piena");
tbl[r][c] = 1;
} else {
n = 0;
label.setText("ok2");
label.setForeground(Color.GREEN);
label.setName("piena");
tbl[r][c] = 2;
}
System.out.println("tbl[" + r + "][" + c + "] = " + tbl[r][c]);
}
Side issues:
Yes, much better using layout managers rather than setBounds, and so your second bit of code is better
Avoid magic numbers such as 42 and instead use properties and constants.
In my code above ROWS = 6 and COLS = 7
My MCVE:
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class Prova2 extends JPanel {
private static final int ROWS = 6;
private static final int COLS = 7;
private static final int LBL_EB = 25; // "eb" for empty border
private static final int PNL_EB = 3;
public static final Font BIG = new Font("Comic Sans MS", Font.BOLD, 18);
private static final Color BACKGROUND = new Color(41, 41, 41);
private static final String VUOTA = "vuota";
private JLabel[] lblCircles = new JLabel[ROWS * COLS];
private Integer[][] tbl = new Integer[ROWS][COLS];
private int choose = 1, n = 0;
public Prova2() {
setBorder(BorderFactory.createEmptyBorder(PNL_EB, PNL_EB, PNL_EB, PNL_EB));
setLayout(new GridLayout(ROWS, COLS));
setBackground(BACKGROUND);
for (int i = 0; i < lblCircles.length; i++) {
lblCircles[i] = new JLabel("test");
lblCircles[i].setForeground(Color.RED);
lblCircles[i].setFont(BIG);
lblCircles[i].setBorder(BorderFactory.createEmptyBorder(LBL_EB, LBL_EB, LBL_EB, LBL_EB));
lblCircles[i].setName(VUOTA);
lblCircles[i].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
for (int i = 0; i < lblCircles.length; i++) {
if (e.getSource() == lblCircles[i] && choose == 1) {
myLabelClicked(lblCircles[i], i);
}
}
}
});
add(lblCircles[i]);
}
}
protected void myLabelClicked(JLabel label, int i) {
int row = i / COLS;
int col = i % COLS;
if (!VUOTA.equals(label.getName())) {
return;
}
if (n == 0) {
n = 1;
label.setText("ok1");
tbl[row][col] = 1;
} else {
n = 0;
label.setText("ok2");
tbl[row][col] = 2;
}
label.setForeground(Color.GREEN);
label.setName("piena");
System.out.printf("tbl[%d][%d] = %d%n", row, col, tbl[row][col]);
}
private static void createAndShowGui() {
Prova2 mainPanel = new Prova2();
JFrame frame = new JFrame("Prova 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
the code im trying to manipulate is the paint method... i'm trying to get it to show a chess board by filling in the squares evenly, but when i run the programme and move the slider to a even number it gives me one column with black one colum with empty etc.
when at an odd number it is the chess board
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class Blobs extends JFrame implements ActionListener, ChangeListener {
private MyCanvas canvas = new MyCanvas();
private JSlider sizeSl = new JSlider(0, 20, 0);
private JButton reset = new JButton("RESET");
private int size = 0; // number of lines to draw
public static void main(String[] args) {
new Blobs();
}
public Blobs() {
setLayout(new BorderLayout());
setSize(254, 352);
setTitle("Blobs (nested for)");
sizeSl.setMajorTickSpacing(5);
sizeSl.setMinorTickSpacing(1);
sizeSl.setPaintTicks(true);
sizeSl.setPaintLabels(true);
add("North", sizeSl);
sizeSl.addChangeListener(this);
add("Center", canvas);
JPanel bottom = new JPanel();
bottom.add(reset);
reset.addActionListener(this);
add("South", bottom);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
size = 0;
sizeSl.setValue(0);
canvas.repaint();
}
public void stateChanged(ChangeEvent e) {
size = sizeSl.getValue();
canvas.repaint();
}
private class MyCanvas extends Canvas {
#Override
public void paint(Graphics g) {
int x, y;
int n = 0;
for (int i = 0; i < size; i++) {
//n = 1 + i;
for (int j = 0; j < size; j++) {
n++;
x = 20 + 10 * i;
y = 20 + 10 * j;
//g.fillOval(x, y, 10, 10);
g.drawRect(x, y, 10, 10);
if (n % 2 == 0) {
g.fillRect(x, y, 10, 10);
}
}
}
}
}
}
The problem is that you count the number of drawn rectangles with n. This does not work for odd numbers. Easy fix:
for (int i = 0; i < size; i++) {
n = (i % 2);
This resets your counter n for each row alternately to 0 and 1.
If you lay out sequentially the squares of an NxN chess board with N being even, every N squares you'll get two equal ones in a row.
Therefore, if size is even you must adjust your method accordingly:
for (int i = 0; i < size; i++) {
n += size % 2 + 1;
for (int j = 0; j < size; j++) {
n++;
//...
I am writing the implementation of Galton Board in Java by using Java awt, Swing and thread. My Program has three text field to choose number of slots, number of balls, and number of ball drops at the same time, two buttons one for display and one for start the program. I try to make it work like I can choose the amount of balls and click start and the balls auto falling down the chimney. Currently, My program be able to drop one ball and running fine, but I don't know how to implement that be able drop more than one ball. Any suggestions or help are appreciated, Thank you. This is Main.Class
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Random;
import javax.swing.*;
public class Main extends JFrame {
private String num_slots;
private String num_balls;
private String ball_free;
private JButton Display;
private JButton Start;
private JPanel textpanel;
private JPanel mainpanel;
private JPanel graphpanel;
public Main() {
textpanel = new JPanel();
textpanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 20));
textpanel.add(new JLabel("Number of Slots"));
final JTextField text1 = new JTextField(10);
textpanel.add(text1);
textpanel.add(new JLabel("Number of Balls"));
final JTextField text2 = new JTextField(10);
textpanel.add(text2);
textpanel.add(new JLabel("How many balls can be freed"));
final JTextField text3 = new JTextField(10);
textpanel.add(text3);
Display = new JButton("Display");
textpanel.add(Display);
Start = new JButton("Start");
textpanel.add(Start);
// Create panel p2 to hold a text field and p1
mainpanel = new JPanel(new BorderLayout());
mainpanel.add(textpanel, BorderLayout.NORTH);
/*
* graphpanel = new JPanel(); graphpanel.setLayout(new
* BoxLayout(graphpanel, BoxLayout.Y_AXIS));
*/
add(mainpanel, BorderLayout.CENTER);
Display.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Display) {
num_slots = text1.getText();
int slots = Integer.parseInt(num_slots);
num_balls = text2.getText();
int balls = Integer.parseInt(num_balls);
MainPanel pa = new MainPanel(slots, balls);
mainpanel.add(pa);
mainpanel.revalidate();
}
}
});
Start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Start) {
num_slots = text1.getText();
int slots = Integer.parseInt(num_slots);
num_balls = text2.getText();
int balls = Integer.parseInt(num_balls);
MainPanel pa = new MainPanel(slots, balls);
mainpanel.add(pa, BorderLayout.CENTER);
pa.start();
mainpanel.revalidate();
mainpanel.repaint();
}
}
});
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Main frame = new Main();
frame.setTitle("The Galton board");
frame.setSize(1000, 800);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setAutoRequestFocus(true);
}
}
main panel class contains the chimneys and balls
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
class MainPanel extends JPanel implements Runnable {
private int num;
private int number_ball;
public static int start_y = 100;
private float ball_x = 385;
private float ball_y = 50;
private float radius = 15;
private static int panel_x = 300;
private static int panel_y = 100;
private int diameter = 20;
private int last_x = 0;
private final static Random generator = new Random();
ArrayList<Balls> list_ball = new ArrayList<Balls>();
private int m_interval = 100;
private Timer m_timer;
public MainPanel() {
}
public MainPanel(int number) {
num = number;
}
public MainPanel(int number, int ball) {
num = number;
number_ball = ball;
for (int i = 1; i <= number_ball; i++)
{
list_ball.add(new Balls());
}
m_timer = new Timer(m_interval, new TimerAction());
}
public int getPanel_y() {
return panel_y;
}
public void start()
{
m_timer.setInitialDelay(250);
m_timer.start();
}
#Override
protected void paintComponent(Graphics g) {
int start_y = 100;
panel_x = 300;
panel_y = 100;
diameter = 20;
last_x = 0;
super.paintComponent(g);
if (num % 2 == 0) {
for (int i = 1; i <= num; i++) {
if ((i % 2) != 0) {
for (int k = 1; k <= num; k++) {
g.setColor(Color.BLUE);
g.fillOval(panel_x, panel_y, diameter, diameter);
panel_x = panel_x + 40;
}
} else if ((i % 2) == 0) {
for (int k = 1; k <= num + 1; k++) {
g.setColor(Color.BLUE);
g.fillOval(panel_x - 20, panel_y, diameter, diameter);
panel_x = panel_x + 40;
}
}
panel_y = panel_y + 40;
panel_x = 300;
}
} else if (num % 2 != 0) {
for (int i = 1; i <= num; i++) {
if ((i % 2) != 0) {
for (int k = 1; k <= num; k++) {
g.setColor(Color.BLUE);
g.fillOval(panel_x, panel_y, diameter, diameter);
panel_x = panel_x + 40;
}
} else if ((i % 2) == 0) {
for (int k = 1; k <= num + 1; k++) {
g.setColor(Color.BLUE);
g.fillOval(panel_x - 20, panel_y, diameter, diameter);
panel_x = panel_x + 40;
}
}
panel_y = panel_y + 40;
panel_x = 300;
}
}
for (int n = 40; n < panel_y - 40; n = n + 40) {
if (num % 2 == 0) {
g.drawLine(panel_x - 50 + n, panel_y - 10, panel_x - 50 + n,
panel_y + 80);
g.drawLine(panel_x, panel_y + 80, panel_x - 50 + n, panel_y + 80);
last_x = panel_x - 50 + n;
} else if (num % 2 != 0) {
g.drawLine(panel_x - 30 + n, panel_y - 10, panel_x - 30 + n,
panel_y + 80);
g.drawLine(panel_x, panel_y + 80, panel_x - 30 + n, panel_y + 80);
last_x = panel_x - 30 + n;
}
}
for (int i = 0; i< list_ball.size(); i++)
{
list_ball.get(i).draw(g);
}
}
class TimerAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i< list_ball.size(); i++)
{
list_ball.get(i).move();
//return;
//m_timer.stop();
repaint();
}
}
Balls Class
import java.awt.geom.Ellipse2D;
import java.util.Random;
import java.awt.*;
public class Balls {
private Ellipse2D.Double thisBall;
private int Ball_x;
private int Ball_y;
public int radius;
public int start_y;
private final static Random generator = new Random();
Mainpanel pa = new Mainpanel();
public Balls()
{
start_y = 100;
Ball_x = 385;
Ball_y = 50;
radius = 15;
}
public void draw(Graphics g)
{
g.setColor(Color.RED);
g.fillOval(Ball_x, Ball_y, radius, radius);
}
public void move()
{
if (Ball_y < pa.getPanel_y() + 65)
{
int direction = generator.nextInt(2);
Ball_y = Ball_y + 5;
if (Ball_y == start_y - 10 && start_y < pa.getPanel_y())
{
if (direction == 0)
{
Ball_x = Ball_x - 20;
}
else Ball_x = Ball_x + 20;
start_y = start_y + 40;
}
System.out.println(Ball_y);
System.out.println(pa.getPanel_y());
}
// Ball_x = Ball_x + 5;
}
}
Create a new logical class, not a GUI class, for your Ball, one that does not extend a JPanel or any Swing component, but rather one that has the logic behind the Ball as well as perhaps a rendering method that accepts a Graphics or Graphics2D object. Then give your drawing JPanel class an ArrayList of these Ball objects, move them in your game loop -- note that I would prefer using a Swing Timer and not a background thread, and then in your JPanel's paintComponent method iterate through the ArrayList of Balls, drawing each Ball by calling its rendering method.
As an aside: all your class names should begin with an upper case letter, and all identifiers other than constants should use camel case, so your mainpanel class should be named MainPanel. I've edited your code prettify the code formatting and have made this change for you.
Aside number 2: your current code has code logic inside of paintComponent. Don't do that as that will mess you up. You don't have full control over when or even if paintComponent will be called.
I'm trying to draw a grid inside the content pane of my JFrame but when I do, everything is off. The grid starts too wide and offset (presumably set where the border of the window overlaps the contentpane) and it doesn't draw the entire grid correctly. When i use frame.setUndecorated(true); everything works perfectly.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.*;
#SuppressWarnings("serial")
class Creator extends JFrame{
JFrame frame;
int[][] Grid = new int[18][27];
public Creator(){
frame = this;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for(int i = 0; i < 18; i++) {
for(int j = 0; j < 27; j++) {
Grid[i][j] = 0;
}
}
setSize(864, 544);
getContentPane().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int yLocation = e.getX()/32;
int xLocation = e.getY()/32;
System.out.println(xLocation + " " + yLocation);
if(e.getButton() == 1){
if(xLocation < 1 || yLocation < 1){
Grid[xLocation][yLocation] = 2;
System.out.println("Enemy Added");
}else if(xLocation > 16 || yLocation > 25){
Grid[xLocation][yLocation] = 2;
System.out.println("Enemy Added");
}else {
Grid[xLocation][yLocation] = 1;
System.out.println("Obstacle Added");
}
}else {
Grid[xLocation][yLocation] = 0;
System.out.println("Item Removed");
}
frame.invalidate();
frame.validate();
frame.repaint();
}
});
}
public void paint(Graphics g) {
g.clearRect(0, 0, 864, 544);
Graphics2D g2 = (Graphics2D) g;
for(int i =0; i < 18; i++) {
for(int j =0; j < 27; j++) {
if(Grid[i][j] != 0){
if( i < 1 || j < 1 || i > 26 || j > 17) {
g2.setColor(Color.RED);
g2.fillRect(j*32, i*32, 32, 32);
}else {
g2.setColor(Color.BLUE);
g2.fillRect(j*32, i*32, 32, 32);
}
}
//System.out.print(Grid[i][j]);
}
//System.out.println();
}
for(int i = 0; i < 27; i++) {
Line2D lin = new Line2D.Float(i*32, 0, i*32, 544);
g2.draw(lin);
}
for(int i = 0; i < 18; i++) {
Line2D lin = new Line2D.Float(0, i*32, 864, i*32);
g2.draw(lin);
}
}
public static void main(String []args){
Creator s=new Creator();
s.setVisible(true);
}
}
Don't set the size of the frame.
Instead, create a subclass of JPanel or JComponent, override paintComponent() to paint your grid, and override getPreferredSize() to return the size it should have (864 x 544). Add this panel to your frame and call pack() to make sure that the frame size adjusts itself to the size needed to display its component with their preferred size.
EDIT: example:
public class GridPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
// paint the grid here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(864, 544);
}
}
and in the JFrame constructor:
GridPanel gridPanel = new GridPanel();
this.add(gridPanel);
this.pack();
JB Nizet, gives you the excellent solution. Change your code as follows:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.*;
#SuppressWarnings("serial")
class Creator extends JPanel{
static int[][] Grid = new int[18][27];
public Creator(){
setSize(getPreferredSize());
}
public void paint(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
Graphics2D g2 = (Graphics2D) g;
for(int i =0; i < 18; i++) {
for(int j =0; j < 27; j++) {
if(Grid[i][j] != 0){
if( i < 1 || j < 1 || i > 26 || j > 17) {
g2.setColor(Color.RED);
g2.fillRect(j*32, i*32, 32, 32);
}else {
g2.setColor(Color.BLUE);
g2.fillRect(j*32, i*32, 32, 32);
}
}
//System.out.print(Grid[i][j]);
}
//System.out.println();
}
for(int i = 0; i < 27; i++) {
Line2D lin = new Line2D.Float(i*32, 0, i*32, getHeight());
g2.draw(lin);
}
for(int i = 0; i < 18; i++) {
Line2D lin = new Line2D.Float(0, i*32, getWidth(), i*32);
g2.draw(lin);
}
}
public static void main(String []args){
JFrame frame=new JFrame();
Creator s=new Creator();
frame.setSize(864, 544);
frame.add(s);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int yLocation = e.getX()/32;
int xLocation = e.getY()/32;
System.out.println(xLocation + " " + yLocation);
if(e.getButton() == 1){
if(xLocation < 1 || yLocation < 1){
Grid[xLocation][yLocation] = 2;
System.out.println("Enemy Added");
}else if(xLocation > 16 || yLocation > 25){
Grid[xLocation][yLocation] = 2;
System.out.println("Enemy Added");
}else {
Grid[xLocation][yLocation] = 1;
System.out.println("Obstacle Added");
}
}else {
Grid[xLocation][yLocation] = 0;
System.out.println("Item Removed");
}
// frame.invalidate();
// frame.validate();
// frame.repaint();
}
});
// s.setUndecorated(true);
}
}
I am a beginner with Java Programming and I have a problem. I am using a JPanel in a JScrollPane all contained in a JFrame.
I am using paintComponent() method to draw a certain curve and that's done correctly. The problem is that when I scroll through my panel I see that the image is being cleared. I've searched and learned about flickering but I'm not quiet sure yet what it means and whether that's the problem I am having. I did notice also that when repaint is called the image is cleared.
Here is my code, can anyone let me know if I am doing something wrong?
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.QuadCurve2D;
import javax.swing.JFrame;
import java.lang.Math;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class DrawCurve extends JPanel {
class MyAdjustmentListener implements AdjustmentListener {
public MyAdjustmentListener() {
}
public void adjustmentValueChanged(AdjustmentEvent evt) {
setFocusable(true);
jScroll.setFocusable(false);
//repaint();
//revalidate();
}
}
Graphics gr;
Stroke drawingStroke = new BasicStroke(0.5f);
double x;
int y = 0;
static String seq = "AAGTCGACCTGTAGCTAGATCGGATCATAGCTCGATCCAGAGATT";
QuadCurve2D curve;
char s;
int a = 0;
int c = 0;
int g = 0;
int t = 0;
int af = 0;
int cf = 0;
int gf = 0;
int tf = 0;
int h = 0;
int flag = 0;
final JScrollPane jScroll = new JScrollPane();
final JFrame parFrame;
Vector<Double> xrand = new Vector<Double>();
public DrawCurve() {
super();
parFrame = new JFrame();
parFrame.pack();
jScroll.setFocusable(false);
setFocusable(true);
parFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
jScroll.setViewportView(this);
jScroll.getHorizontalScrollBar().addAdjustmentListener(new MyAdjustmentListener());
jScroll.getVerticalScrollBar().addAdjustmentListener(new MyAdjustmentListener());
if (checkSequence(seq) == 0) {
jScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
jScroll.setViewportBorder(new LineBorder(Color.WHITE));
setFocusable(true);
setPreferredSize(new Dimension(1000, 300));
setBackground(Color.magenta);
parFrame.add(jScroll, BorderLayout.CENTER);
parFrame.setSize(600, 320);
parFrame.setVisible(true);
} else {
JOptionPane.showMessageDialog(null, "invalid input", "Warning!", JOptionPane.PLAIN_MESSAGE);
}
}
public int checkSequence(String sequ) {
int f = 0;
for (int i = 0; i < sequ.length(); i++) {
if (sequ.charAt(i) != "A".charAt(0) && sequ.charAt(i) != "C".charAt(0) && sequ.charAt(i) != "G".charAt(0) && sequ.charAt(i) != "T".charAt(0)) {
f = 1;
break;
}
xrand.add(Math.random() * 300 - 200);
}
return f;
}
public void paintComponent(Graphics gr) {
super.paintComponent(gr);
Graphics2D ga = (Graphics2D) gr;
System.out.println("in");
ga.setStroke(drawingStroke);
for (int i = 0; i < seq.length(); i++) {
s = seq.charAt(i);
if (s == "A".charAt(0)) {
ga.setColor(Color.RED);
a = 1;
af = 1;
cf = 0;
gf = 0;
tf = 0;
h = -1;
} else if (s == "C".charAt(0)) {
ga.setColor(Color.YELLOW);
c = 1;
af = 0;
cf = 1;
gf = 0;
tf = 0;
h = -3;
} else if (s == "G".charAt(0)) {
ga.setColor(Color.GREEN);
g = 1;
af = 0;
cf = 0;
gf = 1;
tf = 0;
h = 1;
} else if (s == "T".charAt(0)) {
ga.setColor(Color.BLUE);
t = 1;
af = 0;
cf = 0;
gf = 0;
tf = 1;
h = 3;
} else {
af = 0;
cf = 0;
gf = 0;
tf = 0;
h = 0;
}
x = Math.random() * 300 - 200;
curve = new QuadCurve2D.Double(y, 250 + h, y + 10, xrand.elementAt(i), y + 20, 250 + h);
ga.draw(curve);
if (a == 1 && af == 0) {
ga.setColor(Color.RED);
h = -1;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
if (c == 1 && cf == 0) {
ga.setColor(Color.YELLOW);
h = -3;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
if (g == 1 && gf == 0) {
ga.setColor(Color.GREEN);
h = 1;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
if (t == 1 && tf == 0) {
ga.setColor(Color.BLUE);
h = 3;
ga.drawLine(y, 250 + h, y + 20, 250 + h);
}
y += 20;
}
}
public static void main(String[] args) {
final DrawCurve panel = new DrawCurve();
}
}
I figured out what's wrong with that code, it turned out that in my loop I forgot to initialize where the curve should start every time the paintComponent is called. Adding y=0; at the start of paintComponent would solve it