JLabel Update from another class - java

I am currently having an issue incrementing a points counter in combination with a MouseListener event. Here is my current Progress so far (with some irrelevant code removed)
import java.awt.*;
import javax.swing.*;
import java.awt.Color.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.Random;
public class Checkers extends JFrame
{
Random random = new Random();
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private int x;
public static int score;
private JPanel pane = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
public JLabel lbl1 = new JLabel ("score: " + score);
private MyPanel [] panel = new MyPanel[NUM];
private Color col1 = Color.RED;
private Color col2 = Color.WHITE;
private Color tempColor;
public Checkers()
{
super("Checkers");
setSize(600,600);
setVisible(true);
setBackground(Color.BLACK);
setBoard();
}
//pane background colour and the size of this pane.
pane.setBackground(Color.BLACK);
pane.setPreferredSize(new Dimension(300,300));
//pane background colour and size of this pane.
pane2.setBackground(Color.white);
pane2.setPreferredSize(new Dimension(300,300));
//directions on the board where these panes appear.
add(pane, BorderLayout.WEST);
add(pane2, BorderLayout.EAST);
pane2.add(lbl1);
pane2.setLayout(new BoxLayout(pane2, BoxLayout.PAGE_AXIS));
And the MyPanel class
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
public class MyPanel extends JPanel implements MouseListener {
public MyPanel() {
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
setBackground(Color.BLACK);
Checkers.score++;
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
Expected Result - Once one of the smaller panels within the first pane are clicked, the score counter in pane2 is increased by 1, and this keeps going until they have all been clicked and score can't further be increased.
Current Result - The score does increment, but not in the way it should, instead, the points carry over to the next instance of the GUI (eg, if 3 panels are clicked in the first instance, the points will still stay 0 in this first instance, but once a new GUI is created, the points counter will be 3) which is not what i'm after.
Any help/guidance welcome.

Related

How to make all images in Grid Overlay flush?

I am trying to implement a GUI for a maze-based game I created that meets the following specific conditions:
The GUI itself has a set size and is not resizable (line 41) .
The master panel (line 57) that contains all the maze images is scrollable. All maze image components are flush with each other.
If maze is small enough, then entire maze will be visible in master panel.
If maze is very large, then user would need to scroll.
The master panel needs to be accessed by a mouse listener (line 130) that returns the component that is being clicked.
The following code seems to meet criteria 1 and 3, but fails criteria 2:
public class MazeGui extends JFrame implements DungeonView {
private final Board board;
public MazeGui(ReadOnlyModel m) {
//this.setSize(m.getNumRows()*100, m.getNumCols()*100);
this.setSize(600, 600);
this.setLocation(200, 200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.board = new Board(m);
JScrollPane scroller = new JScrollPane(board);
this.add(scroller, BorderLayout.CENTER);
setTitle("Dungeon Escape");
}
private class Board extends JPanel {
private ReadOnlyModel m;
public Board(ReadOnlyModel m) {
this.m = m;
GridLayout layout = new GridLayout(m.getNumRows(),m.getNumCols(), 0, 0);
// layout.setHgap(-100);
// layout.setVgap(-100);
this.setLayout(layout);
this.setSize(m.getNumRows()*64,m.getNumCols()*64);
for (int i = 0; i < m.getNumRows() * m.getNumCols(); i++) {
try {
// load resource from the classpath instead of a specific file location
InputStream imageStream = getClass().getResourceAsStream(String.format("/images/%s.png", m.getRoomDirections(i + 1)));
// convert the input stream into an image
Image image = ImageIO.read(imageStream);
// add the image to a label
JLabel label = new JLabel(new ImageIcon(image));
label.setPreferredSize(new Dimension(64, 64));
JPanel panel = new JPanel();
panel.setSize(64, 64);
String name = String.format("%d", i);
panel.setName(name);
panel.add(label);
// add the label to the JFrame
//this.layout.addLayoutComponent(TOOL_TIP_TEXT_KEY, label);
this.add(panel);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
e.printStackTrace();
}
}
}
}
#Override
public void addClickListener(DungeonController listener) {
Board board = this.board;
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(String.format("(%d,%d)", e.getX(), e.getY()));
JPanel panel = (JPanel) board.getComponentAt(e.getPoint());
System.out.println(panel.getName());
}
};
board.addMouseListener(mouseListener);
}
#Override
public void refresh() {
this.repaint();
}
#Override
public void makeVisible() {
this.setVisible(true);
}
}
Here is an image of what it produces:
First, I'd make use of a different layout manager, one which would try and expand to fit the size of the underlying container.
Then, I would let the components do their jobs. I don't know why you're adding the label to another panel, the panel doesn't seem to be adding additional functionality/features and is just adding to the complexity.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
List<Maze.Direction> directions = new ArrayList<>(32);
directions.add(Maze.Direction.EAST_SOUTH);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.EAST_SOUTH_WEST);
directions.add(Maze.Direction.SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_SOUTH_WEST);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH_SOUTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
directions.add(Maze.Direction.NORTH);
System.out.println(directions.size());
Maze maze = new DefaultMaze(5, 6, directions);
MazeGui frame = new MazeGui(maze);
frame.addClickListener(null);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Maze {
enum Direction {
EAST_SOUTH("EastSouth.png"), EAST_SOUTH_WEST("EastSouthWest.png"), SOUTH_WEST("SouthWest.png"),
NORTH_EAST_SOUTH("NorthEastSouth.png"), NORTH_EAST_SOUTH_WEST("NorthEastSouthWest.png"),
NORTH_SOUTH_WEST("NorthSouthWest.png"), NORTH_SOUTH("NorthSouth.png"), NORTH("North.png");
private BufferedImage image;
private Direction(String name) {
try {
image = ImageIO.read(getClass().getResource("/images/" + name));
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
public BufferedImage getImage() {
return image;
}
}
public int getRows();
public int getColumns();
public Direction getRoomDirections(int index);
}
public class DefaultMaze implements Maze {
int rows;
int columns;
private List<Direction> directions;
public DefaultMaze(int rows, int columns, List<Direction> directions) {
this.rows = rows;
this.columns = columns;
this.directions = directions;
}
public int getRows() {
return rows;
}
public int getColumns() {
return columns;
}
#Override
public Direction getRoomDirections(int index) {
return directions.get(index);
}
}
public class MazeGui extends JFrame {
// Missing code
public interface DungeonController {
}
private final Board board;
public MazeGui(Maze m) {
this.setSize(600, 600);
this.setResizable(false);
this.board = new Board(m);
JScrollPane scroller = new JScrollPane(board);
this.add(scroller, BorderLayout.CENTER);
setTitle("Dungeon Escape");
}
public Board getBoard() {
return board;
}
public void addClickListener(DungeonController listener) {
Board board = getBoard();
board.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Component cell = board.getComponentAt(e.getPoint());
System.out.println(cell.getName());
board.highlight(cell.getBounds());
}
});
}
private class Board extends JPanel {
private Rectangle selectedCell;
private Maze maze;
public Board(Maze maze) {
this.maze = maze;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
for (int index = 0; index < maze.getRows() * maze.getColumns(); index++) {
Maze.Direction direction = maze.getRoomDirections(index);
JLabel label = new JLabel(new ImageIcon(direction.getImage()));
label.setName(direction.name());
add(label, gbc);
gbc.gridx++;
if (gbc.gridx >= maze.getColumns()) {
gbc.gridx = 0;
gbc.gridy++;
}
}
// addMouseListener(new MouseAdapter() {
// #Override
// public void mouseClicked(MouseEvent e) {
// Component component = getComponentAt(e.getPoint());
// selectedCell = null;
// if (component != null) {
// selectedCell = component.getBounds();
// }
// repaint();
// }
// });
}
public void highlight(Rectangle bounds) {
selectedCell = bounds;
repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (selectedCell != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(0, 0, 255, 128));
g2d.fill(selectedCell);
g2d.dispose();
}
}
}
}
}
The GUI itself has a set size and is not resizable
So the issue here is that you are forcing the "board" panel to have an arbitrary size.
this.setSize(600, 600);
The actual size of the panel should be 8 * 64 = 512. So extra space is being added to each grid.
Don't hardcode size values.
It is the job of the layout manager to determine the preferred size of each component.
So instead of using setSize(...) you should pack() the frame before making it visible:
this.pack();
this.setVisible(true);
When you do this you will see that the maze fits completely in the frame.
If you want extra space around the maze then you need to add a "border" to your board:
setBorder( new EmptyBorder(88, 88, 88, 88) );
GridLayout layout = new GridLayout(m.getNumRows(),m.getNumCols(), 0, 0);
Turns out I should have been using GridBagLayout!
There is no need to change layout managers, only use the layout managers more effectively.
If you really for some reason need to specify a fixed frame size then you can make the following change:
//this.add(scroller, BorderLayout.CENTER);
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(scroller, new GridBagConstraints());
this.add(wrapper, BorderLayout.CENTER);
This will allow the "board" panel to be displayed at its preferred size and the "board" panel will be centered in its parent container.
Using these tips will help you effectively create more complicated layouts.

