Java GUI: Change Label in another class - java

Hi so I have this template program and basically what I need to do is:
When the More Bricks button is pressed a new window opens. When that window there is a button in there and when that is pressed the brick variable should be reset and the label should be reset as well in the original window needs to be reset to its original number. How would I go about this?
This is the first class
import javax.swing.*;
import java.awt.event.*;
public class Brick {
private JFrame firstbricks;
int price = 0;
int bricks = 20;
public static void main(String[] args) {
Brick window = new Brick();
window.firstbricks.setVisible(true);
}
public Brick() {
firstbricks = new JFrame();
firstbricks.setBounds(0, 0, 272, 130);
firstbricks.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
firstbricks.getContentPane().setLayout(null);
JLabel lblBricks = new JLabel("20 remaining");
lblBricks.setBounds(20, 54, 128, 23);
firstbricks.getContentPane().add(lblBricks);
JButton btnBricks = new JButton("Bricks");
btnBricks.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
bricks--;
if (bricks <= 20) {
lblBricks.setText(bricks + " remaining");
price += 4;
}
}
});
btnBricks.setBounds(10, 11, 104, 32);
firstbricks.getContentPane().add(btnBricks);
JButton btnExtra = new JButton("More Bricks");
btnExtra.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
MoreBricks info = new MoreBricks();
}
});
btnExtra.setBounds(131, 11, 115, 32);
firstbricks.getContentPane().add(btnExtra);
}
}
And here is the second window class which I want the labels to be changed from:
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MoreBricks {
private JFrame MoreBricks;
public MoreBricks() {
makeFrame();
}
private void makeFrame() {
MoreBricks = new JFrame();
MoreBricks.setBounds(100, 100, 156, 114);
MoreBricks.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
MoreBricks.getContentPane().setLayout(null);
MoreBricks.setVisible(true);
JButton reset = new JButton("Reset");
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
reset.setBounds(10, 11, 104, 34);
MoreBricks.getContentPane().add(reset);
}
}

Easy solution (but perhaps not the best), is MoreBricks constructor takes a Brick instance in as the constructor:
public class MoreBricks {
private JFrame MoreBricks;
private Brick _brick;
public MoreBricks(Brick b) {
_brick = brick;
makeFrame();
}
Then your Reset button just does something like the following:
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
MoreBricks.this._bricks.ResetBrickCount();
}
Ideally you have a "model" class in which all the state of your game (e.g. number of bricks) is encapsulated into a single class. Then whenever the model changes, all the dependent "views" are notified of the change and update themselves to reflect the right values and state on the screen.

Related

JCompenents Not Moving With JFrame

