I'm trying to create a GUI that allows the user to input a number, then the GUI creates an array of Points of that size, then draws that number of circles. However, when I run this code, the GUI only displays a black panel and using a system.out.println it says that the number in the JTextField never reaches the panel. How can I alter my code so that the user can input a number in the textfield, press enter, then the GUI draws that number of circles?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
class ControlPanel extends JPanel{
JLabel inLabel;
JTextField inText;
public ControlPanel(){
setBackground(Color.lightGray);
inLabel = new JLabel("Enter the number of points: ");
inText = new JTextField(20);
add(inLabel);
add(inText);
}
public JTextField getInText(){
return inText;
}
public int getNPoints(){
int nP = Integer.parseInt(inText.getText());
return nP;
}
}
class PiPanel2 extends JPanel{
private Point[] points;
int nPoints;
Dimension d = new Dimension();
private int X = d.width;
private int Y = d.height;
private int w = 5;
private int h = 5;
public PiPanel2(){
setBackground(Color.BLACK);
}
public void setNPoints(int nPoints){
this.nPoints = nPoints;
}
public int getNP(){
return nPoints;
}
public void paintComponent(Graphics g){
int n = getNP();
points = new Point[n];
System.out.println(n);
for(int i = 0; i < n; i++){
points[i] = new Point(Math.random(), Math.random());
}
g.setColor(getBackground());
super.paintComponent(g);
g.setColor(Color.red);
g.drawOval(-X, -Y, X*2, Y*2);
for(int i = 0; i < points.length; i++){
int x = (int)(points[i].getX()*X);
int y = (int)(points[i].getY()*Y);
if(points[i].withinR()){
g.setColor(Color.blue);
g.fillOval(x, y, w, h);
}else if(!points[i].withinR()){
g.setColor(Color.orange);
g.fillOval(x, y, w, h);
}
}
}
}
class PiFrame2 extends JFrame implements ActionListener{
private int X = 600;
private int Y = 600;
ControlPanel control;
PiPanel2 piPan;
public PiFrame2(){
control = new ControlPanel();
piPan = new PiPanel2();
control.getInText().addActionListener(this);
setLayout(new BorderLayout());
// and add the panels to the frame
getContentPane().add(control, BorderLayout.SOUTH);
getContentPane().add(piPan, BorderLayout.CENTER);
// this code enables you to close the window
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(X,Y);
setLocation(500,0);
}
public void actionPerformed(ActionEvent e) {
int nPoints = control.getNPoints();
piPan.setNPoints(nPoints);
}
}
Related
In this exercise, when you enter the name of a city and its population, in the window it must be graphed a bar that represents the population of that city as shown in the figures, the exercise is almost complete but it doesn't work, could someone tell me what I'm doing wrong?, Why is no bar drawn?, the condition that makes the exercise a bit more difficult to me is that the size of the bars and lines must change if the window size changes. The main class can't be modified because is already given.
package Hw02_Statistics;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import hw01_clocknumbers.DigitalNumber;
public class Statistics extends JFrame {
private JLabel city, population, other;
private JTextField tcity, tpopulation;
private JButton add;
private JTable table;
private DefaultTableModel tablem;
private int index=1;
private bar bars;
public Statistics() {
setTitle("Statistics");
setSize(500, 350);
setupWidgets();
seupEvents();
setVisible(true);
}
private void setupWidgets() {
bars = new bar();
city = new JLabel("City",JLabel.LEFT);
population = new JLabel("Population",JLabel.LEFT);
tcity = new JTextField();
other = new JLabel();
tpopulation = new JTextField();
add = new JButton("Add");
tablem = new DefaultTableModel(new Object[] {"Index", "City", "Population"}, 0);
table = new JTable(tablem);
JPanel norte = new JPanel(new GridLayout(5,1));
JPanel sur = new JPanel(new GridLayout(1,2));
add(norte, BorderLayout.NORTH);
add(sur, BorderLayout.CENTER);
norte.add(city);
norte.add(tcity);
norte.add(population);
norte.add(tpopulation);
norte.add(add);
sur.add(new JScrollPane(table));
sur.add(bars);
}
private void seupEvents() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!tcity.getText().equals("") && !tpopulation.getText().equals("")) {
Object rowinfo[] = {index, tcity.getText(), tpopulation.getText()};
tablem.addRow(rowinfo);
int n= Integer.parseInt(tpopulation.getText());
bars.setScale(1, index);
tcity.setText("");
tpopulation.setText("");
index++;
}
}
});
}
public static void main(String[] args) {
new Statistics();
}
}
This is the second class I used
package Hw02_Statistics;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JComponent;
import hw01_clocknumbers.DigitalNumber;
public class bar extends JComponent {
private int digit;
private Integer scale=0;
private int index;
private rect rects[];
public bar () {
}
public void paint(Graphics g) {
int w =getWidth();
int h =getHeight();
rects = new rect[4];
rects[index] = new rect(scale, index, w, h);
// System.out.println(w); 243
// System.out.println(h); 183
g.drawLine(w/12, h/9, w/12, 8*h/9);
g.drawLine(w/12, 8*h/9, 12*w/12, 8*h/9);
}
public void setScale(Integer scale, int index) {
this.index=index-1;
this.scale=scale;
repaint();
}
}
And this is the last Class I used, and it is the one that doesn't work
package Hw02_Statistics;
import java.awt.Graphics;
import javax.swing.JComponent;
public class rect extends JComponent{
private int scale;
private int index;
private int w, h;
public rect(int scale, int index, int w, int h) {
this.scale = scale;
this.index= index;
this.w =w;
this.h=h;
}
public void paint(Graphics e) {
e.fillRect(6*w/12+w*index/12,h/9,scale*w/12,scale*7*h/9);
System.out.println("Aaaa");
repaint();
}
}
class bar (which should be called Bar according to java naming conventions) was renamed to Bars and changed to hold and draw all bars:
class Bars extends JComponent {
//collection of bar heights
private final List<Integer> barsValues;
private static final int W = 20; //bar width
public Bars () {
barsValues = new ArrayList<>();
}
//override paintComponent rather than paint
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); //always call super
int w = getWidth();
int h = getHeight();
//use double to avoid rounding errors
double minX = w/12 , maxX = 12*minX, maxY = h/9, minY = 8 * maxY;
double graphHeight = minY - maxY;
//draw axis
g.drawLine((int)minX, (int)maxY, (int)minX, (int)minY);
g.drawLine((int)minX, (int)minY, (int)maxX, (int)minY);
//draw bars
if(barsValues.size() == 0) return;
double x = minX + W ;
int maxHeight = getMaxHeight(); //calculate scale based on max height
double scale = maxHeight > 0 ? graphHeight / getMaxHeight() : 1;
for(int barValue : barsValues){
double barHeight = scale*barValue;
g.fillRect((int)x ,(int)(minY - barHeight), W, (int)barHeight);
x += 2*W;
}
}
//add bar values. valid values should be > 0
void addBar(int height) {
barsValues.add(height);
repaint();
}
//get max height
int getMaxHeight(){
int max = 0;
for (int value : barsValues){
if(value > max) {
max = value;
}
}
return max;
}
}
class rect is not needed.
To test you need to do some minor changes in Statistics:
change private bar bars; to private Bars bars;
Initialize it by bars = new Bars();
and change one line in the action listener from bars.setScale(1, index) to bars.addBar(n);
The complete code can be copy-pasted from here
So basically I'm trying to create a reversi game. First of all I created a board populated by buttons and attached ID's to them, so I can access them afterwards if needed. Now I am trying to draw a game piece on each of the buttons, however I can't getGraphics() of the button since I read that is a bad idea and also returns null. Keep in mind that I want to keep all of my entities separate: the board, the cell and the piece, since I developing this using MVC pattern.
board.java
import java.awt.GridLayout;
import javax.swing.JPanel;
public class Board extends JPanel {
private static final int sizeOfBoard = 8;
public Board() {
int id =0;
setLayout(new GridLayout(sizeOfBoard,sizeOfBoard));
for (int i = 0; i < sizeOfBoard; i++) {
for (int j = 0; j < sizeOfBoard; j++) {
Cell cell = new Cell(id++);
Disk disk = new Disk();
cell.add(disk);
add(cell);
}
}
setSize(600,500);
setVisible(true);
}
cell.java
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.Painter;
public class Cell extends JButton{
private int id;
private boolean taken;
private String colour;
private Painter painter;
public Cell(int id){
this.id = id;
}
public int getId(){
return id;
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
}
}
disk.java
import java.awt.Graphics;
import javax.swing.JComponent;
public class Disk extends JComponent{
#Override
public void paintComponent ( Graphics g ) {
super.paintComponent(g);
g.drawOval(50,50,50,50);
}
}
TL;DR How should I rewrite my code so it would have an oval on each button.
Thanks in advance.
The simplest solution: create your oval or disk images in a BufferedImage, put it into an ImageIcon, and simply swap Icons on your JButton or JLabel via its setIcon(myIcon) method. I'd create 3 ImageIcons if this were my GUI, a blank one for the initial state, and then two different colored ones for the occupied states.
For example:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class ReversiPanel extends JPanel {
private static final int SIDES = 8;
private static final int ICON_LENGTH = 60;
private static final Color BG = Color.BLACK;
private static final Color LABEL_COLOR = Color.GREEN.darker();
private JLabel[][] labelGrid = new JLabel[SIDES][SIDES];
private Icon blankIcon;
private Icon blackIcon;
private Icon whiteIcon;
public ReversiPanel() {
blankIcon = createIcon(new Color(0, 0, 0, 0));
blackIcon = createIcon(Color.BLACK);
whiteIcon = createIcon(Color.WHITE);
setBackground(BG);
setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
setLayout(new GridLayout(SIDES, SIDES, 1, 1));
MyMouse myMouse = new MyMouse();
for (int i = 0; i < labelGrid.length; i++) {
for (int j = 0; j < labelGrid[i].length; j++) {
JLabel label = new JLabel(blankIcon);
label.setOpaque(true);
label.setBackground(LABEL_COLOR);
label.addMouseListener(myMouse);
labelGrid[i][j] = label;
add(label);
}
}
}
private Icon createIcon(Color color) {
BufferedImage img = new BufferedImage(ICON_LENGTH, ICON_LENGTH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color);
int gap = 4;
int w = ICON_LENGTH - 2 * gap;
int h = w;
g2.fillOval(gap, gap, w, h);
g2.dispose();
return new ImageIcon(img);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel) e.getSource();
Icon icon = label.getIcon();
if (icon == blankIcon) {
label.setIcon(blackIcon);
} else if (icon == blackIcon) {
label.setIcon(whiteIcon);
} else {
label.setIcon(blankIcon);
}
}
}
private static void createAndShowGui() {
ReversiPanel mainPanel = new ReversiPanel();
JFrame frame = new JFrame("ReversiPanel");
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());
}
}
newbie programmer here.
I'm making a program that renders user-inputted equations in a Cartesian coordinate system. At the moment I'm having some issues with letting the user move the view around freely in the coordinate. Currently with mouseDragged the user can drag the view around a bit, but once the user releases the mouse and tries to move the view again the origin snaps back to the current position of the mouse cursor. What is the best way to let the user move around freely? Thanks in advance!
Here's the code for the drawing area.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JPanel;
public class DrawingArea extends JPanel implements MouseMotionListener {
private final int x_panel = 350; // width of the panel
private final int y_panel = 400; // height of the panel
private int div_x; // width of one square
private int div_y; // height of one square
private int real_y;
private int real_x;
private Point origin; // the origin of the coordinate
private Point temp; // temporary point
private static int y = 0;
private static int x = 0;
DrawingArea() {
setBackground(Color.WHITE);
real_x = x_panel;
real_y = y_panel;
setDivisionDefault();
setOrigin(new Point((real_x / 2), (real_y / 2)));
setSize(x_panel, y_panel);
addMouseMotionListener(this);
}
DrawingArea(Point origin, Point destination) {
this.origin = origin;
this.destination = destination;
panel = new JPanel();
panel.setSize(destination.x, destination.y);
panel.setLocation(origin);
this.panel.setBackground(Color.red);
panel.setLayout(null);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D line = (Graphics2D) g;
temp = new Point(origin.x, origin.y);
line.setColor(Color.red);
drawHelpLines(line);
line.setColor(Color.blue);
drawOrigin(line);
line.setColor(Color.green);
for (int i = 0; i < 100; i++) { // This is a test line
//temp = this.suora();
temp.x++;
temp.y++;
line.drawLine(temp.x, temp.y, temp.x, temp.y);
}
}
public void setOrigin(Point p) {
origin = p;
}
public void drawOrigin(Graphics2D line) {
line.drawLine(origin.x, 0, origin.x, y_panel);
line.drawLine(0, origin.y, x_panel, origin.y);
}
public void drawHelpLines(Graphics2D line) {
int xhelp= origin.x;
int yhelp= origin.y;
for (int i = 0; i < 20; i++) {
xhelp+= div_x;
line.drawLine(xhelp, 0, xhelp, y_panel);
}
xhelp= origin.x;
for (int i = 0; i < 20; i++) {
xhelp-= div_x;
line.drawLine(xhelp, 0, xhelp, y_panel);
}
for (int i = 0; i < 20; i++) {
yhelp-= div_y;
line.drawLine(0, yhelp,x_panel, yhelp);
}
yhelp= origin.y;
for (int i = 0; i < 20; i++) {
yhelp+= div_y;
line.drawLine(0, yhelp, x_panel, yhelp);
}
}
public void setDivisionDefault() {
div_x = 20;
div_y = 20;
}
#Override
public void mouseDragged(MouseEvent e) {
//Point temp_point = new Point(mouse_x,mouse_y);
Point coords = new Point(e.getX(), e.getY());
setOrigin(coords);
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
Based on this example, the following program allows the user to drag the axes' intersection to an arbitrary point, origin, which starts at the center of the panel.
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/15576413/230513
* #see https://stackoverflow.com/a/5312702/230513
*/
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final int W = 640;
private static final int H = 480;
private Point origin = new Point(W / 2, H / 2);
private Point mousePt;
public MouseDragTest() {
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
origin.setLocation(origin.x + dx, origin.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, origin.y, getWidth(), origin.y);
g.drawLine(origin.x, 0, origin.x, getHeight());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
In a Java applet, I'm trying to slow down the painting of an image made up of parts, so I wrote a test program to get the basic concept working. I'm using a thread to draw a number of boxes one at a time instead of a timer because I want to be able to click the go button to reset the drawing process at any time.
The problem is, after drawing a box, it moves down a bit and an extra of the label shows up at the top of the screen. When the mouse moves off the button at the bottom, a dummy button also shows up at the top of the screen. The dummy button doesn't respond to clicks (only the real one at the bottom does), it's just there.
I'm still pretty new at this, so any help would be greatly appreciated.
Here's the JApplet class:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TestDraw extends JApplet implements ActionListener
{
private DrawPanel panel;
private JLabel lbl1;
JButton go;
Thread t;
public void init()
{
lbl1 = new JLabel("hi");
go = new JButton("GO");
go.addActionListener(this);
panel = new DrawPanel();
getContentPane().setBackground(Color.yellow);
add(lbl1, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
add(go, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent ae){
// tried adding these. didnt help
//panel.validate();
//panel.repaint();
//validate();
panel.resetBoxes();
repaint();
}
public void start(){
t = new Thread(panel);
t.start();
}
}
Here's the DrawPanel Class:
import java.awt.*;
import java.security.SecureRandom;
import javax.swing.*;
public class DrawPanel extends JPanel implements Runnable
{
private SecureRandom randGen = new SecureRandom();
private Box[] boxes;
private int box2draw = 0;
public DrawPanel()
{
setBackground(Color.WHITE);
boxes = new Box[5];
for (int count = 0; count < boxes.length; count++){
int x = randGen.nextInt(300);
int y = randGen.nextInt(300);
int w = randGen.nextInt(300);
int h = randGen.nextInt(300);
Color color = new Color(randGen.nextInt(256), randGen.nextInt(256), randGen.nextInt(256));
boxes[count] = new Box(x,y,w,h,color);
}
}
public void paintComponent(Graphics g)
{
boxes[box2draw].draw(g);
box2draw++;
}
public void resetBoxes(){
boxes = new Box[5];
for (int count = 0; count < boxes.length; count++){
int x = randGen.nextInt(300);
int y = randGen.nextInt(300);
int w = randGen.nextInt(300);
int h = randGen.nextInt(300);
Color color = new Color(randGen.nextInt(256), randGen.nextInt(256), randGen.nextInt(256));
boxes[count] = new Box(x,y,w,h,color);
box2draw = 0;
}
}
public void run(){
while(true){
try{
Thread.sleep(750);
}
catch(InterruptedException e){
JOptionPane.showMessageDialog(null, "interrupted");
}
repaint();
}
}
}
And finally, the Box class:
import java.awt.Color;
import java.awt.Graphics;
public class Box
{
private int x;
private int y;
private int w;
private int h;
private Color color;
public Box(int x,int y,int w,int h,Color color)
{
// initialise instance variables
this.x = x;
this.y=y;
this.w=w;
this.h = h;
this.color=color;
}
public void draw(Graphics g)
{
g.setColor(color);
g.drawRect( x, y, w, h);
}
}
Thank you for your time!
Problems:
You've got code logic within a painting method -- something that you should never do -- including your incrementing an array index. You don't have full control of when or even if this method is called and so program logic does not belong there, just painting. If you need to increment your array index, do it elsewhere, perhaps within your thread's while (true) loop. Also take care not to have the index go beyond the size of the array.
You never call the super's paintComponent method within your override, and this will prevent the component from doing housekeeping painting, probably your main problem.
If you need to display multiple items, then consider either drawing to a BufferedImage and displaying that within paintComponent, or creating a collection of Shape objects and drawing all of them within paintComponent via a for-loop.
I prefer to use the Swing-safer Swing Timer. While it doesn't matter if only calling repaint() if you want to make any other Swing calls intermittently, it makes life much easier and coding safer.
For example
package foo1;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TestDraw2 {
#SuppressWarnings("serial")
private static void createAndShowGui() {
final DrawPanel2 drawPanel = new DrawPanel2();
JButton drawButton = new JButton(new AbstractAction("Draw!") {
#Override
public void actionPerformed(ActionEvent e) {
drawPanel.resetBoxes();
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(drawButton);
JFrame frame = new JFrame("TestDraw2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(drawPanel);
frame.getContentPane().add(btnPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class DrawPanel2 extends JPanel {
private static final int BOX_COUNT = 5;
private static final int TIMER_DELAY = 750;
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private Random randGen = new Random();
private Box[] boxes;
private int box2draw = 0;
public DrawPanel2() {
setBackground(Color.YELLOW);
boxes = new Box[BOX_COUNT];
for (int count = 0; count < boxes.length; count++) {
int x = randGen.nextInt(300);
int y = randGen.nextInt(300);
int w = randGen.nextInt(300);
int h = randGen.nextInt(300);
Color color = new Color(randGen.nextInt(256), randGen.nextInt(256),
randGen.nextInt(256));
boxes[count] = new Box(x, y, w, h, color);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < box2draw; i++) {
boxes[i].draw(g);
}
}
public void resetBoxes() {
boxes = new Box[BOX_COUNT];
for (int count = 0; count < boxes.length; count++) {
int x = randGen.nextInt(300);
int y = randGen.nextInt(300);
int w = randGen.nextInt(300);
int h = randGen.nextInt(300);
Color color = new Color(randGen.nextInt(256), randGen.nextInt(256),
randGen.nextInt(256));
boxes[count] = new Box(x, y, w, h, color);
box2draw = 0;
}
repaint();
new Timer(TIMER_DELAY, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
box2draw++;
if (box2draw > BOX_COUNT) {
box2draw = BOX_COUNT;
((Timer) e.getSource()).stop();
}
repaint();
}
}).start();
}
}
I have tried reading similar questions on stack overflow, but I am not able to get a concrete solution. So, I am posting it back. I am calling repaint on the click of a button. As in paint function, I draw the objects randomly. I suppose they should move, when I click the button. But, nothing happens when I click the button.
Does anybody knows why such a behavior is happening and how to solve this?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
#SuppressWarnings("serial")
public class Filter extends JFrame
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Filter mainFrame = new Filter();
mainFrame.setVisible(true);
}
});
}
public Filter()
{
//Creating the JFrame main window
setSize(800, 500);
setTitle("Particle Filter");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocation(100, 100);
getContentPane().setLayout(new BoxLayout(this.getContentPane(), BoxLayout.X_AXIS));
//creates two panels content and sidebar. Sidebar has null layout
JPanel content = new JPanel();
content.setPreferredSize(new Dimension(700,500));
content.setBackground(Color.LIGHT_GRAY);
this.getContentPane().add(content);
JPanel sidebar = new JPanel();
sidebar.setBackground(Color.LIGHT_GRAY);
sidebar.setPreferredSize(new Dimension(100,500));
this.getContentPane().add(sidebar);
sidebar.setLayout(null);
//creates three buttons in sidebar
JButton start_button = new JButton("START");
start_button.setBounds(10, 75, 77, 23);
start_button.addActionListener(new MainPanel());
sidebar.add(start_button);
JButton stop_button = new JButton("STOP");
stop_button.setBounds(10, 109, 77, 23);
sidebar.add(stop_button);
JButton reset_button = new JButton("RESET");
reset_button.setBounds(10, 381, 77, 23);
sidebar.add(reset_button);
//calls the content_Walls class and sends the number of ovals to be generated
content.add( new MainPanel());
}
}
#SuppressWarnings("serial")
class MainPanel extends JPanel implements ActionListener
{
public MainPanel()
{
setPreferredSize(new Dimension(680,450));
setBackground(Color.WHITE);
setBorder(BorderFactory.createLineBorder(Color.black));
}
public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("start_button"))
repaint();
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
drawParticles(g);
createObstacles(g,150,225,100,40);
createObstacles(g,500,300,40,100);
createRobot(g);
}
private void createRobot(Graphics g)
{
int x=0, y=0;
int robot_radius=50;
ArrayList<Integer> robot_list= new ArrayList<Integer>();
robot_list=positionRobot(x,y);
drawRobot(g,robot_list.get(0),robot_list.get(1),robot_radius);
}
private void drawParticles(Graphics g)
{
int n=1000; // n denotes the number of particles
ArrayList<Integer> list;
list = new ArrayList<Integer>(Collections.nCopies(n, 0));
for(int i=0;i<list.size();i++)
{
generateParticles(g);
}
}
private void generateParticles(Graphics g)
{
int x=0;
int y=0;
int radius = 4;
ArrayList<Integer> list= new ArrayList<Integer>();
list=positionParticles(x,y);
g.setColor(Color.RED);
g.fillOval(list.get(0),list.get(1), radius, radius);
}
private ArrayList<Integer> positionParticles(int x, int y)
{
int radius = 4;
ArrayList<Integer> list= new ArrayList<Integer>();
x=randomInteger(2,678); // bounds of x between which the particles should be generated
y=randomInteger(2,448); // bounds of y between which the particles should be generated
x=x-(radius/2);
y=y-(radius/2);
if((x<251&&x>=150)&&(y<266&&y>=225))
{
x=0;
y=0;
positionParticles(x,y);
}
if((x<541&&x>499)&&(y<401&&y>299))
{
x=0;
y=0;
positionParticles(x,y);
}
list.add(x);
list.add(y);
return list;
}
private ArrayList<Integer> positionRobot(int x, int y)
{
int robot_radius=50;
ArrayList<Integer> list= new ArrayList<Integer>();
x=randomInteger(25,655);//so that it stays inside the content_Walls panel
y=randomInteger(25,425); //so that it stays inside the content_Walls panel
x=x-(robot_radius/2);
y=y-(robot_radius/2);
if((x<250&&x>=150)||(y<=265&&y>=225))
{
x=0;
y=0;
positionRobot(x,y);
}
if((x<=540&&x>=500)||(y<=400&&y>=300))
{
x=0;
y=0;
positionRobot(x,y);
}
list.add(x);
list.add(y);
return list;
}
private void createObstacles(Graphics g, int x, int y, int width, int height)
{
g.setColor(Color.BLACK);
g.fillRect(x, y, width, height);
}
private void drawRobot(Graphics g, int x, int y, int radius)
{
g.setColor(Color.GREEN);
g.fillOval(x, y, radius, radius);
}
private static int randomInteger(int min, int max)
{
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}
e.getActionCommand() return "START" so you have to change:
if (e.getActionCommand().equals("start_button"))
TO
if (e.getActionCommand().equals("START"))
Your second problem is, that you work with two different Mainpanel. Create an instance of Mainpanel and use this in start_button.addActionListener(mainPanel) and content.add(mainPanel);