I tried a number of other solutions posted on StackExchange but I can't get the JCheckBox to unselect when I click it again [after it's been selected].
I've tried the following and it just stays clicked even when re-clicked:
checkbox2.setSelected(false);
// check state
//if (checkbox2.isSelected()) {
// do something...
checkbox2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
// return str;
//checkbox = (JCheckBox) event.getSource();
if (checkbox2.isSelected()) {
checkbox2.setSelected(false);
experimentalSelection = "ML";
System.out.println(experimentalSelection);
}
}
});
I assumed that if i added checkbox2.setSelected(false); then it would uncheck if it was already selected and then clicked.
The behavior that you describe -- making the JCheckBox unselected when a user clicks on an already selected JCheckBox is the check box's default/innate behavior. You don't have to do anything special for this to occur, and you certainly don't have to (or want to) change its selection state within a listener. For example:
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import javax.swing.*;
public class GuiFun extends JPanel {
private JCheckBox checkbox = new JCheckBox("Foo");
public GuiFun() {
setPreferredSize(new Dimension(300, 150));
add(checkbox);
checkbox.setSelected(false);
checkbox.addItemListener(l -> {
if (l.getStateChange() == ItemEvent.SELECTED) {
System.out.println("CheckBox SELECTED");
} else {
System.out.println("CheckBox UNSELECTED");
}
});
}
private static void createAndShowGui() {
GuiFun mainPanel = new GuiFun();
JFrame frame = new JFrame("Gui Fun");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Related
My program seems to run fine, except for the delete part. Every time I click on the 'delete' button, it deletes itself. So my question is, how would I delete a selected button after I clicked on the "delete" button?
Here is a snippet of my code:
public class DeleteButton extends JFrame implements ActionListener
{
JButton b18a = new JButton("Delete");
JPanel panel = new JPanel();
panel.add(b18);
class ClickListenerTwo implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JButton buttonThatWasClicked = (JButton) e.getSource();
Container parent = buttonThatWasClicked.getParent();
parent.remove(buttonThatWasClicked);
parent.revalidate();
parent.repaint();
}
}
}
ActionListener b18aClicked = new ClickListenerTwo();
b18a.addActionListener(b18aClicked);
P.S - This selected button that I'm talking about is made during run time, so I want to delete it during run time too, if that would be possible. Thanks!
So, assuming that you need to click the "other" button first, you could use an instance field to maintain a reference to the "last" clicked button and then use that when the delete button is clicked
For example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JButton lastButton;
public TestPane() {
JPanel grid = new JPanel(new GridLayout(8, 8));
for (int index = 0; index < 8 * 8; index++) {
JButton btn = new JButton(Integer.toString(index + 1));
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
lastButton = btn;
}
});
grid.add(btn);
}
JButton delete = new JButton("Delete");
delete.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (lastButton != null) {
lastButton.getParent().remove(lastButton);
grid.revalidate();
grid.repaint();
}
lastButton = null;
}
});
setLayout(new BorderLayout());
add(grid);
add(delete, BorderLayout.SOUTH);
}
}
}
Personally, a JToggleButton would give a better user experience
You have to find the Component from the Top Frame.
May be this code will help you.
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source instanceof Component) {
Window w = findWindow((Component) source);
//Find your component and remove it from this window.
} else {
System.out.println("source is not a Component");
}
}
public static Window findWindow(Component c) {
System.out.println(c.getClass().getName());
if (c instanceof Window) {
return (Window) c;
} else if (c instanceof JPopupMenu) {
JPopupMenu pop = (JPopupMenu) c;
return findWindow(pop.getInvoker());
} else {
Container parent = c.getParent();
return parent == null ? null : findWindow(parent);
}
}
When I click on an item of a JComboBox to show a JoptionPane with the text of selected item , it is showed two times. How can I desactive the item listener event?
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
public class Combo implements ItemListener {
JFrame f;
JComboBox cb;
Combo() {
f = new JFrame("Combo ex");
String country[] = {"India", "Aus", "U.S.A", "England", "Newzeland"};
cb = new JComboBox(country);
cb.setBounds(50, 50, 90, 20);
f.add(cb);
cb.addItemListener(this);
f.setLayout(null);
f.setSize(400, 500);
f.setVisible(true);
}
public static void main(String[] args) {
new Combo();
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getSource()==cb) {
String seleccionado=(String)cb.getSelectedItem();
JOptionPane.showMessageDialog(f, seleccionado);
}
}
}
You want to avoid overriding itemStateChanged(). Changing the state of the item within itemStateChanged causes itemStateChanged to be fired... which is why you're seeing the dialog twice. You should use an ActionListener instead.
I slightly modified your code as an example. It should show only 1 dialog box now.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Combo{
JFrame frame;
JComboBox cb;
Combo() {
frame = new JFrame("Combo ex");
String country[] = {"India", "Aus", "U.S.A", "England", "Newzeland"};
cb = new JComboBox(country);
cb.setBounds(50, 50, 90, 20);
cb.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String seleccionado=(String)cb.getSelectedItem();
JOptionPane.showMessageDialog(frame, seleccionado);
}
});
frame.add(cb);
frame.setLayout(null);
frame.setSize(400, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
new Combo();
}
}
Problem is, itemStateChanged() is invoked when an item has been selected or deselected by the user. In simple terms, when you select a new item, you also deselected the old item.
Try this:
if (e.getSource()==cb && e.getStateChange() == ItemEvent.SELECTED) {
//
}
getStateChange(), returns the type of state change (selected or deselected).
Basically.. I made a JDialog using swing. And now I want it to return a value to the JFrame that called it. Problem is, whenever I call the constructor for the JDialog, it won't block the thread even though I've set setModal(true). Am I missing something obvious here?
private final JPanel contentPanel = new JPanel();
private File chosenFile = null;
private JList list;
private File[] files;
public File getInformation()
{
return chosenFile;
}
/**
* Create the dialog.
*/
public PatientPicker(JFrame parent)
{
super(parent);
setModal(true);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setLocationRelativeTo(parent);
setBounds(100, 100, 450, 396);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
files = new File(ClientInfo.GetAppData() + "/patients").listFiles(new TextFileFilter());
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("OK");
okButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if(files.length != 0)
chosenFile = files[list.getSelectedIndex()];
dispose();
}
});
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("Cancel");
cancelButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
dispose();
}
});
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
}
And then here is how I create it:
PatientPicker patientPicker = new PatientPicker(frmReportGenerator);
File dataFile = patientPicker.getInformation();
You state:
Problem is, whenever I call the constructor for the JDialog, it won't block the thread even though I've set setModal(true). Am I missing something obvious here?
The constructor will never block the event thread. Modality means that the event thread is blocked only when you call setVisible (true) on your modal dialog (as per the api).
Unrelated problem: you should not use MouseListeners on JButtons but rather ActionListeners. Otherwise you will run into major problems now, such as when you press the file via the space bar, and while it does depress, nothing happens, and in later code, such as say when you make the button disabled, and yet it is still functioning, even though it looks disabled.
Now if you are still having problems, then you may wish to post more code, a minimal code example program which would allow us to understand and experience your problem.
Edit
You state:
Yes. The user chooses a file in the JDialog and I want it to return to the JFrame that called it.
Why not just use a JFileChooser modal dialog?
Edit 2
An example using a JOptionPane:
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class SwingFoo extends JPanel {
private JTextField fileField = new JTextField(20);
private JButton showDialog = new JButton(new ShowDialogAction("Show Dialog",
KeyEvent.VK_D, this));
public SwingFoo() {
fileField.setEditable(false);
fileField.setFocusable(false);
add(new JLabel("File Selected:"));
add(fileField);
add(showDialog);
}
public void setFileFieldText(String text) {
fileField.setText(text);
}
private static void createAndShowGui() {
SwingFoo mainPanel = new SwingFoo();
JFrame frame = new JFrame("SwingFoo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class ShowDialogAction extends AbstractAction {
private SwingFoo swingFoo;
public ShowDialogAction(String name, int mnemonic, SwingFoo swingFoo) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.swingFoo = swingFoo;
}
#Override
public void actionPerformed(ActionEvent e) {
PatientPicker patientPicker = new PatientPicker();
int result = JOptionPane.showConfirmDialog(swingFoo, patientPicker,
"Select Something", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
swingFoo.setFileFieldText(patientPicker.getSelectedItem());
}
patientPicker.setVisible(true);
}
}
#SuppressWarnings("serial")
class PatientPicker extends JPanel {
private static final String[] ITEMS = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Sunday", "Fubar", "Snafu", "DILLIGAF", "BOHICA"};
private JList<String> selectionList = new JList<>(ITEMS);
public PatientPicker() {
add(new JScrollPane(selectionList));
selectionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
public String getSelectedItem() {
return selectionList.getSelectedValue();
}
}
What you need to do is have a way to send a notification to your main window once the user has completed interacting with the dialog assuming they clicked the ok button.
You can do this by creating an anonymous class and passing that along in the constructor of your Dialog.
let's assume that you open the dialog with a button called openDialogBtn from the main window:
openDialogBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new PatientPicker(this, new FileSelectionNotifier() {
public void okButtonPressed(File chosenFile) {
// do whatever you need to do with the file (assign to a member variable
// or call another thread to do some kind of processing
}
});
In your dialog window you would need to have something like this:
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
// notify that the ok button was pressed
fileSelectionNotifier.okButtonPressed(chosenFile);
}
}
i have a situation where i show a dialog where user has to fill some menus and then press OK. It works fine, but now i have another button on this dialog that if user wants to add some certain value, i want another dialog to popup where user fills the additional value and while pressing ok, this dialog disappears and user comes back to the main dialog.
I have tried this, but every time i call the new dialog, the focus does not go away from the main dialog, how can i do such a task.
Is there any relevant example or what is the proper way of doing such things.
EDIT:
public static class EdgeMenu extends JPopupMenu {
// private JFrame frame;
public MyMenu(final JFrame frame) {
super("My Menu");
// this.frame = frame;
this.addSeparator();
this.add(new EdgePropItem(frame));
}
}
//this shows the first dialog, another class because i have some other
//functions to be performed here
public static class EdgePropItem extends JMenuItem{
//...
public EdgePropItem(final JFrame frame) {
super("Edit Properties");
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
EdgePropertyDialog dialog = new EdgePropertyDialog(frame, edge);
dialog.setVisible(true);
}
});
}
}
and now in other dialog, in the button even listener i am trying to call another dialog:
private void newDialogHandler(java.awt.event.ActionEvent evt) {
MyNewDialog rdialog = new MyNewDialog(edge);
rdialog.setVisible(true);
}
It appears fine, but the previous dialog, does not leave the focus, and it goes away only if i press finish/done on that dialog, what i want is the new dialog to come in focus, while pressing ok on here, focus should come back to the old main dialog, but it is not working?
maybe this code could be demonstate your issues,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SuperConstructor extends JFrame {
private static final long serialVersionUID = 1L;
public SuperConstructor() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 300));
setTitle("Super constructor");
Container cp = getContentPane();
JButton b = new JButton("Show dialog");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
FirstDialog firstDialog = new FirstDialog(SuperConstructor.this);
}
});
cp.add(b, BorderLayout.SOUTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
});
add(bClose, BorderLayout.NORTH);
pack();
setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
SuperConstructor superConstructor = new SuperConstructor();
}
});
}
private class FirstDialog extends JDialog {
private static final long serialVersionUID = 1L;
FirstDialog(final Frame parent) {
super(parent, "FirstDialog");
setPreferredSize(new Dimension(200, 200));
setLocationRelativeTo(parent);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
JButton bNext = new JButton("Show next dialog");
bNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
SecondDialog secondDialog = new SecondDialog(parent, false);
}
});
add(bNext, BorderLayout.NORTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
private int i;
private class SecondDialog extends JDialog {
private static final long serialVersionUID = 1L;
SecondDialog(final Frame parent, boolean modal) {
//super(parent); // < --- Makes this dialog
//unfocusable as long as FirstDialog is visible
setPreferredSize(new Dimension(200, 200));
setLocation(300, 50);
setModal(modal);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setTitle("SecondDialog " + (i++));
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
}
You can achieve this as follows:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JOptionPane;
public class MultipleDialogs
{
public MultipleDialogs()
{
JButton btnOpen = new JButton("Open another dialog!");
btnOpen.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(null, "This is the second dialog!");
}
});
Object[] options = {"OK", "Cancel", btnOpen};
int selectedOption = JOptionPane.showOptionDialog(null,
"This is the first dialog!", "The title",
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE,
null, options, options[0]);
if(selectedOption == 0) // Clicking "OK"
{
}
else if(selectedOption == 1) // Clicking "Cancel"
{
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new MultipleDialogs();
});
}
}
}
You can replace "This is the first dialog!" and "This is the second dialog!" with JPanel's which can contain any swing components you want.
Create the second dialog from a constructor that takes dialog and boolean as parameters and that solves the problem.
I try to attach action Events on the JCombobox arrow JButton.
So I make a custom ComboBoxUI:
public class CustomBasicComboBoxUI extends BasicComboBoxUI {
public static CustomBasicComboBoxUI createUI(JComponent c) {
return new CustomBasicComboBoxUI ();
}
#Override
protected JButton createArrowButton() {
JButton button=super.createArrowButton();
if(button!=null) {
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// arrow button clicked
}
});
}
return button;
}
}
The problem with this is that the look of combobox is different, seem to be an old look.
Why? I only add a listener to the same arrow button...
Thank.
Perhaps the problem is due to your expecting a JComboBox isn't a BasicComboBoxUI but one of another look and feel, perhaps a MetalComboBoxUI.
Rather than create a new CustomBasicComboBoxUI object, could you extract the JButton component from an existing JComboBox object? i.e.,
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class ComboBoxArrowListener {
private static void createAndShowUI() {
String[] data = {"One", "Two", "Three"};
JComboBox combo = new JComboBox(data);
JPanel panel = new JPanel();
panel.add(combo);
JButton arrowBtn = getButtonSubComponent(combo);
if (arrowBtn != null) {
arrowBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("arrow button pressed");
}
});
}
JFrame frame = new JFrame("ComboBoxArrowListener");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static JButton getButtonSubComponent(Container container) {
if (container instanceof JButton) {
return (JButton) container;
} else {
Component[] components = container.getComponents();
for (Component component : components) {
if (component instanceof Container) {
return getButtonSubComponent((Container)component);
}
}
}
return null;
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}