I am new to Java and I'm trying to make an auto clicker. It works like this. when you click a button, the application starts clicking (also works when you press s), and when you press "w" the application stops clicking. My main issue currently is I can't manage to make my application click :V. (I also have a "main.java" for startup) Here's my code vvvvvvv
package copy;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyAdapter;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Game
implements ActionListener{
JFrame frame;
JLabel label;
JButton button;
Action ON;
Action OFF;
private static Robot bot;
public static boolean status = false;
Game(){
ON = new statusON();
OFF = new statusOFF();
frame = new JFrame("Bullet Chicken Clicker");
label = new JLabel();
button = new JButton("turn on?");
frame.setSize(400, 400);
frame.setLocation(600, 150);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.add(label);
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label.getInputMap().put(KeyStroke.getKeyStroke('w'), "OFF");
label.getActionMap().put("OFF", OFF);
label.getInputMap().put(KeyStroke.getKeyStroke('w'), "upAction");
label.getActionMap().put("upAction", ON);
label.getInputMap().put(KeyStroke.getKeyStroke('s'), "downAction");
label.getActionMap().put("downAction", OFF);
button.setPreferredSize(new Dimension(40, 40));
button.setOpaque(true);
button.setForeground(Color.BLACK);
button.setBounds(125, 150, 150, 30);
button.setVisible(true);
button.addActionListener(this);
button.setFocusable(false);
}
private void clicky() {
while (status == true);
bot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
bot.delay(300);
bot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
bot.delay(300);
}
public static void robot() {
try {
bot = new Robot();
} catch (AWTException e2) {
e2.printStackTrace();
}
}
public class statusON extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
status = true;
System.out.print(status);
}
}
public class statusOFF extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
status = false;
System.out.print(status);
}
}
#Override
public void actionPerformed(ActionEvent e) {
status = true;
System.out.print(status);
}
}
My main issue currently is I can't manage to make my application click :V.
Well, you don't assign a key binding to the "V" key. You define the binding for "W" twice.
Having said that your code is still incorrect and will cause you problems in the future:
you are adding two components to the BorderLayout.CENTER
components should be added to the frame BEFORE the frame is made visible
you are using the wrong InputMap
From the tutorial given to you in your last question there are 3 InputMaps. The default InputMap will only work when the component has focus. In your incorrect example is just happens that the label does have focus. However, if you add more components it will likely not retain focus.
In the case of a game the easiest way to make sure you game responds to the KeyStroke is to bind the KeyStroke to the InputMap of the JRootPane of the frame. Then it doesn't matter which component on the frame has focus, the Action will be invoked.
So your code should be something like:
JRootPane rootPane = frame.getRootPane();
InputMap im = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(KeyStroke.getKeyStroke('v'), "OFF");
rootPane.getActionMap().put("OFF", OFF);
im.put(KeyStroke.getKeyStroke('w'), "upAction");
rootPane.getActionMap().put("upAction", ON);
im.put(KeyStroke.getKeyStroke('s'), "downAction");
rootPane.getActionMap().put("downAction", OFF);
There is no need for the JLabel.
Related
So I want to make some kind of a JLabel that will appear and disappear after a few seconds once certain components are clicked. I used Swing Timer.
Here is my method which is handling this JLabel
`
public void Clicked(String dialog) {
if(isStarted == true) { //Checking if any other component is clicked
dialogue.setText(dialog);// setting text to the label which is the method argument
}
isStarted = false;
t = new Timer(2500,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialogue.setText("");// disappearing the label after 2.5 seconds
}
});
t.start();
t.setRepeats(false);
isStarted = true;
}
`
It actually works fine but when I click 2 components at once, it kinda starts acting weirdly.
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Concurrency in Swing section.
We don't make a JLabel disappear. We change the text of the JLabel to blank.
I created a simple GUI to demonstrate how to use Swing Timers.
After you press the "Display" JButton, the following text is displayed.
After 2.5 seconds, the following text is displayed.
After 2.5 seconds, the text is cleared.
The "trick" is setting a boolean in the original ButtonListener that causes the actionPerformed method to ignore repeated JButton presses. The entire process runs from start to finish no matter how many times you press the JButton while the process is running.
Here's the complete runnable code. I made the additional class an inner class so I could post the code as one block.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class DisappearingJLabelGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DisappearingJLabelGUI());
}
private JLabel textLabel;
#Override
public void run() {
JFrame frame = new JFrame("Disappearing JLabel GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
textLabel = new JLabel(" ");
panel.add(textLabel);
JButton button = new JButton("Display");
button.addActionListener(new ButtonListener());
panel.add(button);
return panel;
}
public class ButtonListener implements ActionListener {
private boolean isRunning;
public ButtonListener() {
this.isRunning = false;
}
#Override
public void actionPerformed(ActionEvent event) {
if (!isRunning) {
isRunning = true;
textLabel.setText("Now, you see it.");
Timer timer = new Timer(2500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
Timer timer = (Timer) event.getSource();
timer.stop();
textLabel.setText("Now, you don't.");
timer = new Timer(2500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
Timer timer = (Timer) event.getSource();
timer.stop();
textLabel.setText(" ");
isRunning = false;
}
});
timer.start();
}
});
timer.start();
}
}
}
}
I'm making a program that has a popup menu with two buttons, one of which should close the popup menu, but I have no idea how to do that and googling hasn't gone too well.
I've tried using popup.hide() but then the menu wouldn't come back, despite doing so when I tried just moving the popup. It also required me to put a SuppressWarning in that case and it took a few seconds for it to close at all. Is there any better way of doing it?
I'm not sure what kind of code is relevant, but here's the relevant buttons and their roles in this(I skipped all the creating the GUI parts that didn't seem relevant, everything looks good and I know that the buttons are working):
package test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
interface CustomButton {
JButton create();
void react(JPopupMenu popup, JFrame frame);
}
class ErrandsButton implements CustomButton {
private JButton errands = new JButton("Errands");
public JButton create() {
return errands;
}
public void react(JPopupMenu popup, JFrame frame) {
errands.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
popup.show(frame, 120, 65);
}
});
}
}
class Test {
static JFrame frame = new JFrame("List");
static CustomButton errands = new ErrandsButton();
static JButton cancelTask = new JButton("Cancel");
static JPopupMenu popup = new JPopupMenu();
static void cancelTask() {
cancelTask.addActionListener(new ActionListener() {
#SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
popup.hide();
}
});
}
public static void main(String args[]) {
createInterface();
cancelTask();
errands.react(popup, frame);
}
static void createInterface() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
JPanel popup1 = new JPanel();
JPanel button = new JPanel();
popup1.add(cancelTask);
popup.add(popup1);
frame.add(popup);
button.add(errands.create());
frame.getContentPane().add(BorderLayout.CENTER, button);
frame.setVisible(true);
}
}
Use popup.setVisible(true) and popup.setVisible(false).
frame.add(popup); is the problem. Do not add a JPopupMenu to a Container. Instead, use setComponentPopupMenu.
Alternatively, you could do the work yourself by adding a MouseListener whose mousePressed, mouseReleased and mouseClicked methods call isPopupTrigger and show. (It is vital that you do this in all three of those methods—different platforms have different conditions for showing popup menus.)
But really, using setComponentPopupMenu is easier.
I have written this code however I am having trouble with one aspect I wish to code into it. I want to make the green square change size when I press one of the three buttons I have so when I press the button 'small' the square changes size to small e.g. 100 and when I press the button 'medium' it changes size to medium e.g. 400. This is my code so far:
package Lab2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
FilledFrame frame = new FilledFrame();
frame.setVisible( true );
}
}
class FilledFrame extends JFrame {
int size = 400;
public FilledFrame()
{
JButton butSmall = new JButton("Small");
JButton butMedium = new JButton("Medium");
JButton butLarge = new JButton("Large");
JButton butMessage = new JButton("Say Hi");
SquarePanel panel = new SquarePanel(this);
JPanel butPanel = new JPanel();
butPanel.add(butSmall);
butPanel.add(butMedium);
butPanel.add(butLarge);
butPanel.add(butMessage);
add(butPanel, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
setSize( size+100, size+100 ); } }
class SquarePanel extends JPanel {
FilledFrame theApp;
SquarePanel(FilledFrame app)
{
theApp = app;
}
public void paintComponent ( Graphics g)
{
super.paintComponent(g);
g.setColor(Color.green);
g.fillRect(20, 20, theApp.size, theApp.size);
}
}
class buttonHandler implements ActionListener {
FilledFrame theApp;
int size;
public buttonHandler(FilledFrame app, int size) {
theApp = app;
this.size = size;
}
#Override
public void actionPerformed (ActionEvent e){
theApp.setSize(this.size, this.size);
}
}
As I don't see any event listeners for your buttons, I assume this is all the code you have. Your buttons will not do anything unless you tell them to do it. You need to add event listeners, and through that change the size and update the panel.
Example:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
theApp.size = 200;
frame.getContentPane().repaint();
//OR frame.repaint();
}
});
EDIT:
The problem with using the button handler class is you would need to find which buttton was pressed, instead its easier to use the way I showed above. I edited the code above, try copy pasting to one of the buttons.
Im trying to change the color of a JPanel using the JColorChooser when the "apply" button is pressed, but i'm not sure how to actually make the color change. How would I do that?
private class SetColorAction implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
setColor(DrawnView.colorChooser.getColor());
//Color color;
}
}
^ is one in class while the stuff below is in a different one
public void setColor(Color color){
this.setBackground(color);
}
public ViewUserActions() {
this.applyColorBtn.setVisible(false);
this.discardChangesBtn.setVisible(false);
this.editBtn.addActionListener((ActionEvent ae) -> {
if (this.editBtn.isSelected()) {
this.applyColorBtn.setVisible(true);
this.discardChangesBtn.setVisible(true);
} else {
this.applyColorBtn.setVisible(false);
this.discardChangesBtn.setVisible(false);
}
});
this.applyColorBtn.addActionListener(new SetColorAction());
this.discardChangesBtn.addActionListener(new SetColorAction());
this.applyColorBtn.addActionListener(new GetInfoAction());
this.discardChangesBtn.addActionListener(new GetInfoAction());
}
Here is a short demo of changing the background color of a JPanel by a button click.
This cam also give you an idea of mcve , doing just that and nothing more:
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Frame extends JFrame {
JPanel panel;
Color[] colors = new Color[] {Color.YELLOW, Color.CYAN, Color.LIGHT_GRAY, Color.WHITE};
int counter =0;
Frame() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JButton button = new JButton("Change color");
button.addActionListener( ae -> setColor());
add(button, BorderLayout.NORTH);
panel = new JPanel();
panel.add(new JLabel ("Test panel"));
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
}
private void setColor() {
panel.setBackground(colors[counter++]);
counter = (counter >= colors.length) ? 0 : counter;
}
public static void main(String[] args) {
new Frame();
}
}
Try this simple source code:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ColorChooserExample {
private static JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
runColorChangerApp();
}
});
}
private static void runColorChangerApp() {
frame = new JFrame();
frame.setTitle("JPanel Color Changer");
frame.getContentPane().setLayout(new GridLayout(1, 1));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(400, 250, 400, 300);
frame.getContentPane().add(getHomePanel());
frame.setVisible(true);
}
private static JPanel getHomePanel() {
final JPanel panel = new JPanel();
panel.setOpaque(true);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
//Fire on Mouse Right Click
if(evt.getButton() == MouseEvent.BUTTON3) {
frame.setTitle("Listened Right Click");
Color initColor = panel.getBackground();
Color choosedColor = JColorChooser.showDialog(panel,
"Choose JPanel Background Color", initColor);
frame.setTitle("JPanel Color Changer");
panel.setBackground(choosedColor);
}
}
});
return panel;
}
}
I am going to assume by the "apply" button, you mean the "ok" button of the JColorChooser dialog.
In that case, here is an optimal solution:
Color r = JColorChooser.showDialog(null, "Select Color for JPanel", Color.CYAN);
//null is the parent Component for the dialog,The String is the title, and cyan
//will be the initially selected Color.
if(r==null)
{ //perform whatever you would do if the user cancels the dialog }
else
{ jpanelobj.setBackground(r); }
This should do the trick, but here's my advice for you.
JColorChooser extends JComponent, and this means that IT CAN BE ADDED AS A COMPONENT to a Frame, giving you control such as adding ChangeListeners to instantaneously detect a Color change. Another method you may find helpful is:
JDialog jd=JColorChooser.createDialog(Component c,
String title,
boolean modal,
JColorChooser chooserPane,
ActionListener okListener,
ActionListener cancelListener);
Where c is the parent component-leave it null, usually.
The title is the dialogs Title modal is a boolean value which specifies whether you want the program to wait for the
the dialog to be responded to by the user before continuing the program thread
execution.
chooserPane is the JColorChooser you want as the main chooser->eg:
new JColorChooser(Color.GREEN);
okListener and cancelListener are action listeners for ok and cancel buttons.
This method gives you control over the dialogs buttons, display, etc.
I need to display a swing popup with my custom component. The popup should stay visible, until I hide it myself, but shouldn't get focus.
I have a code written by some other developer that does it in the following way:
popupMenu = new JPopupMenu();
popupMenu.add(myCustomComponent, BorderLayout.CENTER);
popupMenu.setFocusable(false);
popupMenu.setVisible(true);
popupMenu.show(parentComponent, x, y);
This seems to work, but has a bug - when the popup is visible, first mouse click outside the component is consumed by the popup. So I need to click twice to set focus to another component.
How can I fix it? Or what is correct way to make the popup?
UPDATE
At last I've managed to reproduce my problem in short code fragment. Thanks to Guillaume Polet for giving me a starting point.
Here's the code:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class TestJPopup {
protected void initUI() {
JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField textField = new JTextField("Some text field");
frame.add(textField, BorderLayout.WEST);
final JButton buttonToHit = new JButton("Hit me");
buttonToHit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
}
});
frame.add(buttonToHit);
frame.setSize(200, 100);
frame.setVisible(true);
final JPopupMenu popup = new JPopupMenu();
popup.add(new JLabel("<html>Hey!<br>I'm the popup window!</html>"),
BorderLayout.NORTH);
popup.setFocusable(false);
popup.setVisible(true);
popup.show(textField, 60, 60);
// I want to activate popup when user clicks in the text field
textField.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (popup != null) {
popup.show(textField, 60, 60);
}
}
});
}
public static void main(String[] args) throws Exception {
Class lnfClass = Class.forName("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", true,
Thread.currentThread().getContextClassLoader());
LookAndFeel feel = (LookAndFeel) lnfClass.newInstance();
UIManager.setLookAndFeel(feel);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestJPopup().initUI();
}
});
}
}
Two critical moments:
Windows look and feel used (with default not reproducible)
Mouse listener attached to text field in main frame
Not an answer, but just an example SSCCE in which I can't currently reproduce the behaviour you described. Maybe start from this code, try to reproduce the error and the edit your post with modified non-working code.
import java.awt.BorderLayout;
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.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestJPopup {
protected void initUI() {
JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel leftLabel = new JLabel("Left");
frame.add(leftLabel, BorderLayout.WEST);
final JButton buttonToHit = new JButton("Hit me");
buttonToHit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
}
});
frame.add(buttonToHit);
frame.setSize(500, 400);
frame.setVisible(true);
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new JLabel("<html>A Custom<br>component<br>made to<br> simulate <br>your custom component</html>"),
BorderLayout.NORTH);
JTextField textfield = new JTextField(30);
popupMenu.add(textfield);
popupMenu.setFocusable(false);
popupMenu.setVisible(true);
popupMenu.show(leftLabel, 20, 20);
// Let's force the focus to be in a component in the popupMenu
textfield.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestJPopup().initUI();
}
});
}
}
Not a solution, but:
Looks like a bug to me, even a plain componentPopup exhibits the same mis-behaviour (in winLAF and Nimbus, not in Metal):
JTextField field = new JTextField("some popup owner");
JPopupMenu menu = new JPopupMenu();
menu.add("dummy");
field.setComponentPopupMenu(menu);
Action action = new AbstractAction("hit me!") {
#Override
public void actionPerformed(ActionEvent e) {
LOG.info("got hit!");
}
};
JComponent content = new JPanel();
content.add(new JButton(action));
content.add(field);
for quick research and/or for future readers,
this issue is reproducible and presented for,
a) JPopup
b) JMenu
tested on jdk1.6.0_25 and jdk1.7.0_04,
same issue on WinXp and Win7,
for Look and Feel to SystemLookAndFeel / WindowsLookAndFeel,
Here's a possible workaround with JWindow instead of JPopupMenu, that was proposed by mKorbel in comments:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestJPopup {
protected void initUI() {
final JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField textField = new JTextField("Some text field");
frame.add(textField, BorderLayout.WEST);
final JButton buttonToHit = new JButton("Hit me");
buttonToHit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
}
});
frame.add(buttonToHit);
frame.setSize(200, 70);
frame.setVisible(true);
final JWindow popup = new JWindow();
popup.getContentPane().add(new JLabel("<html>Hey!<br>I'm the popup window!</html>"),
BorderLayout.NORTH);
popup.setLocation(frame.getLocation().x + 60, frame.getLocation().y + 60);
popup.pack();
popup.setFocusable(false);
popup.setVisible(true);
// I want to activate popup when user clicks in the text field
textField.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
if (popup != null) {
popup.setVisible(true);
popup.setLocation(frame.getLocation().x + 60, frame.getLocation().y + 60);
popup.toFront();
}
}
});
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
if (popup != null) {
popup.setVisible(false);
}
}
});
}
public static void main(String[] args) throws Exception {
Class lnfClass = Class.forName("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", true,
Thread.currentThread().getContextClassLoader());
LookAndFeel feel = (LookAndFeel) lnfClass.newInstance();
UIManager.setLookAndFeel(feel);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestJPopup().initUI();
}
});
}
}
Here is the magic line that fixes the problem:
UIManager.put("PopupMenu.consumeEventOnClose", Boolean.FALSE);
I found this after looking into the source code for the BasicPopupMenuUI class. Apparently this behaviour is a deliberate design choice according to the following comments in the code, but it sure feels like a bug to me.
// Ask UIManager about should we consume event that closes
// popup. This made to match native apps behaviour.
By the way, it happens in Java 5 and 6 too.