For every click different effect? - java

I have one problem. First - I HAVE AND I WILL HAVE JUST ONE BUTTON.
My problem is: How it can be for each button click different effect-animation.
So, when I first time click on button image goes down, then I second time click image goes from left to right, then I third time click image gone and then it repeat for fourth click image goes down(I can make animation left to right, animation down and then image gone.So I know how to do animation (effects), but I just do not know how to create for every click different effect on image)...

first read about ActioListeners
then simply create a listener that uses a counter!
Each time you click the button the listener increases that counter. And you use different animations based on the current value of the counter. When the "last" animation took place - simply reset the counter to start from scratch.

Here you go
public class ButtonCycle extends JPanel {
private int counter = 0;
public ButtonCycle() {
JButton btn = new JButton("Next");
btn.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseClicked(MouseEvent e) {
switch(counter) {
case 0:
// "Go down"-animation code here
System.out.println("Go down");
counter++;
break;
case 1:
// "Left->right"-animation code here
System.out.println("Left->right");
counter++;
break;
case 2:
// "Disappearing"-animation code here
System.out.println("*poof*, now I'm gone");
counter = 0;
break;
}
}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
});
add(btn);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("Button cycling through animations");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(250,250));
f.setContentPane(new ButtonCycle());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}

You could utilize the java.util.Random class along with the Random.nextInt() method against values from 1 to 4 within the ActionPerformed event of your Button. Then, depending upon which value is randomly produced run a specific animation method, perhaps through a switch/case or if statements...whatever. Here is an example:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Random rnd = new Random();
int value = (rnd.nextInt(4) + 1);
switch (value) {
case 1:
imageDown();
break;
case 2:
imageLeftRight();
break;
case 3:
imageGone();
break;
case 4:
imageUp();
break;
}
}
Or if you prefer, you could use the Math.random() method., for example:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int value = 4 + (int)(Math.random() * (((1 - 2) - 4) + 1));
switch (value) {
case 1:
imageDown();
break;
case 2:
imageLeftRight();
break;
case 3:
imageGone();
break;
case 4:
imageUp();
break;
}
}
Of course there will be times when the random number generated will be the very much the same as the number generated previously but then again you could use a class field to hold the previous random value and if the currently generated value is the same as the previously generated value then you can generate another within perhaps a do/while loop, for example:
private int previousValue = 0;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int value = 0;
Random rnd = new Random();
do {
value = (rnd.nextInt(4) + 1);
} while (previousValue == value);
previousValue = value;
switch (value) {
case 1:
imageDown();
break;
case 2:
imageLeftRight();
break;
case 3:
imageGone();
break;
case 4:
imageUp();
break;
}
}

Related

How do I run the key event only once even if the key is hold?

I'm testing this code when I'm making a game with Java 8.
public void keyReleased(KeyEvent e) {
int keycode = e.getKeyCode();
switch( keycode ) {
case 37:
System.out.println("left");
break;
case 39:
System.out.println("right");
break;
case 38:
System.out.println("up");
break;
case 40:
System.out.println("down");
break;
}
}
I found out that when I press an arrow key and hold it, it will print out that key name many times until I release it. If I want it to print the key name only once even if I'm holding the key (and print it again until I release and press it again), what should I do?
I've look at the docs but it says:
Because of how operating systems handle key repeats, holding down a
key may cause multiple calls to keyPressed() (and keyReleased() as
well). The rate of repeat is set by the operating system and how each
computer is configured. ( end auto-generated )
Call method getWhen to find how much time elapsed between consecutive calls to method keyReleased. If the elapsed time is less than a particular amount (say half a second, i.e. 500 milliseconds) then you know that the key is being held down. By the way, with Java 11 on Windows 10 I don't get this behavior. The key name prints only once.
Try the below example app.
import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class GetsWhen implements KeyListener {
/** Maximum elapsed time to consider key held down. */
private static final long THRESHOLD = 500L;
/** Timestamp of last invocation of method 'keyReleased'. */
private long lastWhen;
#Override // java.awt.event.KeyListener
public void keyTyped(KeyEvent e) {
// Not implemented.
}
#Override // java.awt.event.KeyListener
public void keyPressed(KeyEvent e) {
// Not implemented.
}
#Override // java.awt.event.KeyListener
public void keyReleased(KeyEvent e) {
long when = e.getWhen();
long diff = when - lastWhen;
if (diff > THRESHOLD) {
int keycode = e.getKeyCode();
switch (keycode) {
case 37:
System.out.println("left");
break;
case 39:
System.out.println("right");
break;
case 38:
System.out.println("up");
break;
case 40:
System.out.println("down");
break;
}
}
lastWhen = when;
}
private void createAndDisplayGui() {
JFrame frame = new JFrame("When");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField textField = new JTextField(10);
textField.addKeyListener(this);
frame.add(textField);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GetsWhen().createAndDisplayGui());
}
}

How to capture user input multiple times in a JTextField