I am trying to create a game about war. I am starting off with just creating a single window. I am using swing to create windows. However, when the user tries to resize the JFrame, the elements don't move with the frame. I am resizing the buttons that I use, as well as my JPanel. My code can be seen below:
Main.java:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import Numbers.Numbers;
public class Main implements ActionListener {
static JFrame frame;
static JPanel titlePane;
static JButton playButton;
static JButton explanationButton;
static JPanel explanationPane;
static JButton nextButton;
static JLabel explanationLabel;
static JButton backButton;
static int frameSize = 500;
public Main(boolean run) {
if (run) {
frame = new JFrame("War");
titlePane = new JPanel(null);
playButton = new JButton("PLAY");
explanationButton = new JButton("HOW TO PLAY");
explanationPane = new JPanel(null);
nextButton = new JButton("NEXT");
backButton = new JButton("BACK");
titlePane.setSize(frameSize, frameSize);
titlePane.add(playButton);
playButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
playButton.setBackground(Color.GRAY);
playButton.setForeground(Color.WHITE);
playButton.setVisible(true);
explanationButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/(25/11)), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
explanationButton.setBackground(Color.GRAY);
explanationButton.setForeground(Color.WHITE);
explanationButton.setVisible(true);
explanationPane.setSize(frameSize, frameSize);
explanationPane.add(nextButton);
nextButton.setBounds(225, 50, 50, 15);
nextButton.setBackground(Color.GRAY);
nextButton.setForeground(Color.WHITE);
nextButton.setVisible(true);
backButton.setBounds(225, 450, 50, 15);
backButton.setBackground(Color.GRAY);
backButton.setForeground(Color.WHITE);
backButton.setVisible(true);
frame.setSize(frameSize, frameSize);
frame.add(titlePane);
frame.add(explanationPane);
titlePane.setVisible(false);
explanationPane.setVisible(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
public void switchPane(String pane) {
switch (pane) {
case "title":
titlePane.setVisible(true);
explanationPane.setVisible(false);
break;
case "explanation":
titlePane.setVisible(false);
explanationPane.setVisible(true);
break;
}
}
#Override
public void actionPerformed(ActionEvent event) {
}
public static void main(String[] args) {
Main war = new Main(true);
war.switchPane("title");
while (true) {
if (frame.getX() != frameSize) {
frameSize = frame.getX();
}
else if (frame.getY() != frameSize) {
frameSize = frame.getY();
}
frame.setSize(frameSize, frameSize);
titlePane.setSize(frameSize, frameSize);
explanationPane.setSize(frameSize, frameSize);
playButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
explanationButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/(25/11)), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
}
}
}
Numbers.java:
package Numbers;
public class Numbers {
public static int doubleToInt(double toConvert) {
int toReturn = (int) toConvert;
return toReturn;
}
}
Any help would be appreciated! :)
Please note I am not close to finishing so please ignore the empty method.

How to make when i click JButton to make it doubling output. For ex i click jButton once, but i want to output 2

I'm trying to make cookie clicker game and i'm at point where i want to program upgrades, for ex: when i buy first upgrade i want if i click once to get 2 cookies, before upgrade it was if i click once i get only 1 cookie. I'm not sure how to code that and also in the future i want to code even more upgrades. What i'm asking to someone help me to make peace of code that can be used to make clicking upgrades.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.*;
public class JavaApplication13 {
public static void main(String[] args) {
DBP prozor = new DBP();
prozor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
prozor.setVisible(true);
}
}
class DBP extends JFrame {
private JLabel oznaka;
public DBP() {
setTitle("Cookie Clicker");
setSize(500, 150);
setLayout(new FlowLayout(FlowLayout.CENTER, 30, 20));
oznaka = new JLabel("No points!");
add(oznaka);
JButton dugme = new JButton("Click");
add(dugme);
JButton upgrade = new JButton("Buy upgrade!");
add(upgrade);
upgrade.setVisible(false);
dugme.addActionListener(new ActionListener() {
private int brojac;
#Override
public void actionPerformed(ActionEvent e) {
brojac++;
oznaka.setText("Points " + brojac);
if (brojac == 5) {
upgrade.setVisible(true);
}
}
});
upgrade.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
upgrade.setVisible(false);
System.out.println("SA");
}
});
}
}
The simplest way to do it, is to keep a boolean value if the user has clicked the upgrade button. If he did, increase "cookies" one more time.
public class JavaApplication13 {
public static void main(String[] args) {
// All swing applications must run on their own thread.
SwingUtilities.invokeLater(() -> {
DBP prozor = new DBP();
prozor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
prozor.setVisible(true);
});
}
}
class DBP extends JFrame {
private JLabel oznaka;
private boolean upgraded; //whether user upgraded
public DBP() {
setTitle("Cookie Clicker");
setSize(500, 150);
setLayout(new FlowLayout(FlowLayout.CENTER, 30, 20));
oznaka = new JLabel("No points!");
add(oznaka);
JButton dugme = new JButton("Click");
add(dugme);
JButton upgrade = new JButton("Buy upgrade!");
add(upgrade);
upgrade.setVisible(false);
dugme.addActionListener(new ActionListener() {
private int brojac;
#Override
public void actionPerformed(ActionEvent e) {
brojac++;
if (upgraded)
brojac++;
oznaka.setText("Points " + brojac);
if (brojac == 5) {
upgrade.setVisible(true);
}
}
});
upgrade.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
upgrade.setVisible(false);
upgraded = true;
}
});
}
}