Using a thread to repaint() components

It doesn't appear that my thread ever starts. Either that or the run method isn't actually doing anything, for which reason I could not explain.
I have a listener on my button StartRace and it should start the thread which will increment the length of each rectangle until one of them is long enough to be declared winner (by surpassing the width of the window, 250px).
I get all of the components initially painted to the screen, but they're never repainted. Is there something wrong with the way I call the method? Do I have classes nested within others that shouldn't be?
//--------------------------------------------------------------
// Start a race between blue and red, track the winner
// Use threads to manage each rectangle's movement
// Allow for user interaction, like stopping and starting
//--------------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class ConcurrencyRace extends JFrame
{
private ConcurrencyPanel panel = new ConcurrencyPanel();
private JButton startRace = new JButton("Start The Race!");
private JButton stopRace = new JButton("Stop The Race!");
private JLabel winnerText = new JLabel("Winner: ");
private int blueDraw = 5, redDraw = 5;
private Random rn = new Random();
//-----------------------------------------------------------------
// Creates and displays the main program frame.
//-----------------------------------------------------------------
public ConcurrencyRace() {
super("Concurrency");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Container cp = getContentPane();
cp.add(panel, BorderLayout.CENTER);
JPanel p = new JPanel();
p.add(startRace);
p.add(stopRace);
cp.add(p, BorderLayout.NORTH);
cp.add(winnerText, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main (String[] args)
{
ConcurrencyRace tRun = new ConcurrencyRace();
tRun.setVisible(true);
}
private class ConcurrencyPanel extends JPanel
{
public class runnerThread extends Thread {
#Override
public void run() {
while (blueDraw < 250 && redDraw < 250) {
panel.validate();
panel.repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
}
}
}
public ConcurrencyPanel ()
{
setPreferredSize(new Dimension(600,250));
}
private class ButtonListener implements ActionListener {
runnerThread rectDraw = new runnerThread();
//--------------------------------------------------------------
// Starts the thread to draw each rectangle ("racer")
//--------------------------------------------------------------
public void actionPerformed (ActionEvent event)
{
if (event.getSource() == startRace) {
rectDraw.start();
}
}
}
#Override
public void paintComponent (Graphics page) {
super.paintComponent(page);
page.setColor(Color.blue);
page.fillRect(0,80,blueDraw,20);
page.setColor(Color.red);
page.fillRect(0,120,redDraw,20);
blueDraw += rn.nextInt(10) + 1;
redDraw += rn.nextInt(10) + 1;
page.dispose();
}
}
}
Primarily
You never add a ActionListener to either of your buttons, so nothing is responding when they are activated
Additionally
The state management is all over the place. blueDraw and redDraw should be instance fields of ConcurrencyPanel.
Don't update the state of the UI (or variables which the UI relies on) from within any paint method. Paint methods should paint the state, not change it. Updating the blueDraw and redDraw should be done in a specific method, which can be called when a update is required.
All of that leads me to believe you'd be better of using a Swing Timer
Conceptually...
You could do something like this...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ConcurrencyRace {
//-----------------------------------------------------------------
// Creates and displays the main program frame.
//-----------------------------------------------------------------
public ConcurrencyRace() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Timer timer = new Timer(200, null);
JFrame frame = new JFrame();
frame.add(new ButtonPane(timer), BorderLayout.NORTH);
frame.add(new RacePane(timer));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new ConcurrencyRace();
}
public class ButtonPane extends JPanel {
private JButton startRace = new JButton("Start The Race!");
private JButton stopRace = new JButton("Stop The Race!");
public ButtonPane(Timer timer) {
startRace.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopRace.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
setLayout(new GridBagLayout());
add(startRace);
add(stopRace);
}
}
private class RacePane extends JPanel {
private int blueDraw = 5, redDraw = 5;
private Random rn = new Random();
public RacePane(Timer timer) {
timer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (updateState()) {
((Timer)e.getSource()).stop();
}
}
});
}
protected boolean updateState() {
blueDraw += rn.nextInt(10) + 1;
redDraw += rn.nextInt(10) + 1;
repaint();
return blueDraw >= getWidth() || redDraw >= getWidth();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 250);
}
#Override
public void paintComponent(Graphics page) {
System.out.println(">>");
super.paintComponent(page);
page.setColor(Color.blue);
page.fillRect(0, 80, blueDraw, 20);
page.setColor(Color.red);
page.fillRect(0, 120, redDraw, 20);
}
}
}
This maintains the Timer as the central concept, which is shared between the buttons and race panels.
I've not added support for generating notification of a winner, this would be done via a simple observer pattern passed to the RacePane

How can I set a Java Component to set its location in free space?

I'm trying to add a JButton to a JPanel programatically on click. I am able to add it in the panel, but I would like to add the succeeding buttons NOT ON TOP of the button but on the available space not occupied.
addButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
JButton button = new JButton("Button");
button.setBounds(50,20, 90,20);
internalFrame.getContentPane().add(button);
button.addMouseListener(drag);
button.addMouseMotionListener(drag);
repaint();
System.out.println("Button added.");
}
});
Here is a demonstration of adding components with a mouse click, as well as basic dragging. Please note the comments:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.MouseInputAdapter;
public class DragDemo extends JFrame {
private static int NAX_COMP_COUNT = 3;
public DragDemo() {
setTitle("Drag Demo");
setLayout(new GridLayout(1,3));
//demonstrates adding components to a null layout panel, with a button click
JPanel panelA = new CustomPanel("Add components,Null layout");
add(panelA);
//adds drsg support to the above
JPanel panelB = new CustomPanel("Add components,Null layout, Drag", true);
add(panelB);
//demonstrates adding components to a flow layout panel, with a button click
//you can add drag support, but components will be auto-layout when repainted
JPanel panelC = new CustomPanel("Add components, Flow layout", new FlowLayout());
add(panelC);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) { new DragDemo(); }
private class CustomPanel extends JPanel {
private final BevelBorder border = new BevelBorder(BevelBorder.RAISED);
private final int W =250, H = 200, GAP = 5;
private int originX =10, originY = 10;
private int compCounter = 0;
private JPanel centerPane ;
private LayoutManager layoutManager;
private boolean isDragSupport = false;
CustomPanel(String title) { this(title, null, false); }
CustomPanel(String title, boolean isDragSupport ) {
this(title,null, isDragSupport);
}
CustomPanel(String title, LayoutManager layoutManager) {
this(title,layoutManager, false);
}
CustomPanel(String title, LayoutManager layoutManager, boolean isDragSupport) {
this.layoutManager = layoutManager;
this.isDragSupport = isDragSupport;
TitledBorder tBorder = new TitledBorder(border, title);
setBorder(tBorder);
setLayout(new BorderLayout(GAP,GAP));
JButton button = new JButton("Add Label");
button.addActionListener( e-> addComponenet());
add(button, BorderLayout.SOUTH);
centerPane = new JPanel();
centerPane.setPreferredSize(new Dimension(W, H));
centerPane.setLayout(layoutManager);
add(centerPane, BorderLayout.CENTER);
}
private void addComponenet() {
if( ++ compCounter <= NAX_COMP_COUNT) {
centerPane.add(getComponent());
centerPane.getParent().revalidate();
centerPane.repaint();
}
}
private Component getComponent() {
JLabel label = new JLabel(""+ compCounter, SwingConstants.CENTER);
label.setBorder(border);
if(isDragSupport) {
DragListener drag = new DragListener();
label.addMouseListener( drag );
label.addMouseMotionListener( drag );
}
if(layoutManager == null) {//if no layout manger set bounds
label.setBounds(originX, originY, W/5, H/5);
originX +=W/5; originY += H/5; //update origin of next component
}else {
label.setPreferredSize(new Dimension(W/5, H/5));
}
return label;
}
}
//source: https://tips4java.wordpress.com/2009/06/14/moving-windows/
private class DragListener extends MouseInputAdapter {
Point location;
MouseEvent pressed;
#Override
public void mousePressed(MouseEvent me) { pressed = me; }
#Override
public void mouseDragged(MouseEvent me) {
Component component = me.getComponent();
location = component.getLocation(location);
int x = (location.x - pressed.getX()) + me.getX();
int y = (location.y - pressed.getY()) + me.getY();
component.setLocation(x, y);
}
}
}
For more control and auto-layout you may want to consider DragLayout.
Feel free to ask for any clarifications needed.

Java Swing - the best control for specific task

I need to divide java swing window into many fields, something similar to the table or chess board. Color of each cell should be dependent on the object which this cell represents (each object has coordinates, which are changing during the game, so the color of each cell is not constant).
Additionally, if the user clicks on the empty field (white color), then a new random object is created and this object is assigned to these field (and field color is changing).
Which of java swing controls will be the best for these functionalities?
If I were you I would make 2 panel classes(white and black), the white one with a MouseAdapter, so that when one of the panels is clicked you can pull a random JLabel from an array. Here's an example that might help (roughly 120 lines):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class ScratchPaper extends JFrame {
private static final long serialVersionUID = 1L;
private static final int GRIDSIZE = 8;
private JPanel[][] whitePanel = new WhitePanel[GRIDSIZE][GRIDSIZE];
private JPanel[][] blackPanel = new BlackPanel[GRIDSIZE][GRIDSIZE];
private Random rand = new Random();
JButton b1 = new JButton("Btn1");
JButton b2 = new JButton("Btn2");
JButton b3 = new JButton("Btn3");
JLabel l1 = new JLabel("Lbl1");
JLabel l2 = new JLabel("Lbl2");
JLabel l3 = new JLabel("Lbl3");
JPanel panel = new JPanel();
private JComponent[][] randObjects = {{b1, b2, b3}, {l1, l2, l3}, {panel, panel, panel}};
private Color[] randColors = {Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
public ScratchPaper() {
initGUI();
setTitle("EXAMPLE");
pack();
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private void initGUI() {
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(GRIDSIZE, GRIDSIZE)); // makes 8*8 grid
add(centerPanel, BorderLayout.CENTER);
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Component clickedComp = findComponentAt(e.getPoint());
JPanel target = (JPanel) clickedComp;
panel.setBackground(randColors[rand.nextInt(randColors.length)]);
if (target instanceof WhitePanel){
target.add(randObjects[rand.nextInt(randObjects.length)][rand.nextInt(randObjects[0].length)]);
target.updateUI();
}
}
};
addMouseListener(ma);
for (int row=0; row<GRIDSIZE; row++) {
for (int col=0; col<GRIDSIZE; col++) {
whitePanel[row][col] = new WhitePanel(row, col);
blackPanel[row][col] = new BlackPanel(row, col);
if ((row%2 == 0 && col%2 == 0) || ((row+1)%2 == 0 && (col+1)%2 == 0)) {
centerPanel.add(whitePanel[row][col]);
}
else {
centerPanel.add(blackPanel[row][col]);
}
}
}
}
public static void main(String args[]) {
try {
String className = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(className);
} catch (Exception ex) {
System.out.println(ex);
}
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
new ScratchPaper();
}
});
}
class WhitePanel extends JPanel {
private static final int SIZE = 50;
public WhitePanel(int row, int col) {
Dimension size = new Dimension(SIZE, SIZE);
setPreferredSize(size);
setBackground(Color.WHITE);
}
}
class BlackPanel extends JPanel {
private static final int SIZE = 50;
public BlackPanel(int row, int col) {
Dimension size = new Dimension(SIZE, SIZE);
setPreferredSize(size);
setBackground(Color.BLACK);
}
}
}
Try running it! It's actually pretty fun!

