I am trying to get my action listener to show a picture when the button is clicked, but hide it until then. I also need it to only allow me to click it once. I have the button in a separate class that extends JButton so I'm unsure if that is affecting it. When I add the image using the action listener, it doesn't show the image whether I click it or not. When I add it to the button, it shows it before it is clicked(as expected). What is the best way to hide the image until the button is clicked? FYI, there are many instances of this button created, if that makes a difference.
This is the button class
import javax.swing.*;
public class EmptyButton extends JButton
{
public EmptyButton()
{
//add image to button
ImageIcon emptyImage = new ImageIcon("Empty.jpg");
JLabel empty = new JLabel(emptyImage);
}
}
This is the action listener
private class emptyButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
game.noTreasureFound();
treasuresFoundTextField.setText(String.valueOf(game.getTreasuresFound()));
treasuresLeftTextField.setText(String.valueOf(20-game.getTreasuresFound()));
triesLeftTextField.setText(String.valueOf(game.getTriesLeft()));
}
}
use JLabel#setVisible(true) to make image visible on click. Initially call setVisible(false) to hide it
use JButton#setEnabled(false) to disable button after click
Related
I didn't like the standard arrow button of the JComboBox, because it didn't fit well in my GUI. So I changed it. To do this, I wrote a class, which is extending BasicComboUI. In the regular case, everything is like I am expecting it. But as soon as I am disabling the button, it stays the way it is, which means that the button doesn't get the grey background color anymore. Instead, the left part of the list does. So I would like to know, if there is a way to define or to modify the disabling-behavior of the arrow button.
Here is my current code:
public class CustomArrowUI extends BasicComboBoxUI{
private static Color buttonBackground;
private static Color borderBox;
private static Color arrowColor;
private static Color buttonBorder;
public static ComboBoxUI createUI(JComponent c, Color buttonBackground, Color borderBox, Color arrowColor, Color buttonBorder)
{
CustomArrowUI.buttonBackground = buttonBackground;
CustomArrowUI.borderBox = borderBox;
CustomArrowUI.arrowColor = arrowColor;
CustomArrowUI.buttonBorder = buttonBorder;
return new CustomArrowUI();
}
#Override
protected JButton createArrowButton()
{
JButton button = new BasicArrowButton(BasicArrowButton.SOUTH, buttonBackground, borderBox, arrowColor, buttonBorder);
LineBorder border = new LineBorder(buttonBorder, 1);
button.setEnabled(false);
button.setBorder(border);
return button;
}}
What I could do is setting the background light grey as default, and change the color in the ActionListener of the previous button, which is enabling my JComboBox. But I kinda don't like this solution. I would prefer to do it directly in my CustomArrowUI
I found one short way to solve this. I added a ChangeListener to my arrow button, which is checking if the button is enabled or not, and coloring the button:
#Override
protected JButton createArrowButton()
{
final JButton button = new BasicArrowButton(BasicArrowButton.SOUTH, buttonBackground, borderBox, arrowColor, buttonBorder);
LineBorder border = new LineBorder(buttonBorder, 1);
button.setEnabled(false);
button.setBorder(border);
button.addChangeListener(new ChangeListener(){
#Override
public void stateChanged(ChangeEvent arg0) {
if(button.isEnabled())
button.setBackground(Color.WHITE);
else
{
button.setBackground(ColorPalette.LIGHT_GREY);
button.setBorder(new LineBorder(ColorPalette.LIGHT_GREY, 1));
}
}
});
return button;
}
Above I changed the background of the button and the border color too make it look like the arrow is part of the JComboBox, and not like a separate button inside of it.
Since the disabling-behavior is inheritet from the JComboBox itself (I guess), I don't need to take care if the button is usable or not. All I need to define is the color.
Another important point is to make sure, to call the setEnabled()-method after setting the UI of the JComboBox, if the JComboBox should be disabled by default. Otherwise it will not react initially, and the arrow button will look enabled.
Basically I am making an application that allows you to draw shapes. I am working on a feature that would allow you to "undo a draw". All drawing occurs on the drawing panel. I got the algorithm part of the undo down, move to a stack...., but I can't get the undo button to disable after there are no more shapes to draw in the collection.(can't undo any more )
These are my two collections that I use to store my shapes
//to store shapes that have been drawn
private final List<ShapeColorThickness> myShapesToDraw
//store shapes that have been "undone"
private final Stack<ShapeColorThickness> myUndoShapes;
This is the AbstractAction class used to handle clicks to the undo button.
public class UndoAction extends AbstractAction{
private final DrawingPanel myDrawingPanel;
public UndoAction(String name, DrawingPanel panel) {
super(name);
myDrawingPanel = panel;
//I don't want the button to be enabled in the beginning.
setEnabled(false);
}
#Override
public void actionPerformed(ActionEvent arg0) {
myDrawingPanel.undo();
boolean canUndo = myDrawingPanel.canUndo();
setEnabled(myDrawingPanel.canUndo());
}
}
This is where I initialized the undo button
new JButton(new UndoAction("Undo", myDrawingPanel)
And pertinent code in DrawingPanel.java
public boolean canUndo() {
//if there are no shapes left in shapes drawn, you cannot undo
return !myShapesToDraw.isEmpty();
}
public void undo() {
myUndoShapes.push(myShapesToDraw.remove(myShapesToDraw.size() - 1));
repaint();
}
When I add a Shape and proceed to remove it, the undo button stays enabled. I've been trying to debug this but just cant figure it out. I put a breakpoint next to
boolean canUndo = myDrawingPanel.canUndo();
And saw that it evaluated to false when i pressed the undo button and stepped through the code. But the button still remains enabled. What's even stranger is that the undo button disables itself perfectly fine if i add 2 shapes and remove them both. Does anyone know what this issue could be?
What I think cause the issue was that when i constructed the button with the action, I did something like
JButton button = new JButton(new UndoAction(.....));
And later in some part of my code, I called
button.setEnabled(true);
I am not sure how the setEnabled on the button affects the action enabled state but after i made sure that all calls that affected state came from the Action class, I managed to fix my issue.
help,
my questions are:
why isn't itemStateChanges triggered, I tried to put it in the inner class ButtonHandler and also in RadioButtonHandler Im having trouble with it, what is the right way to do it?
I want to trigger and check the marked JRadioButtons after the user click the "check" button.
What is the right way to check which button was clicked, I feel like comparing the strings is bad programming practise. Maybe using an ID ?
How should I make a "reset" button(start over), I want to uncheck all radio buttons and run the constructor once again.
Thank you for your help !
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class ExamFrame extends JFrame {
static ArrayList<Question> qArrList;
JRadioButton a1,a2,a3,a4;
public ExamFrame() {
super("Quiz");
setLayout(new GridLayout(0, 1));
GridBagConstraints gbc = new GridBagConstraints();
Exam exam = new Exam();
qArrList = exam.getExam();
int count=0;
for(Question q : qArrList){
count++;
JLabel questionLabel = new JLabel(count+". "+q.getQustion()); //swing constant ?
ArrayList<String> ansRand = q.getAllRandomAns();
a1 = new JRadioButton(ansRand.get(0));
a2 = new JRadioButton(ansRand.get(1));
a3 = new JRadioButton(ansRand.get(2));
a4 = new JRadioButton(ansRand.get(3));
add(questionLabel);
add(a1);add(a2,gbc);add(a3);add(a4);
ButtonGroup radioGroup = new ButtonGroup(); //logical relationship
radioGroup.add(a1);radioGroup.add(a2);radioGroup.add(a3);radioGroup.add(a4);
}
//buttons:
JButton checkMe = new JButton("Check Exam");
JButton refresh = new JButton("Start Over");
ButtonHandler handler = new ButtonHandler();
checkMe.addActionListener(handler);
refresh.addActionListener(handler);
add(checkMe);
add(refresh);
}
/** Listens to the radio buttons. */
public class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e) {
if(e.getActionCommand().equals("Start Over")){ //id?
//how to do this?
}
else{
RadioButtonHandler handler = new RadioButtonHandler();
a1.addItemListener(handler);
System.out.println("success?");
}
JOptionPane.showMessageDialog(ExamFrame.this, String.format("You pressed: %s", e.getActionCommand()));
}
public void itemStateChanged(ItemEvent e) //can i add it here?
{
JOptionPane.showMessageDialog(ExamFrame.this, String.format("yes?"));
System.out.println("success!");
}
}
public class RadioButtonHandler implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
JOptionPane.showMessageDialog(ExamFrame.this, String.format("radio state changed"));
}
}
}
why "itemStateChanges" isn't triggered, i tried to put it in the inner
class "ButtonHandler" and also in "RadioButtonHandler" Im having
troubles with it, what is the right way to do it? I want to trigger
and check the marked JRadioButtons after the user click the "check"
button.
ButtonHandler is implemented with ActionListener only:
public class ButtonHandler implements ActionListener{}
The itemStateChanged(ItemEvent) function belongs to ItemListener. This function is triggered if state of a source component to which this listener is registered gets changed. So implement the ItemListener. However, one more thing to note, that JButton doesn't respond to ItemListener but JRadioButton will. Because this Item events are fired by components that implement the ItemSelectable interface. Some example of such components are: check boxes, check menu items, toggle buttons and combo boxes including Radio Buttons as mentioned above.
What is the right way to check which button was clicked, i feel like
comparing the strings is wrong programming. Maybe using an ID
Well using the event source function: e.getSource(), check whither the type of the source is your expected type and cast it to appropriate type. And then you can use getName(String) function and check the name you were expecting. Of-course you should assign the name using setName(String) after initialization of component. Or using the component reference directly if it is declared in the Class context and you have direct access to the component.
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getSource() instanceof JCheckBox)
{
JCheckBox checkBox = (JCheckBox)e.getSource();
if(checkBox.getName().equals("expectedName"))
; // do my thing
}
}
How should i make a "reset" button(start over), i want to uncheck all
radio buttons and run the constructor once again.
Well you are working with ButtonGroup. And ButtonGroup has a nice function: clearSelection() to help with whatever(I could not understand the part: run the constructor part) you want.
Edit: As you wanted me to see an ItemListener implemented class, Yes i can see that But:
i can not see that you have actually registered an instance of that class(a1.addItemListener(handler);) to any component before performing any action on the component to which ButtonHandler is registered to: checkMe, refresh
In addition to that, in this action performed function, you are checking with
action command, which you haven't even set with JButton.setActionCommand(String) function. You should not assign a (Item)listener depending on event-occurrence of another (Action)listener.
Tutorial:
How to Write an ItemListener
How to Write an ActionListener
How to Use the ButtonGroup Component
I use Netbeans to make a Java application. I am still a beginner. I have 4 buttons and I want to change an icon, when a user click one of them. I have already put buttons and one icon but I have no idea on how to continue.
You will need an ActionListener that changes the icon (use an ImageIcon for this). Add that ActionListener to the Button which should be responding to a click, with that action.
button.addActionListener(/*here your listener*/);
Are you using the windowbuilder of netbeans?
If yes, check the generated code for your specified button and see how they did it :)
Ok, i created a new JFrame Form to my package called TestFrame.
public class TestFrame extends javax.swing.JFrame {
static public ImageIcon imageCross;
static public ImageIcon imageCircle;
URL cross = TestFrame.class.getResource("cross.jpg");
URL circle = TestFrame.class.getResource("circle.jpg");
boolean clicked = true;
/**
* Creates new form TestFrame
*/
public TestFrame() {
imageCross = new javax.swing.ImageIcon(cross);
imageCircle = new javax.swing.ImageIcon(circle);
initComponents();
}
...
This is just how i declare my images.
Now i need to change them when i click on a button.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if(clicked) {
jButton1.setIcon(imageCircle);
clicked = false;
} else {
jButton1.setIcon(imageCross);
clicked = true;
}
}
Just add all your images you need. Add for every single JButton a actionPerformed() and switch your icons with a if-condition or maybe switch/case ( if you have more).
I am playing about with GUI builder and i was wondering if there is an easy way to open the register window through the current main window (in reference to the page below). I am trying to do this through the menu bar.
I've been trying all day, because GUI Builder generates some code, its not possible to edit this code.
Thanks For the help!
Create a separate class which extends JDialog class and add your GUI components:
public Register extends JDialog {
//Make GUI
setModalityType(ModalityType.APPLICATION_MODAL); //Make it modal
}
Add ActionListener to that menu item which is supposed to open a register window:
mnuItmRegisteration.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
Register r = new Register();
r.setVisible(true);
}
});
Right click on that shortcut button, click Events, click ActionPreformed.
There you should write codes to make your register window appear.
An example:
private void RegisterationEventActionPerformed(java.awt.event.ActionEvent evt) {
JFrame Register = new Register();
Register.setVisible(true);
}
Remember to make another JFrame called ("Register" assuming u are using the code i gave) at the same package as your current JFrame
Maybe u would probably should use the run button (The button with a Green Triangle or Arrow), run it try to press the menu item, it should appear the register window.