Which objects do I attach the Timer class event listener to, in Java?

I am trying to create a whack a mole game. I have used swing to create background and add mole images with event listeners which increment a score each time they are clicked, but I am having problems setting whether they should be visible or not. I thought the best way to do this would be to use a timer to set/reset a boolean (vis). Randomizing the period for which the images are visible would be ideal. I have tried using a swing timer several times but doesn't seem to be working. Where do I instantiate the timer, and to what do I attach the event listener which executes the code after the timer has counted down?
package whackmole;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class WhackAMole extends JFrame {
public WhackAMole() {
createAndShowGUI();
}
static int score = 0;
public static JLabel scoreDisplay;
boolean vis;
public static void main(String[] args) throws Exception {
// run asynchronously
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(600, 600));
Holes holes = new Holes(frame);
frame.getContentPane().add(holes);
holes.setLayout(null);
frame.pack();
frame.setVisible(true);
scoreDisplay = new JLabel("Score: " + score);
scoreDisplay.setBounds(239, 11, 84, 38);
holes.add(scoreDisplay);
Mole mole = new Mole(68, 92, true);
mole.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
score++;
scoreDisplay.setText("Score: " + score);
}
});
holes.add(mole);
Mole mole2 = new Mole(181, 320, false);
mole2.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
score++;
scoreDisplay.setText("Score: " + score);
}
});
holes.add(mole2);
Mole mole3 = new Mole(414, 439, true);
mole3.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
score++;
scoreDisplay.setText("Score: " + score);
}
});
holes.add(mole3);
Mole mole4 = new Mole(297, 203, false);
mole4.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
score++;
scoreDisplay.setText("Score: " + score);
}
});
holes.add(mole4);
}
}
In this context, you can instantiate your Timer with a fixed rate and a class that implements ActionListener.
public class Example extends JPanel implements ActionListener {
private static final int RATE = 1000 / 8; // ~8 Hz
private final Timer timer = new Timer(RATE, this);
}
In this complete example, GameButton is a subclass of JToggleButton, and the implementation of ActionListener simply toggles the state of a randomly selected GameButton.
private final List<GameButton> buttons = new ArrayList<GameButton>(MAX);
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == timer) {
int index = random.nextInt(game.max());
GameButton gb = buttons.get(index);
gb.setSelected(!gb.isSelected());
}
...
}
To distinguish states, the example uses Unicode glyphs, but you can use setIcon() and setSelectedIcon().

Auto clicker UI goes black when started