Increment/decrement with GUI(Java)

I am supposed to implement an application to the user that has 2 buttons(Increment/decrement) and a label. When increment is pressed the number increases and decreases by one when decrement is pressed. The number starts at 50. I have it to where it shows the buttons and they work, but they work on 2 different variables, so their is 2 number printed to the screen instead of 1. My question is how can i make the button act on only one number. I have seen people use push etc. but is there another way to do this by passing in a value to both or something? Thanks
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonModifier
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
FlowLayout flow = new FlowLayout();
frame.getContentPane().setLayout(flow);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setTitle("Button Modifier");
IncrementPanel panel = new IncrementPanel();
DecrementPanel panel1 = new DecrementPanel();
frame.add(panel);
frame.add(panel1);
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DecrementPanel extends JPanel
{
private JButton button1;
private JLabel label;
private int number = 50;
public DecrementPanel()
{
button1 = new JButton("Decrement");
button1.addActionListener(new /*DecrementPanel.*/ButtonListener());
label = new JLabel("" + number);
this.add(button1);
this.add(label);
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//int increment = 50;
number--;
label.setText("" + number);
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class IncrementPanel extends JPanel
{
private JButton button;
private JLabel label;
int number = 50;
public IncrementPanel()
{
button = new JButton("Increment");
button.addActionListener(new ButtonListener());
label = new JLabel("" + number);
this.add(button);
this.add(label);
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//int increment = 50;
number++;
label.setText("" + number);
}
}
}
I am supposed to implement an application to the user that has 2 buttons(Increment/decrement) and a label."
Then why do you have two?
IncrementPanel panel = new IncrementPanel();
DecrementPanel panel1 = new DecrementPanel();
Just use one and change the text on that one
Should be more like this
public class ButtonModifier extends JFrame {
private JLabel numberLabel = new JLable("50");
private JButton decrease = new JButton("-1");
private JButton increase = new JButton("+1");
private static int num = 50;
public ButtonModifier(){
setLayout(new GridLayout(1, 3));
add(increase);
add(numberLabel);
add(decrease);
increase.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
num++;
numLabel.setText("" + num);
}
});
decrease.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
num--;
numLabel.setText("" + num);
}
});
}
public static void main(String[] args){
JFrame frame = ButtonModifier();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setTitle("Button Modifier");
frame.setVisible(true);
}
}
You should have one JLabel which will display the only number in your program.
Then your two buttons will do operations on that number and update the label.
Your mistake is that each Panel has its own number and its own Label to display the number.
public class ButtonModifier {
private static int number = 50;
private static JLabel label;
public static void main(String[] args) {
JFrame frame = new JFrame();
label = new JLabel("" + number);
// <SNIP>
JButton increment = new JButton("Increment");
increment.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
number++;
label.setText("" + number);
}
}
JButton decrement = new JButton("Increment");
increment.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
number--;
label.setText("" + number);
}
}
frame.add(label);
frame.add(increment);
frame.add(decrement);
frame.setVisible(true);
}
}
An important note: Swing is not thread-safe, and all the operations with GUI components must be performed on Event Dispatch Thread. So your main must actually look this way:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Here you create the frame and all the components
}
});
}
Take a look at this program :
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
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;
public class IncDecApp extends JFrame {
private JButton incBtn = new JButton("Increment");
private JButton decBtn = new JButton("Decrement");
private JPanel lowPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
private JLabel showLbl = new JLabel("00", JLabel.CENTER);
private Font myFont = new Font("Tahoma", Font.BOLD, 60);
private int valueInt;
public IncDecApp() {
setTitle("IncDec Application =)");
setDefaultCloseOperation(EXIT_ON_CLOSE);
lowPanel.add(incBtn);
lowPanel.add(decBtn);
incBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
valueInt = Integer.parseInt(showLbl.getText());
valueInt++;
if (valueInt >= 10) {
showLbl.setText(String.valueOf(valueInt));
} else {
showLbl.setText("0" + String.valueOf(valueInt));
}
}
});
decBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
valueInt = Integer.parseInt(showLbl.getText());
if (valueInt > 0) {
valueInt--;
}
if (valueInt >= 10) {
showLbl.setText(String.valueOf(valueInt));
} else {
showLbl.setText("0" + String.valueOf(valueInt));
}
}
});
showLbl.setFont(myFont);
add(showLbl, BorderLayout.CENTER);
add(lowPanel, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new IncDecApp();
}
}
Create the JLabel in the main function. Have the incrementPanel and DecrementPanel classes constructors take a JLabel as an argument that they store as a private variable. The ButtonListeners csn also be passed the JLabel as an argument. Now the button listeners csn update a common JLabel.
Now, you can improve things by combining the code of IncrementPanel and DecrementPanel classes by passing an int in the constructor indicating the increment of +1 or -1.
A quick and dirty way to implement the functionality is through the use of anonymous classes implementing button listeners within a single monolithic class.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class ButtonApplet extends Applet implements ActionListener{
Button buttonInc, buttonDec;
int x=0;
public void init(){
buttonInc=new Button("Increment");
buttonDec=new Button("Decrement");
buttonInc.addActionListener(this);
buttonDec.addActionListener(this);
add(buttonInc);
add(buttonDec);
}
public void paint(Graphics g){
g.drawString("Count is : "+x,50,100);
}
public void actionPerformed(ActionEvent ev){
if(ev.getSource() == buttonInc)
{
x++;
repaint();
}
else if(ev.getSource() == buttonDec){
x--;
repaint();
}
}
}
Make Java GUI Application using AWT
You are required to make one label (Count), one textfield, one button (Increment), one button (Decrement) and one button (Close)
When the increment button is clicked, you need to increment the value in textfield, value should be incremented again and again when the button is clicked
When the decrement button is clicked, you need to decrement the value in textfield, value should be decremented again and again when the button is clicked
When the close button is clicked, you need to close the AWT Frame

Categories

Resources