Could you help me with this little problem?
I'm trying to make a menu system which shows the options in a JEditorPane, it's something like this:
Welcome
Select an option.
1.) New register.
2.) New input.
3.) Exit.
the options are chosen by the user through a JTextField, when "1" is entered it shows another menu:
New register
1.) Option X.
2.) Option Y.
3.) Back.
and so on, the problem is that I don't know how I can capture the user's input, advance to the next menu, and re-capture the user's input all in a JTextField.
textField.addActionListener(new ActionListener () {
public void actionPerformed(ActionEvent e) {
String cap = "";
cap = textField.getText();
switch(cap) {
case "1":
paintEditorPane("Welcome");
// here is my problem, I don't know how to re-capture JTextField input
switch(cap){
case "1":
paintEditorPane("NewRegister");
break;
}
break;
}
}
});
Here's Basic. Now you have to make many cases to judge states.
public static class MainPanel extends JPanel{
private JTextArea textArea;
public MainPanel() {
this.setLayout(new BorderLayout());
this.textArea = new JTextArea();// you can use constructor to set Text but I like use method "setText".
this.textArea.addKeyListener(new keyHandler());
this.textArea.setText("Welcome\r\nSelect an option. 1.) New register. 2.) New input. 3.) Exit.\r\n");
this.textArea.setCaretPosition(this.textArea.getText().length());// move caret to last
this.add(this.textArea, BorderLayout.CENTER);
}
public void addText(String text) {textArea.setText(textArea.getText() + "\r\n" + text +"\r\n");}
public class keyHandler extends KeyAdapter{
#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_1 : addText("New register"); break;
case KeyEvent.VK_2 : addText("New input"); break;
case KeyEvent.VK_3 : addText("Exit"); break;
}
}
}
}

Memory game card flipping problems

I'm working on a simple memory game where you basically match the same cards. I want the cards to be able to flip back if both didn't match. The flipping codes are the following:
mT1.unselect();
mT2.unselect();
When i put it in the else statement the cards flip back immediately so i used a handler to slow it down.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mT1.unselect();
mT2.unselect();
playSound( SOUND_FAILED );
}
}, 2000);
But when i test it doesn't flip back, but the sound is played after the given time. What's the problem?
Full code:
public void onPosition(int position)
{
if (position == mLastPosition)
{
return;
}
mLastPosition = position;
Tile tile = mList.get(position);
tile.select();
int sound = tile.mResId % mSounds.length;
playSound(sound);
switch (mSelectedCount)
{
case 0:
mT1 = tile;
break;
case 1:
mT2 = tile;
if (mT1.getResId() == mT2.getResId())
{
mT1.setFound(true);
mT2.setFound(true);
mFoundCount += 2;
playSound(SOUND_SUCCEED);
}
else
{
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mT1.unselect();
mT2.unselect();
playSound( SOUND_FAILED );
}
}, 2000);
}
break;
case 2:
if (mT1.getResId() != mT2.getResId())
{
}
mSelectedCount = 0;
mT1 = tile;
break;
}
mSelectedCount++;
mMoveCount++;
updateView();
checkComplete();
}
As with your previous question, you've still not given us enough context, but I'll have a wild stab in the dark - maybe you need to call:
updateView();
in your Runnable's run() method.
Maybe if you post your updateView() method and some more context of how it works, we might be able to help more if this guess doesn't fix it.

Why are some keypresses not being captured during multi-key combinations?

Is it a keyboard limitation problem?
I'm having an issue with some code I'm just playing around with. Imagine a top down space shooter. The issue I'm having is that, on my computer, when I press and hold the up and left arrows, I cannot shoot (Spacebar). Any other direction (up, down, left, right, up + right, right + down, left + down) works. I had a friend run the code on his computer and he found that all directions worked except up + right and right + down, but up + left worked fine for him. We both looked at the code and can't figure it out. Could this be a hardware issue?
Basically, this is what I'm doing:
import javax.swing.*;
import java.awt.event.*;
public class Test extends JFrame
{
boolean up, down, left, right, fire;
// Main constructor
public Test()
{
// listeners for user input
this.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
{
up = true;
break;
}
case KeyEvent.VK_LEFT:
{
left = true;
break;
}
case KeyEvent.VK_RIGHT:
{
right = true;
break;
}
case KeyEvent.VK_DOWN:
{
down = true;
break;
}
case KeyEvent.VK_SPACE:
{
fire = true;
break;
}
case KeyEvent.VK_ESCAPE:
{
// Exit
System.exit(0);
}
}
}
public void keyReleased(KeyEvent e)
{
// Upon releasing key, stop direction
switch(e.getKeyCode())
{
case KeyEvent.VK_UP:
{
up = false;
break;
}
case KeyEvent.VK_LEFT:
{
left = false;
break;
}
case KeyEvent.VK_RIGHT:
{
right = false;
break;
}
case KeyEvent.VK_DOWN:
{
down = false;
break;
}
}
}
});
}
public static void main(String[] args)
{
// create frame
Test test = new Test();
test.setLocationRelativeTo(null);
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setVisible(true);
test.loop();
}
public void loop()
{
Timer timer = new Timer(250, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (up)
System.out.println("Moving UP.");
if (left)
System.out.println("Moving LEFT.");
if (right)
System.out.println("Moving RIGHT.");
if (down)
System.out.println("Moving DOWN.");
if (fire)
{
System.out.println("FIRING.");
fire = false;
}
}
});
timer.start();
}
}
This question was originally asked here.
Yes, it looks like a hardware limitation. You can try to check whether it behaves the same way in other programs, if yes, it's definitely a hardware issue.
Keyboards have these kinds of limitations, see Rollover (key).

Java Scoping with ActionListeners

I have an application that needs to scan for bluetooth devices every 10 minutes for a duration set by the user.
I have two javax.swing.Timer (not java.util.Timer) - one controls invoking the Scanning method every 10 minutes, the other is stopping the first timer (therfore stopping the scanning) once the duration limit has been hit.
The durationTimer is created and started within an actionListener.
My problem is that because durationTimer is created within an ActionListener, i cannot stop the timer from another ActionListener, as the program cannot "see" the variable name "durationTimer".
The reduced code is shown below....
public class mainGui extends JFrame
{
public mainGui()
{
final ActionListener timerActionEvent = new ActionListener(){
public void actionPerformed(ActionEvent evt){
//start a task here
Timer myTimer2 = (Timer) evt.getSource();
//Invoke BluetoothScan method
BluetoothScan(myTimer2);
}
};
final Timer timerDuration;
final Timer myTimer = new Timer(5000, timerActionEvent);
final ActionListener timerDurationActionEvent = new ActionListener(){
public void actionPerformed(ActionEvent evt){
//Stops myTimer, so that Bluetooth Stops scanning every 10mins.
myTimer.stop();
}
};
ActionListener btnScanAction = new ActionListener(){
//Action listener for reading data from db
public void actionPerformed(ActionEvent e){
int roomID = 0;
int lecturer = 0;
int unit;
int roomIDIndex;
int lectIDIndex;
int yearIDIndex;
int unitIDIndex;
String[] roomArray;
String[] lecturerArray;
String[] unitArray = null;
int durationIndex;
String DURATION;
int durationInt;
//System.out.println(unitArray.length);
durationIndex = durCB.getSelectedIndex();
DURATION = itemDuration[durationIndex];
durationInt = Integer.parseInt(DURATION);
//User Selected Duration converted to Milliseconds
int durationMilliSec = (int)(durationInt*60000);
ArrayList<String[]> unitYear = null;
//Store the index ID of the JComboBox Selections
roomIDIndex = roomCB.getSelectedIndex();
lectIDIndex = lectCB.getSelectedIndex();
unitIDIndex = unitCB.getSelectedIndex();
yearIDIndex = yearCB.getSelectedIndex();
switch(yearIDIndex)
{
case 1: unitYear = Units1; break;
case 2: unitYear = Units2; break;
case 3: unitYear = Units3; break;
case 4: unitYear = UnitsMasters; break;
}
//Get the Array contents at index location
roomArray = rooms.get(roomIDIndex);
lecturerArray = Lecturers.get(lectIDIndex);
unitArray = unitYear.get(unitIDIndex);
if(unitArray==null){
System.out.println("Please select a unit");
System.exit(0);
}
roomID = Integer.parseInt(roomArray[0]);
lecturer = Integer.parseInt(lecturerArray[0]);
unit = Integer.parseInt(unitArray[0]);
populateComboBoxes pcb = new populateComboBoxes();
pcb.LabSessionInfo(roomID, lecturer, unit);
myTimer.start();
Timer timerDuration = new Timer(durationMilliSec, timerDurationActionEvent);
timerDuration.start();
}
};
public void BluetoothScan(Timer myTimer) {
BluetoothDeviceDiscovery scan = new BluetoothDeviceDiscovery();
try {
myTimer.stop();
scan.main();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myTimer.start();
};
}
Thankyou in advance for any help
You can declare the durationTimer at the class level and still construct it in the ActionListener. This way it should be visible throughout the class. Just be sure to check that it's not null before trying to call stop() on it.
Another option is to have it stop itself:
final ActionListener timerDurationActionEvent = new ActionListener(){
public void actionPerformed(ActionEvent evt){
//Stops myTimer, so that Bluetooth Stops scanning every 10mins.
myTimer.stop();
((Timer)evt.getSource()).stop();
}
};
And another (and perhaps the best) option is to simply make it non-repeating:
Timer timerDuration = new Timer(durationMilliSec, timerDurationActionEvent);
timerDuration.setRepeats(false);
timerDuration.start();
This last one is the way to go.
Since you start the blue tooth scan on the Event Dispatch thread, you're second Timer will not fire until the blue tooth scan is complete.
You need to start a new thread for the blue tooth scan.
I suggest you use a SwingWorker.
I don't know when btnScanAction is triggered (probably often since it is an ActionListener), but it creates a new
timerDuration at each call. You'll probably end up with multiple duration timers, which (I guess...) is not what you want.

Categories

Resources