i have made a simple auto clicker, but when i run it the screen goes black so i cant stop it etc. i dont have a clue what i have done wrong. I thought maybe i had to set focus, but i am not sure.
Code:
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.UIManager;
import javax.swing.JRadioButton;
public class AutoClicker1 extends JFrame {
private JPanel contentPane;
private JTextField textField;
public static int rate;
public static boolean go = false;
public static int time;
public static int multiplyer;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
AutoClicker1 frame = new AutoClicker1();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public AutoClicker1() {
setTitle("Auto Clicker");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 361, 154);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel lblNoOfClicks = new JLabel("Interval between clicks");
lblNoOfClicks.setBounds(10, 25, 149, 14);
contentPane.add(lblNoOfClicks);
textField = new JTextField();
textField.setBounds(10, 55, 139, 20);
contentPane.add(textField);
textField.setColumns(10);
JButton btnStopf = new JButton("Stop(F11)");
btnStopf.setBounds(203, 45, 89, 23);
contentPane.add(btnStopf);
JButton button = new JButton("Stop(F11)");
button.setBounds(203, 81, 89, 23);
contentPane.add(button);
final JRadioButton rdbtnSeconds = new JRadioButton("Seconds");
rdbtnSeconds.setBounds(6, 81, 65, 23);
contentPane.add(rdbtnSeconds);
final JRadioButton rdbtnMilliseconds = new JRadioButton("Milliseconds");
rdbtnMilliseconds.setBounds(71, 81, 109, 23);
contentPane.add(rdbtnMilliseconds);
btnStopf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
go = false;
}
});
JButton btnStart = new JButton("Start(F10)");
btnStart.setBounds(203, 11, 89, 23);
contentPane.add(btnStart);
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
go = true;
if (rdbtnMilliseconds.isSelected()) {
autoClick();
} else {
if (rdbtnSeconds.isSelected()) {
multiplyer = 1000;
autoClick();
}
}
}
});
}
private void autoClick() {
requestFocus();
rate = Integer.parseInt(textField.getText());
time = (rate * multiplyer);
System.out.print(time);
try {
Robot robot = new Robot();
while (true) {
try {
Thread.sleep(rate);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (InterruptedException ex) {}
}
} catch (AWTException e) {}
}
private void keyListner(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_F10) {
System.out.print("pressed F10");
go = true;
}
if (key == KeyEvent.VK_F11) {
go = false;
}
}
private void setTheme() {
try {
UIManager
.setLookAndFeel("com.seaglasslookandfeel.SeaGlassLookAndFeel");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void checkRate() {
if (rate < 500) {
rate = 0;
}
}
}
You are blocking the Event Dispatch Thread in autoClick() with the while(true), instead of that you can use a Swing Timer.
I suggest not using keyListener for listen only 2 keys, you can use keybindings for that purpose. Also you shouldn't call directly setBounds rely in a proper LayoutManager to position in screen.
You break out of the program loop in your Main method when you enter the wile loop in your AutoClick method.
You could instead run your program in a "game loop".
In the main method what I would do is create a method called run()
public void run()
{
int FPS = 60;
float startTime = System.currentTimeInMillis();
while(started)
{
float currentTime = System.currentTimeInMillis();
float passedTime = currentTime - startTime;
startTime = System.currentTimeInMillis();
if(passedTime > (float) 1000/FPS)
{
update();
}
}
}
and then in the update method put the logic of the program. I know it is a totally different approach to how you are currently doing it but in my opinion it allows for more flexibility.
For example in your action listener you could have it invoke a "startClick()" method
where it sets a boolean value to true and initializes what you intialzie currently in the autoclick method. Then your update() method would look like this:
public void update()
{
if(boolean) //boolean value that startClick sets to true
{
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
This way the program isn't stuck in an infinite while-loop and you can control how often it updateswith the FPS variable.

Toggle read-only in Java

Is there a way to toggle a read-only mode so when you click any object in your window it simply returns what you clicked, ignoring the object's usual event handling? IE, while in this "read-only" mode, if you click on a Button, it simply returns the button, not actually pressing the button. Then I could do something like:
if ("thing pressed" == button) "do this";
else if ("thing pressed" == panel) "do that";
else "do nothing";
Here's my code, its a frame with 3 colored boxes. Clicking the 2nd box, the 3rd box, or the background will display a message. Clicking box 1 does nothing. I like using new mouse adapters so I want to do it this way.
Now what I want is when you click box 1, box 1 is treated as selected (if that helps you get the picture). Then if you click anywhere, including box 1 again, box 1 is deselected and nothing else (meaning that box 2, box 3. or the background's message will display). At that time, only if box 2 or 3 were clicked, they will still not display their normal message but a different message would be displayed.
I'm very sorry if I come off a little short.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Labels {
public static void main(String[] args) {
new Labels();
}
Square l1, l2, l3;
public Labels() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
l1 = new Square();
l2 = new Square();
l3 = new Square();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(120, 150);
frame.setResizable(false);
panel.setVisible(true);
panel.setLayout(null);
l1.setLocation(5, 5);
l2.setLocation(5, 60);
l3.setLocation(60, 5);
l2.setColor("yellow");
l3.setColor("black");
l1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
//do nothing
}
});
l2.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Pushed label 2");
}
});
l3.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Pushed label 3");
}
});
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("pushed background");
}
});
frame.add(panel);
panel.add(l1);
panel.add(l2);
panel.add(l3);
}
class Square extends JLabel{
Color color = Color.blue;
public Square() {
// TODO Auto-generated constructor stub\
setVisible(true);
setSize(50,50);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(color);
g.fillRect(0, 0, 50, 50);
}
public void setColor(String color){
if (color == "white") this.color = Color.white;
else if (color == "black") this.color = Color.black;
else if (color == "yellow") this.color = Color.yellow;
else {
System.out.println("Invalid color");
return;
}
repaint();
}
}
}
Don't disable anything. Simply change the state of your class, perhaps by using a few boolean flag variables/fields and change these flags depending on what is pressed.
So have boolean fields called label1PressedLast, label2PressedLast, and label3PressedLast or something similar, and when a label is pressed, check the states of all other flags and have your program's behavior change depending on the state of these flags and the label that was just pressed. Then set all flags to false except for the one corresponding to the label that was just pressed.
For example, this little program reacts only if the first and then the third JLabel have been pressed:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class FlagEg extends JPanel {
private static final int LABEL_COUNT = 3;
private JLabel[] labels = new JLabel[LABEL_COUNT];
private boolean[] flags = new boolean[LABEL_COUNT];
public FlagEg() {
setLayout(new GridLayout(1, 0, 20, 0));
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
// panel mouse listener
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
inactivateAll();
}
});
MouseListener labelsMouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvt) {
myMousePressed(mouseEvt);
}
};
// create JLabels and add MouseListener
for (int i = 0; i < labels.length; i++) {
labels[i] = new JLabel("Label " + (i + 1));
labels[i].addMouseListener(labelsMouseListener);
labels[i].setOpaque(true);
labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
add(labels[i]);
}
}
private void inactivateAll() {
for (int i = 0; i < labels.length; i++) {
labels[i].setBackground(null);
flags[i] = false;
}
}
private void myMousePressed(MouseEvent mouseEvt) {
JLabel label = (JLabel) mouseEvt.getSource();
// which label was pressed?
int index = -1;
for (int i = 0; i < labels.length; i++) {
if (label == labels[i]) {
index = i;
}
}
// check if first label and then third pressed:
if (flags[0] && index == 2) {
System.out.println("first and then third label pressed!");
}
// reset all labels and flags to initial state
inactivateAll();
// set pressed label background color and set flag of label just pressed
labels[index].setBackground(Color.pink);
flags[index] = true;
}
private static void createAndShowGui() {
FlagEg mainPanel = new FlagEg();
JFrame frame = new JFrame("Flag Example");
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(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Logic iteration two: only label 1 is the "primer" JLabel. This is actually easier to implement, because now you only need one boolean flag, that representing label 1 being pressed:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class FlagEg2 extends JPanel {
private static final int LABEL_COUNT = 3;
private JLabel[] labels = new JLabel[LABEL_COUNT];
private boolean label1Flag = false;
public FlagEg2() {
setLayout(new GridLayout(1, 0, 20, 0));
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
// panel mouse listener
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
inactivateAll();
}
});
MouseListener labelsMouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvt) {
myMousePressed(mouseEvt);
}
};
// create JLabels and add MouseListener
for (int i = 0; i < labels.length; i++) {
labels[i] = new JLabel("Label " + (i + 1));
labels[i].addMouseListener(labelsMouseListener);
labels[i].setOpaque(true);
labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
add(labels[i]);
}
}
private void inactivateAll() {
for (int i = 0; i < labels.length; i++) {
labels[i].setBackground(null);
label1Flag = false;
}
}
private void myMousePressed(MouseEvent mouseEvt) {
JLabel label = (JLabel) mouseEvt.getSource();
// which label was pressed?
int index = -1;
for (int i = 0; i < labels.length; i++) {
if (label == labels[i]) {
index = i;
}
}
if (label1Flag) {
if (index == 1) {
System.out.println("Label 1 and label 2 pressed");
} else if (index == 2) {
System.out.println("Label 1 and label 3 pressed");
}
}
// reset all labels and flags to initial state
inactivateAll();
// if label1, then activate it
if (index == 0) {
labels[0].setBackground(Color.pink);
label1Flag = true;
}
}
private static void createAndShowGui() {
FlagEg2 mainPanel = new FlagEg2();
JFrame frame = new JFrame("Flag Example");
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(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
package javaapplication6;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* #author Jan Vorcak <vorcak#mail.muni.cz>
*/
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
MouseListener listener = new MouseAdapter() {
private int count = 0;
#Override
public void mouseClicked(MouseEvent e) {
if(e.getComponent() instanceof JLabel) {
count++;
if (count >= 2) {
System.out.println("clicked 2 times on labels");
count = 0;
}
} else {
count = 0;
}
}
};
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel l1 = new JLabel("Label 1");
JLabel l2 = new JLabel("Label 2");
JLabel l3 = new JLabel("Label 3");
l1.addMouseListener(listener);
l2.addMouseListener(listener);
l3.addMouseListener(listener);
frame.addMouseListener(listener); // or panel.addMouseListener(listener);
panel.add(l1);
panel.add(l2);
panel.add(l3);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
You could want to create a listener that do the job for using the putClientProperty method of JComponent.
public class JComponentClickCountListener extends MouseAdapter {
private final Integer ONE = 1;
#Override
public void mouseClicked(MouseEvent e) {
if (e.getComponent() instanceof JComponent) {
JComponent jComponent = (JComponent) e.getComponent();
Object property = jComponent.getClientProperty(JComponentClickCountListener.class);
if (property instanceof Number) {
property = ONE + ((Number) property).intValue();
}
else {
property = ONE;
}
jComponent.putClientProperty(JComponentClickCountListener.class, property);
}
}
}
Then in your code you can decide to have a single instace of that class for all of your components or create a new one each time.
This could give you the advantage of using the propertyChangeListener for future actions.
PS.
The code example do not represent all logic for OP question but i could by used as solid base. Later on i will try to update it. To cover that.
EDIT2:
I think that you should separate the logic, of selection and action over selected items. Then the task is divided into two tasks. First is the possibility to store the information about it state, clicked active, clicked again inactive. The second tasks it to operate on that status when a jComponent status was changed.
This is an simple example that i wrote, the functionality is to highlight the background of labels when the are selected and remove it when it was clicked again or the panel was clicked remove all selections.
This example is divided to three elements Enum, Iterface and class that manage the logic of selection
Enum - we store the possible statuses and a property key.
public enum JComponentActivationStatus {
NONE,
ACTIVE,
INACTIVE;
public static final String PROPERTY_KEY = JComponentActivationStatus.class.getCanonicalName();
}
Interface - provide a delegate for action to be taken when jcomponenet status change.
public abstract interface JComponenetActivationStatusChangeAction<T extends JComponent> {
public abstract void onActivation(T object);
public abstract void onDeactivation(T object);
}
Class - This class mange the status logic of jcomponents.
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
public class JComponenetActivationManager {
public static <T extends JComponent> T addMouseStatusControl(T jComponent) {
jComponent.addMouseListener(new JComponentMouseStatusModyfier());
return jComponent;
}
public static <T extends JComponent> T addActivationStatusChangeAction(T jComponenet, JComponenetActivationStatusChangeAction<T> statusChangeAction) {
jComponenet.addPropertyChangeListener(craeteJCompositeActivationStatusChangeListener(statusChangeAction));
return jComponenet;
}
public static <T extends JComponent> PropertyChangeListener craeteJCompositeActivationStatusChangeListener(JComponenetActivationStatusChangeAction<T> action) {
return new JComponentStatusPropertyChangeListener<T>(action);
}
/**
* Class that set the status for the JComponet after doubClicl
*/
private final static class JComponentMouseStatusModyfier extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
if(e.getComponent() instanceof JComponent) {
JComponent jComponent = (JComponent) e.getComponent();
Object propertyValue = jComponent.getClientProperty(JComponentActivationStatus.PROPERTY_KEY);
if(JComponentActivationStatus.ACTIVE.equals(propertyValue)) { //We check that the ACTIVE status is already selected, if so we inactive.
propertyValue = JComponentActivationStatus.INACTIVE; //If so we inactive it.
} else {
propertyValue = JComponentActivationStatus.ACTIVE; // Otherwise we set it as active
}
jComponent.putClientProperty(JComponentActivationStatus.PROPERTY_KEY, propertyValue); // We use the property key form status
}
}
}
/**
* Help class that fire the actions after status is changed
*/
private static final class JComponentStatusPropertyChangeListener<T extends JComponent> implements PropertyChangeListener {
private final JComponenetActivationStatusChangeAction<T> statusChangeAction;
/**
*
*/
public JComponentStatusPropertyChangeListener(JComponenetActivationStatusChangeAction<T> statusChangeAction) {
if(statusChangeAction == null) {
throw new IllegalArgumentException("action can not be null at this point");
}
this.statusChangeAction = statusChangeAction;
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
if(JComponentActivationStatus.PROPERTY_KEY.equals(evt.getPropertyName())) {
if(JComponentActivationStatus.ACTIVE.equals(evt.getNewValue())) {
statusChangeAction.onActivation((T) evt.getSource());
}
if(JComponentActivationStatus.INACTIVE.equals(evt.getNewValue())){
statusChangeAction.onDeactivation((T) evt.getSource());
}
}
}
}
}
That class contain two public static method, that allow the developer to add the functionality to mange status to any jComponent object, add subscribe the action handler if any change occur.
At the end we have the main method that test our solution
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel l1 = new JLabel("Label 1");
JLabel l2 = new JLabel("Label 2");
JLabel l3 = new JLabel("Label 3");
panel.setBackground(Color.CYAN);
addMouseStatusControl(panel);
addMouseStatusControl(l1);
addMouseStatusControl(l2);
addMouseStatusControl(l3);
JComponenetActivationStatusChangeAction<JLabel> activeBackground = new JComponenetActivationStatusChangeAction<JLabel>() {
#Override
public void onActivation(JLabel object) {
object.setOpaque(true);
object.setBackground(Color.YELLOW);
}
#Override
public void onDeactivation(JLabel object) {
object.setOpaque(false);
object.setBackground(object.getParent().getBackground());
}
};
JComponenetActivationStatusChangeAction<JPanel> deactivateChildrens = new JComponenetActivationStatusChangeAction<JPanel>() {
#Override
public void onDeactivation(JPanel object) {
}
#Override
public void onActivation(JPanel object) {
for(Component component : object.getComponents()) {
if(component instanceof JComponent) {
((JComponent) component).putClientProperty(JComponentActivationStatus.PROPERTY_KEY,JComponentActivationStatus.INACTIVE);
}
}
}
};
addActivationStatusChangeAction(l1, activeBackground);
addActivationStatusChangeAction(l2, activeBackground);
addActivationStatusChangeAction(l3, activeBackground);
addActivationStatusChangeAction(panel, deactivateChildrens);
panel.add(l1);
panel.add(l2);
panel.add(l3);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
The solution is very flexible and extendable in case you will need to add more labels.
The example is for those that want to learn. Any comment would be appreciate.

Categories