I am quite new to Java and only after researching and googling and reading many answers, I am posting this. I am kinda lost. A little guidance would be of great help. The following is a method from a class that implements the "ActionListener" interface. What I am trying to do is this: There is a button which one clicked should open a new window with two options in the form of two Radio Buttons. I need to know the Radio Button which was selected for further use in my code. I declared, the "scoreOption" variable as a class variable and static, and then attempt to update it in the "actionPerformed" abstract method. But when I refer to it (after the method call), the value stays the same - null, or whatever I set it to initially. Here is the code:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class StartEvents implements ActionListener {
StartPanel startingPanel;
static String scoreOption;
public StartEvents(StartPanel startPanel) {
startingPanel = startPanel;
}
// Scoring System Window - 1
public void scoringSystem() {
startingPanel.scoringSystem.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
Panel scoringSystemPanel = new Panel();
JFrame scoreSystemFrame = scoringSystemPanel.frame(150, 250, "Scoring System", 2, true);
JPanel scoreSystemPanel = scoringSystemPanel.panel(Color.lightGray);
JButton confirmSelection = scoringSystemPanel.button(40, 20, "Confirm");
JRadioButton scoreSystem1 = scoringSystemPanel.radioButton("Option 1: Same Points Per Hit");
scoreSystem1.setActionCommand("Option 1");
JRadioButton scoreSystem2 = scoringSystemPanel.radioButton("Option 2: Unique Points Per Hit");
scoreSystem2.setActionCommand("Option 2");
ButtonGroup scoreSys = new ButtonGroup();
scoreSys.add(scoreSystem1);
scoreSys.add(scoreSystem2);
scoreSystemFrame.getContentPane().add(scoreSystemPanel);
scoreSystemPanel.add(scoreSystem1);
scoreSystemPanel.add(scoreSystem2);
scoreSystemPanel.add(confirmSelection);
// Get Selection Event
// Option 1
scoreSystem1.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
if (scoreSystem1.isSelected()) {
scoreOption = scoreSystem1.getActionCommand();
}
}
});
// Option 2
scoreSystem2.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
if (scoreSystem2.isSelected()) {
scoreOption = scoreSystem2.getActionCommand();
}
}
});
// Confirm Event
confirmSelection.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
scoreSystemFrame.dispose();
}
});
}
});
}
Main Game Class where the method scoringsystem is called.
import java.util.ArrayList;
public class Game {
public static void main(String[] args) {
StartPanel startingPanel = new StartPanel();
startingPanel.makeStartPanel();
StartEvents starter = new StartEvents(startingPanel);
starter.rulesButton();
starter.exitButton();
starter.highScoresButton();
ArrayList<Integer> dimensions = starter.boardSizeSelector();
// Problem Zone
System.out.println(StartEvents.scoreOption);
starter.scoringSystem();
System.out.println(StartEvents.scoreOption);
// The two values of scoreOption should be different
String[] playPanelDetails = {"970", "Player 1", "450"};
// Final Start of the Game
starter.startGameButton(playPanelDetails, dimensions);
}
}
Furthermore, could you please let me know regarding the following questions:
Implementing "ActionListener" within another "ActionListener" is recommended? Good Practice?
Can there only be one declaration of the "actionPerformed" method or can it be overloaded too?
Is it possible to get a return value from "actionPerformed" method?
I would be really grateful if even some hints could be provided. I really tried a lot and only then posting it here. Thank you very much in advance.
Small Edit: When I "System.out.println" the "actioncommand" there itself, it does work perfectly, printing in the console. But not when I try to update the class variable and then try to print it after the method call. Dunno if this helps.
JFrames are not modal -- you create one and display it, it does not block the code flow, and so you are extracting the value of scoreOption right as the JFrame is being displayed and before the user has had any chance to change it. You need to use a modal dialog such as a JDialog that is created as a modal dialog or use a JOptionPane (which is actually just a modal JDialog under the hood). This will block the flow of code so that you extract the data only after it has been changed by the user.
An example that proves the point:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooGui01 extends JPanel {
private String frameTest = "";
private String dialogTest = "";
private JFrame mainFrame = new JFrame("Main GUI");
private JFrame subFrame;
private JDialog dialog;
public FooGui01() {
JButton showFrameBtn = new JButton("Show JFrame");
showFrameBtn.addActionListener(e -> {
changeTest1WithJFrame();
System.out.println("frameTest: " + frameTest);
});
JButton showDialogBtn = new JButton("Show JDialog");
showDialogBtn.addActionListener(e -> {
changeTest2WithModalDialog();
System.out.println("dialogTest: " + dialogTest);
});
JPanel panel = new JPanel();
panel.add(showDialogBtn);
panel.add(showFrameBtn);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(panel);
mainFrame.pack();
mainFrame.setLocationByPlatform(true);
mainFrame.setVisible(true);
}
public void changeTest1WithJFrame() {
if (subFrame == null) {
subFrame = new JFrame("Frame");
JButton button = new JButton("Press me");
button.addActionListener(e -> {
frameTest = "Hello World and frameTest";
subFrame.setVisible(false);
});
JPanel panel = new JPanel();
panel.add(button);
subFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
subFrame.add(panel);
subFrame.pack();
subFrame.setLocationByPlatform(true);
}
subFrame.setVisible(true);
}
public void changeTest2WithModalDialog() {
if (dialog == null) {
dialog = new JDialog(mainFrame, "Dialog", Dialog.ModalityType.APPLICATION_MODAL);
JButton button = new JButton("Press me");
button.addActionListener(e -> {
dialogTest = "Hello World and dialogTest";
dialog.setVisible(false);
});
JPanel panel = new JPanel();
panel.add(button);
dialog.add(panel);
dialog.pack();
dialog.setLocationByPlatform(true);
}
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new FooGui01());
}
}
If you run the code, when you show the sub JFrame, the test text is displayed immediately in the console before the dialog has been dealt with. If you press the button to show the dialog, the test text display is delayed until after the button has been pushed, changing the text.
Pressing the frame button twice will finally show the correct text since the text was set by the first time it was displayed.
A JDialig is just like a JFrame. That is you add components to it like you do any frame.
The difference is that you can make a JDialog modal. This means that when you use:
dialog.setVisible(true);
System.out.println("here");
The code after the setVisible(...) statement will not be executed until the dialog is closed. It also means you can't click on the parent JFrame until the dialog is closed.
An easy way to create a modal JDialog is to use a JOptionPane. It has some predefined methods that make prompting for user input easy.
For example in your case you could do something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE extends JPanel
{
private int scoringOption = -1;
public SSCCE()
{
JButton button = new JButton("Change Points Option");
add(button);
button.addActionListener((e) -> displayOptionDialog());
}
private void displayOptionDialog()
{
Window window = SwingUtilities.windowForComponent( this );
// Custom button text
Object[] options = {"Option 1: Same Points Per Hit", "Option 2: Unique Points Per Hit"};
scoringOption = JOptionPane.showOptionDialog(
window,
"Select your scoring option:",
"Scoring Option",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
null);
System.out.println( scoringOption );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
The above is also an example of an "MRE". The code is simple and contained in a single class that you can copy/paste/compile and test.
Read the section from the Swing tutorial on How to Use Dialogs for more examples of using a JOptionPane.
If you really want to use radio buttons, then you can create a panel with the radio buttons and display them on the option pane using the showConfirmDialog(...) method. When the dialog closes you would then need to get the action command from the ButtonModel of the ButtonGroup.
See: how to set & manage the layout of JOptionPane for a basic example of this approach to get you started.
Related
I have a JDialog which can generate another one. The two JDialogs have the property setAlwaysOnTop(true) and aren't modal. The second Jdialog generated from the first one appears always behind. I would like it to appear in front.
I tried several things : toFront(), requestFocus(), etc..
Here a short example to reproduce the problem:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
public class SwingTester {
public static void main(String[] args) {
createWindow();
}
private static void createWindow() {
final JDialog modelDialog = createDialog();
modelDialog.setVisible(true);
}
private static JDialog createDialog(){
final JDialog modelDialog = new JDialog();
modelDialog.setBounds(132, 132, 300, 200);
Container dialogContainer = modelDialog.getContentPane();
dialogContainer.setLayout(new BorderLayout());
JPanel panel1 = new JPanel();
JButton okButton = new JButton("Ok");
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final JDialog modelDialog = createDialog();
modelDialog.setVisible(true);
}
});
panel1.add(okButton);
dialogContainer.add(panel1, BorderLayout.SOUTH);
modelDialog.setAlwaysOnTop(true);
return modelDialog;
}
After a click on the OK button, we see another dialog appearing behind the current one. The new dialog has the focus but is still behind
Actually, I tried your code, and it is no problem appears. If you want to see it too clearly, create dialog with random location. In every click, new dialog is random place on the top.
modelDialog.setBounds(new Random().nextInt(400), new Random().nextInt(400), 300, 200);
But my suggestion is create dialog as modal, in addition to set old one as parent.
I have a program which displays two buttons and changes the image of one of the buttons on roll over. I am getting an error on my
press.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
part, And it looks like this: The method setDefaultCloseOperation(int) is undefined for the type ButtonClass. Even with the exit on close commented out there are more errors, please help.
Main class (with error):
package Buttons;
import javax.swing.JFrame;
public class Main_buttons{
public static void main(String[] args) {
ButtonClass press = new ButtonClass();
press.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
press.setSize(300,200);
press.setVisible(true);
}
}
ButtonClass class:
package Buttons;
import java.awt.FlowLayout; //layout proper
import java.awt.event.ActionListener; //Waits for users action
import java.awt.event.ActionEvent; //Users action
import javax.swing.JFrame; //Window
import javax.swing.JButton; //BUTTON!!!
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane; //Standard dialogue box
public class ButtonClass extends JButton {
private JButton regular;
private JButton custom;
public ButtonClass() { // Constructor
super("The title"); // Title
setLayout(new FlowLayout()); // Default layout
regular = new JButton("Regular Button");
add(regular);
Icon b = new ImageIcon(getClass().getResource("img.png"));
Icon x = new ImageIcon(getClass().getResource("swag.png"));
custom = new JButton("Custom", b);
custom.setRolloverIcon(x); //When you roll over the button that says custom the image will change from b to x
add(custom);
Handlerclass handler = new Handlerclass();
regular.addActionListener(handler);
custom.addActionListener(handler);
}
private class Handlerclass implements ActionListener { // This class is inside the other class
public void actionPerformed(ActionEvent eventvar) { // This will happen
// when button is
// clicked
JOptionPane.showMessageDialog(null, String.format("%s", eventvar.getActionCommand()));//Opens a new window with the name of the button
}
}
}
I have searched everywhere for this problem and found nothing. Please tell me how to resolve this issue about exiting my window.
Thanks!
You're a little confused as you're creating a class that extends JButton, and calling setVisible(true) on it as if it were a top-level window such as a JFrame or JDialog, and that doesn't make sense. Since it isn't a top-level window it also makes sense to not have a default close operation or understand what that means.
I suggest that you call this method only on top-level windows such as on a JFrame or JDialog and the like. As a side recommendation, I usually avoid setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); and instead more often do setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); which gives it a little more flexibility.
Edit: actually, just change your class to extends JFrame not extends JButton.
Make sure your image path to your resources is correct. For example:
that method is defined for JFrame, not JButton. You're calling it on an instance of a class that extends JButton
The JFrame.Exit_on_close must be used in a JFrame, and you are extending from JButton.
To set a JButton to close a JFrame its something like this.
public class MyClass extends JFrame implements ActionListener{
private JButton button = new JButton("Button");
private JPanel panel = new JPanel();
public static void main(String args[]) {
new MyClass();
}
public MyClass() {
setSize(300, 300);
button.addActionListener(this);
panel.add(button);
add(panel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.dispose();
}
}
I am working on a school assignment. We have 10 buttons, lets say first 10 letters of alpahabet. For exmaple when you click the 'A' button, character 'A' gets added to jLabel.
I know I could write new function for every button, but is there any better way? Like I pass the letter by argument and use only 1 function? Or is somehow possible to detect what button called my event handler and add letter according to that?
Yes, you can use actionCommand. Here you have examples doing that. How to use Buttons.
Example:
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.JPanel;
public class ButtonExample {
private JPanel panel;
private JLabel label;
public ButtonExample(){
panel = new JPanel();
label = new JLabel(" ");
ActionListener listener = new MyActionListener();
JButton buttonA = new JButton("Press me A");
buttonA.setActionCommand("A");
buttonA.addActionListener(listener);
JButton buttonB = new JButton("Press me B");
buttonB.setActionCommand("B");
buttonB.addActionListener(listener);
JButton buttonC = new JButton("Press me C");
buttonC.setActionCommand("C");
buttonC.addActionListener(listener);
panel.add(buttonA);
panel.add(buttonB);
panel.add(buttonC);
}
private class MyActionListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
String text = (label.getText() == null || label.getText().isEmpty() )?"":label.getText();
label.setText(text+e.getActionCommand());
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Textfield example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(Boolean.TRUE);
ButtonExample buttonExample =new ButtonExample();
frame.add(buttonExample.panel,BorderLayout.CENTER);
frame.add(buttonExample.label,BorderLayout.NORTH);
//Display the window.
frame.pack();
frame.setVisible(Boolean.TRUE);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
You can do like
Yourlabel.setText(yourbutton.getText());
It will place your button name say A to your desired label!
This is just a hint you can get an idea.
enter image description hereI'm a new programmer and I'm working on a text adventure that uses dropdown boxes (choice) as an input device. I have an itemListener on the first box that populates the members of the 2nd with the members that can be added. The player is then allowed to click the submit button and the first box is reset to the first item on the list and the second box is supposed to be cleared. When I run the program, the first time it reacts exactly as planned. The 2nd time I try to input something using the drop down boxes, the dropdown box doesn't respond. I put a marker inside the itemListener to see if it was even triggering to find out that it wasn't. I feel like I've tweeked the program in every way imaginable but I have no idea what is causing this issue. If I toggle between the items in the drop down box a few times the itemListener starts to respond again.
This is a representation of my issue I threw together.
import java.awt.Choice;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
public class gui implements ActionListener
{
private static JTextPane outputField = new JTextPane();
private static JPanel mainPanel = new JPanel(new GridBagLayout());
private Choice commandDropDown = new Choice();
private Choice itemDropDown = new Choice();
private JButton submitButton = new JButton();
public gui()
{
JFrame frame = new JFrame("test");
mainPanel.setSize(450,585);
commandDropDown = buildCommandBox(commandDropDown);
commandDropDown.setBounds(100, 15, 100, 40);
itemDropDown.setBounds(200, 15, 100, 40);
submitButton.setText("submit");
submitButton.setBounds(15, 15, 100, 40);
submitButton.addActionListener(this);
frame.add(commandDropDown);
frame.add(itemDropDown);
frame.add(submitButton);
frame.setResizable(false);
frame.pack();
frame.setSize(300, 300);
//frame.setLayout(null);
//frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
itemDropDown.removeAll();
commandDropDown.select(0);
}
private Choice buildCommandBox(Choice custoChoi)
{
final Choice c = new Choice();
c.addItem("choices");
c.addItem("Option1");
c.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent ie)
{
System.out.println("the action event for the command"
+ "box is working.");
if(c.getSelectedItem().equals("Option1"))
{
itemDropDown.addItem("things");
itemDropDown.addItem("stuff");
}
}
});
return c;
}
}
Hopefully these pictures clear up any confusion about my post.
http://imgur.com/a/h9oOX#0
In my opinion, your buildCommandBox( Choice custoChoi) is wrong, it should be something like that:
private Choice buildCommandBox(final Choice custoChoi) {
custoChoi.addItem("choices");
custoChoi.addItem("Option1");
custoChoi.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent ie) {
System.out.println("the action event for the command" + "box is working.");
if (custoChoi.getSelectedItem().equals("Option1")) {
itemDropDown.addItem("things");
itemDropDown.addItem("stuff");
}
}
});
return custoChoi;
}
I would recommand to use JComboBox instants of Choice, if Swing is allowed.
I'm doing some very basic coding, just trying to learn the basic concepts behind keybinding. It all seems very straightforward but there's something wrong with my logic or structure that is keeping my code from executing the way I want it to.
Here is my code
public class Board {
ButtonListener buttonlistener;
EnterAction enterAction;
public Board(){
JFrame skeleton = new JFrame();
skeleton.setDefaultCloseOperation(EXIT_ON_CLOSE);
skeleton.setVisible(true);
skeleton.setSize(400, 400);
buttonlistener = new ButtonListener();
enterAction = new EnterAction();
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
JButton button = new JButton("button");
button.addActionListener(buttonlistener);
panel.add(button);
skeleton.add(panel);
panel.getInputMap().put(KeyStroke.getKeyStroke("s"), "doEnterAction");
panel.getActionMap().put("doEnterAction", enterAction);
}
public class ButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("button pressed");
}
}
public class EnterAction extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("enter pressed");
}
}
public static void main(String[] args){
new Board();
}
So, it should be pretty simple. As you can see I'm just trying to make it print out "enter pressed" whenever you press enter, but it isn't printing out anything (unless you click the button also shown in the code above). Also, in eclipse, the EnterAction class is underlined in yellow, I think it may not be being called right, but I don't know why it wouldn't be.
Any help is appreciated, thanks.
Change
panel.getInputMap().put(KeyStroke.getKeyStroke("s"), "doEnterAction");
To
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"), "doEnterAction");
Also
skeleton.setDefaultCloseOperation(EXIT_ON_CLOSE);
the parameter must be JFrame.EXIT_ON_CLOSE or just put number 3.
The immediate issue I can see is with the following statement
panel.getInputMap().put(KeyStroke.getKeyStroke("s"), "doEnterAction");
KeyStroke.getKeyStroke("s") is going to return null. The requirements for the String passed to this method are very particular and not well documented (IMHO).
You could use KeyStroke.getKeyStroke("S") instead, but I prefer to use KeyStroke.getKeyStroke(KeyEvent.VK_S, 0) as there is no chance of ambiguity in the statement.
I would also recommend that you define the focus boundaries as well for the input map...
Instead of panel.getInputMap(), try using panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) to ensure that the key event will be triggered if the window is focused
Take a look at JComponent#getInputMap for more details.
If you haven't already done so, you should also take a look at How to use Key Bindings
I think Azad and MadProgrammer are correct, I only had to make one more simple change in addition to what they recommended to get the program running. I have numbered the three items for you as a comment in the code: (copy and paste and you are good to go).
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Board {
ButtonListener buttonlistener;
EnterAction enterAction;
public Board() {
JFrame skeleton = new JFrame();
//Change #1 below
skeleton.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
skeleton.setVisible(true);
skeleton.setSize(400, 400);
buttonlistener = new ButtonListener();
enterAction = new EnterAction();
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
JButton button = new JButton("button");
button.addActionListener(buttonlistener);
panel.add(button);
skeleton.add(panel);
//Change #2 below
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke("S"), "doEnterAction");
panel.getActionMap().put("doEnterAction", (Action) enterAction);
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("button pressed");
}
}
public class EnterAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("enter pressed");
}
}
public static void main(String[] args) {
new Board();
}
//Change #3 below
}
here is the screenshot: