How is JSpinner different than other swing components? - java

I have a method that can recursively enable/disable all components within a JPanel. There are also exception lists. So I can do the following
Disable all components in panel1 except for textfield1, textfield3 who should be enabled.
Enable all components in panel2 except for button2, label3 who should be disabled.
Here is a SSCCE that does exactly that:
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
final JPanel panel = new JPanel(new GridLayout(3, 3));
final JTextField textfield = new JTextField("asdf");
final JButton button = new JButton("asdf");
final JCheckBox checkbox = new JCheckBox("asdf");
final JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 1, 100, 1));
final JLabel label = new JLabel("asdf");
panel.add(textfield);
panel.add(button);
panel.add(checkbox);
panel.add(spinner);
panel.add(label);
// fill in some random stuff
for (int i = 0; i < 4; i++)
panel.add(new JLabel("asdf"));
frame.setContentPane(panel);
frame.setSize(300, 100);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Thread(new Runnable() {
#Override
public void run() {
boolean toggle = true;
while (true) {
toggle = !toggle;
Set<Component> enableList = new HashSet<Component>();
Set<Component> disableList = new HashSet<Component>();
enableList.add(textfield);
enableList.add(spinner);
disableList.add(checkbox);
setEnableAllRec(panel, toggle, disableList, enableList);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
}).start();
frame.setVisible(true);
}
public static void setEnableAllRec(Container root, boolean defaultState, Set<Component> disableList, Set<Component> enableList) {
if (root == null) return;
for (Component c : root.getComponents()) {
if (disableList != null && disableList.contains(c)) {
c.setEnabled(false);
disableList.remove(c);
} else if (enableList != null && enableList.contains(c)) {
c.setEnabled(true);
enableList.remove(c);
} else c.setEnabled(defaultState);
if (c instanceof Container) setEnableAllRec((Container) c, defaultState, disableList, enableList);
}
}
}
The SSCCE sets all components every second to enable/disable alternatingly. Except for some components that should always be enabled and some that should always be disabled. That works extremely well except for the JSpinner. It gets detected as a component but can not be found in the list (and therefore is not handled as a special case). All other swing components that I have tried are working as expected.
Can you tell me whats wrong with JSpinner?
I hope the SSCCE is not too confusing... ;)

Simply because a JSpinner contains other components such as 2 buttons and an editor (see the code of javax.swing.plaf.basic.BasicSpinnerUI) and you go recursively on all containers, thus, also on contained components of the JSpinner.
Btw, your Thread is violating the Swing-EDT. You should rather perform that in a Swing Timer
The solution is easy:
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
final JPanel panel = new JPanel(new GridLayout(3, 3));
final JTextField textfield = new JTextField("asdf");
final JButton button = new JButton("asdf");
final JCheckBox checkbox = new JCheckBox("asdf");
final JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 1, 100, 1));
final JLabel label = new JLabel("asdf");
panel.add(textfield);
panel.add(button);
panel.add(checkbox);
panel.add(spinner);
panel.add(label);
// fill in some random stuff
for (int i = 0; i < 4; i++) {
panel.add(new JLabel("asdf"));
}
frame.setContentPane(panel);
frame.setSize(300, 100);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Thread(new Runnable() {
#Override
public void run() {
boolean toggle = true;
while (true) {
toggle = !toggle;
Set<Component> enableList = new HashSet<Component>();
Set<Component> disableList = new HashSet<Component>();
enableList.add(textfield);
enableList.add(spinner);
disableList.add(checkbox);
setEnableAllRec(panel, toggle, disableList, enableList);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}).start();
frame.setVisible(true);
}
public static void setEnableAllRec(Container root, boolean defaultState, Set<Component> disableList, Set<Component> enableList) {
if (root == null) {
return;
}
for (Component c : root.getComponents()) {
if (disableList != null && disableList.contains(c)) {
c.setEnabled(false);
disableList.remove(c);
} else if (enableList != null && enableList.contains(c)) {
c.setEnabled(true);
enableList.remove(c);
} else {
c.setEnabled(defaultState);
if (c instanceof Container) {
setEnableAllRec((Container) c, defaultState, disableList, enableList);
}
}
}
}
}

Related

How would I use the radio button in jswing to make a listener capable of placing an S or O in the given cell depending on what is selected?

package SOS;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createBoard(ActionEvent event) {
Object source = event.getSource();
if (source instanceof JTextField) {
JTextField textField = (JTextField) source;
String text = textField.getText();
int dimension = Integer.parseInt(text);
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
}
}
frame.add(board, BorderLayout.CENTER);
frame.pack();
}
}
private JPanel createTopPanel() {
JRadioButton optionS = new JRadioButton("S");
JRadioButton optionO = new JRadioButton("O");
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
JPanel topPanel = new JPanel();
JLabel label = new JLabel("Board size:");
topPanel.add(label);
JTextField boardSize = new JTextField(6);
boardSize.addActionListener(this::createBoard);
topPanel.add(boardSize);
topPanel.add(optionS, BorderLayout.NORTH);
topPanel.add(optionO, BorderLayout.CENTER);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
I know I am supposed to make an action listener for each radio button and that seems pretty straightforward, but I am confused on how I would do that and then translate that to placing an S or O on the game boards given cell depending on what is selected. I think the more confusing part is being able to draw in the given cell either the S or the O depending on what is selected. This is for an SOS game, sort of like tic tac toe. I tried following a simple tic tac toe example but got lost as there is no radio buttons like this and I am using a different createboard method.
You can declare your radioButton globally so you can check the selected status. Then in a listener in your cells check that and place the appropriate letter:
package SOS;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
private JRadioButton optionS;
private JRadioButton optionO;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createBoard(ActionEvent event) {
Object source = event.getSource();
if (source instanceof JTextField) {
JTextField textField = (JTextField) source;
String text = textField.getText();
int dimension = Integer.parseInt(text);
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
square.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
square.setText(optionS.isSelected() ? " S " : " O ");
}
});
}
}
frame.getContentPane().add(board, BorderLayout.CENTER);
frame.pack();
}
}
private JPanel createTopPanel() {
optionS = new JRadioButton("S");
optionO = new JRadioButton("O");
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
JPanel topPanel = new JPanel();
JLabel label = new JLabel("Board size:");
topPanel.add(label);
JTextField boardSize = new JTextField(6);
boardSize.addActionListener(this::createBoard);
topPanel.add(boardSize);
topPanel.add(optionS, BorderLayout.NORTH);
topPanel.add(optionO, BorderLayout.CENTER);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
There are few ways you might be able to do this, personally, I like to decouple the workflows and remove dependencies where I can.
For example, your createBoard method is making an assumption about how the dimension value is captured by the user. What happens if you want to change that workflow to use a JSpinner or JCombobox? You'd then have to modify this method as well.
Better to pass the method the information it needs to do its job. In fact, I'd make it return an instance of JPanel, so as to remove all the dependencies, after all createBoard should do just that, nothing else.
I've changed the workflow so there is now a dedicated "create" button, this will collect the information it needs in order to be able to create the board itself. Not as dynamic as the other approach, but it gives the user time to consider their inputs
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
enum State {
S, O;
}
private JPanel board;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createBoard(int dimension, State state) {
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" " + state.name() + " ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
}
}
return board;
}
private JPanel createTopPanel() {
JRadioButton optionS = new JRadioButton("S");
JRadioButton optionO = new JRadioButton("O");
JTextField boardSize = new JTextField(6);
JPanel topPanel = new JPanel();
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
// Default state
optionS.setSelected(true);
JButton createButton = new JButton("Make it so");
createButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
State state = State.O;
if (optionS.isSelected()) {
state = State.S;
}
try {
int dimension = Integer.parseInt(boardSize.getText());
if (board != null) {
frame.remove(board);
}
board = createBoard(dimension, state);
frame.add(board, BorderLayout.CENTER);
frame.pack();
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(topPanel, "Invalid board size", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
JLabel label = new JLabel("Board size:");
topPanel.add(label);
topPanel.add(boardSize);
topPanel.add(optionS);
topPanel.add(optionO);
topPanel.add(createButton);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
If you'd prefer something a little more dynamic, then you could add shared ActionListener to the buttons and text field, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
enum State {
S, O;
}
private JPanel board;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createBoard(int dimension, State state) {
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" " + state.name() + " ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
}
}
return board;
}
private JPanel createTopPanel() {
JRadioButton optionS = new JRadioButton("S");
JRadioButton optionO = new JRadioButton("O");
JTextField boardSize = new JTextField(6);
JPanel topPanel = new JPanel();
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
State state = State.O;
if (optionS.isSelected()) {
state = State.S;
}
try {
int dimension = Integer.parseInt(boardSize.getText());
if (board != null) {
frame.remove(board);
}
board = createBoard(dimension, state);
frame.add(board, BorderLayout.CENTER);
frame.pack();
} catch (NumberFormatException exp) {
// Not yet ready
}
}
};
optionS.addActionListener(actionListener);
optionO.addActionListener(actionListener);
boardSize.addActionListener(actionListener);
// Default state
optionS.setSelected(true);
JLabel label = new JLabel("Board size:");
topPanel.add(label);
topPanel.add(boardSize);
topPanel.add(optionS);
topPanel.add(optionO);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}

JList Swing adding description to List Item

I am trying to create a JList with a small arrow next to it. When clicked, I want some content associated with the list item shown in the same List/Panel. The picture, I hope, gives a clear idea of what I am trying to achieve.
How do I do this ? Also, what is the small triangle feature to the left known as (for future search tags) ?
I hope this is what you meant. The arrowButton is a JToggleButton which, when activated, displays a JWindow containing information about the selected value of the JList. This JWindow will remain visible until the JToggleButtons state is set back to unselected again. The ListPanel class should be reusable in your code.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToggleButton;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Example {
public Example() {
JFrame frame = new JFrame();
ArrayList<Object> elements = new ArrayList<Object>();
ArrayList<String> texts = new ArrayList<String>();
ListPanel listPanel = new ListPanel(elements, texts);
JButton addButton = new JButton("Add");
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JTextField elementField = new JTextField(5);
JTextArea textArea = new JTextArea(5, 10);
JPanel panel = new JPanel();
panel.add(new JLabel("Element:"));
panel.add(elementField);
panel.add(Box.createHorizontalStrut(15));
panel.add(new JLabel("Text:"));
panel.add(new JScrollPane(textArea));
int result = JOptionPane.showConfirmDialog(frame, panel, "Element & Text",
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
listPanel.addElementToList(elementField.getText(), textArea.getText());
}
}
});
JButton deleteButton = new JButton("Remove");
deleteButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (listPanel.getList().getSelectedValue() != null) {
listPanel.removeElementFromList(listPanel.getList().getSelectedValue());
}
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(addButton);
buttonPanel.add(deleteButton);
frame.add(listPanel);
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
class ListPanel extends JPanel {
private JList<Object> list;
private JToggleButton arrowButton;
private ArrayList<String> texts;
private JWindow popup;
public ListPanel(ArrayList<Object> elements, ArrayList<String> texts) {
this.texts = texts;
popup = new JWindow();
arrowButton = new JToggleButton("\u25B6");
arrowButton.setMargin(new Insets(0, 0, 0, 0));
arrowButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (arrowButton.isSelected()) {
Object value = list.getSelectedValue();
if (value != null) {
JLabel titleLabel = new JLabel(value.toString());
titleLabel.setBackground(Color.WHITE);
titleLabel.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
titleLabel.setHorizontalAlignment(JLabel.LEFT);
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
titlePanel.setBackground(Color.WHITE);
titlePanel.add(titleLabel);
JTextPane textPane = new JTextPane();
textPane.setEditable(false);
textPane.setText(texts.get(list.getSelectedIndex()));
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
contentPanel.add(titlePanel, BorderLayout.NORTH);
contentPanel.add(textPane);
popup.setLocation(arrowButton.getLocationOnScreen().x + arrowButton.getWidth(),
arrowButton.getLocationOnScreen().y);
popup.setContentPane(contentPanel);
popup.revalidate();
popup.pack();
popup.setVisible(true);
}
} else {
if (popup.isVisible()) {
popup.setVisible(false);
}
}
}
});
Timer timer = new Timer(100, null);
timer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (((JFrame) SwingUtilities.getWindowAncestor(ListPanel.this)) != null) {
activateComponentListener();
timer.stop();
}
}
});
timer.start();
list = new JList<Object>(new DefaultListModel<Object>());
for (Object element : elements) {
((DefaultListModel<Object>) list.getModel()).addElement(element);
}
JPanel buttonPanel = new JPanel(new BorderLayout());
buttonPanel.setBackground(Color.WHITE);
buttonPanel.add(arrowButton, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setBorder(null);
setLayout(new BorderLayout());
setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(scrollPane);
add(buttonPanel, BorderLayout.WEST);
}
private void activateComponentListener() {
((JFrame) SwingUtilities.getWindowAncestor(this)).addComponentListener(new ComponentAdapter() {
#Override
public void componentMoved(ComponentEvent arg0) {
if (popup.isVisible()) {
popup.setLocation(arrowButton.getLocationOnScreen().x + arrowButton.getWidth(),
arrowButton.getLocationOnScreen().y);
}
}
});
}
public void removeElementFromList(Object element) {
int index = getElementIndex(element);
if (((DefaultListModel<Object>) getList().getModel()).getElementAt(getElementIndex(element)) != null) {
((DefaultListModel<Object>) getList().getModel()).removeElementAt(index);
getTexts().remove(index);
}
}
public void removeElementFromList(int index) {
if (((DefaultListModel<Object>) getList().getModel()).getElementAt(index) != null) {
((DefaultListModel<Object>) getList().getModel()).removeElementAt(index);
getTexts().remove(index);
}
}
private Integer getElementIndex(Object element) {
for (int i = 0; i < ((DefaultListModel<Object>) getList().getModel()).getSize(); i++) {
if (((DefaultListModel<Object>) getList().getModel()).getElementAt(i).equals(element)) {
return i;
}
}
return null;
}
public void addElementToList(Object element, String text) {
((DefaultListModel<Object>) list.getModel()).addElement(element);
getTexts().add(text);
}
public JList<Object> getList() {
return list;
}
public JToggleButton getArrowButton() {
return arrowButton;
}
public ArrayList<String> getTexts() {
return texts;
}
}

JScrollPane shrink/collapse on window minimize

I have a JScrollPane which contains a JTextArea. When the window is minimized and then restored, the JScrollPane will then collapse on itself. Note that this squish only happens if the text in the JTextArea exceeds the given width and/or height of the JTextArea (i.e., the horizontal or vertical scrollbars appear).
This question here: JScrollpane loses size after minimize poses the same problem, but the issue is never addressed, other than to add weightx, weighty, and fill constraints to the JScrollPane, which I already had to begin with.
Below is a simplified example that demonstrates the problem. How can I get the JScrollPane to sustain its size after the window is minimized and restored?
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.EtchedBorder;
public class GUITest implements ActionListener {
JButton button = new JButton("Button");
JTextArea textArea = new JTextArea();
SwingWorker<String, String> mySwingWorker = null;
public static void main(String[] args) throws IOException {
GUITest tracer = new GUITest();
}
public GUITest() throws IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGUI();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public void createAndShowGUI() throws IOException {
JFrame frame = new JFrame("GUI Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints mainPanelConstraints = new GridBagConstraints();
mainPanelConstraints.gridx = 0;
mainPanelConstraints.gridy = 0;
mainPanelConstraints.fill = GridBagConstraints.BOTH;
button.addActionListener(this);
mainPanel.add(button, mainPanelConstraints);
mainPanelConstraints.gridx = 0;
mainPanelConstraints.gridy = 1;
mainPanelConstraints.fill = GridBagConstraints.BOTH;
mainPanel.add(buildTextAreaPanel(), mainPanelConstraints);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setVisible(true);
}
private JPanel buildTextAreaPanel() {
JPanel textAreaPanel = new JPanel();
textAreaPanel.setLayout(new GridBagLayout());
GridBagConstraints textAreaPanelConstraints = new GridBagConstraints();
textAreaPanel.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(EtchedBorder.RAISED), "TextArea"));
textArea.setColumns(30);
textArea.setRows(15);
textArea.setEditable(false);
JScrollPane textAreaScrollPane = new JScrollPane(textArea);
textAreaScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
textAreaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
textAreaPanelConstraints.gridx = 0;
textAreaPanelConstraints.gridy = 0;
textAreaPanelConstraints.weightx = 1.0;
textAreaPanelConstraints.weighty = 1.0;
textAreaPanelConstraints.fill = GridBagConstraints.BOTH;
textAreaPanel.add(textAreaScrollPane, textAreaPanelConstraints);
return textAreaPanel;
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
mySwingWorker = new MySwingWorker();
mySwingWorker.execute();
}
}
private class MySwingWorker extends SwingWorker<String, String> {
public String doInBackground() throws Exception {
for (int i = 0; i < textArea.getRows(); i++) {
publish("text\n");
}
publish("more text\n");
return "Done.";
}
public void process(List<String> chunks) {
for (String msg : chunks) {
textArea.append(msg);
}
}
public void done() {
try {
String msg = get();
textArea.append("\n" + msg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
You need to set the weightx and weighty in both layouts. In createAndShowGui, set mainPanelConstraints.weightx and mainPanelConstraints.weighty to 1 before adding the text area panel.
Set the layout of the parent Container (the content pane) to FlowLayout
...
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(mainPanel);
...
I solved the shrinkage problem in this particular code example by removing all GridBagLayouts and replacing them with BorderLayouts. I have no idea why a JScrollPane reacts the way you discovered when using a GridBagLayout.
I felt real uncomfortable starting the Event Dispatch thread from the class constructor. I moved the SwingUtilities invokeLater into the main method.
Anyway, here's the code.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.EtchedBorder;
public class JScrollPaneTest implements ActionListener {
JButton button = new JButton("Button");
JTextArea textArea = new JTextArea();
SwingWorker<String, String> mySwingWorker = null;
public static void main(String[] args) throws IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new JScrollPaneTest().createAndShowGUI();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public JScrollPaneTest() throws IOException {
}
public void createAndShowGUI() throws IOException {
JFrame frame = new JFrame("JScrollPane Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(button, BorderLayout.NORTH);
mainPanel.add(buildTextAreaPanel(), BorderLayout.CENTER);
button.addActionListener(this);
frame.add(mainPanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel buildTextAreaPanel() {
JPanel textAreaPanel = new JPanel();
textAreaPanel.setLayout(new BorderLayout());
textAreaPanel.setBorder(BorderFactory.createTitledBorder(
new EtchedBorder(EtchedBorder.RAISED), "TextArea"));
textArea.setColumns(30);
textArea.setRows(15);
textArea.setEditable(false);
JScrollPane textAreaScrollPane = new JScrollPane(textArea);
textAreaPanel.add(textAreaScrollPane, BorderLayout.CENTER);
return textAreaPanel;
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
mySwingWorker = new MySwingWorker();
mySwingWorker.execute();
}
}
private class MySwingWorker extends SwingWorker<String, String> {
public String doInBackground() throws Exception {
for (int i = 0; i < textArea.getRows(); i++) {
publish("text\n");
}
publish("more text\n");
return "Done.";
}
public void process(List<String> chunks) {
for (String msg : chunks) {
textArea.append(msg);
}
}
public void done() {
try {
String msg = get();
textArea.append("\n" + msg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}

select many Checkbox in a checkboxgroup java swing

I am working on a Jframe netbeans IDE basically i drag and drop thing in the form i want to make a group of checkboxes at least two groups in one frame and each group has many checkboxes i want to select multiple checkbox in each group and return the value of checked boxes i have read that button group is not applicable in this situation since button group will only have one selection. Any code snippet or idea on how to do this is much appreciated.
UPDATE
Found this sample this is how i want my checkbox to behave only i dont want to put them in table plus there is no table component in netbeans IDE i can drag for this purpose any idea on how to do this is much appreciated
I agree with Trashgod, a JTable is probably a good place to start, another option is to roll your own...
Each "column" is it's own component and allows you to select multiple options, but only within the context of that "group"
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.Scrollable;
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.setLayout(new GridLayout(0, 2));
frame.add(new CheckBoxGroup(new String[]{"Bananas", "Oranages", "Apples", "Pears"}));
frame.add(new CheckBoxGroup(new String[]{"Learn Archery", "Float in the dead sea", "Swing with a whale shark", "Sail the greek islands", "Go skydiving", "Dance in the rain", "Cycle through the Netherlands"}));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CheckBoxGroup extends JPanel {
private JCheckBox all;
private List<JCheckBox> checkBoxes;
public CheckBoxGroup(String... options) {
checkBoxes = new ArrayList<>(25);
setLayout(new BorderLayout());
JPanel header = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1));
all = new JCheckBox("Select All...");
all.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (JCheckBox cb : checkBoxes) {
cb.setSelected(all.isSelected());
}
}
});
header.add(all);
add(header, BorderLayout.NORTH);
JPanel content = new ScrollablePane(new GridBagLayout());
content.setBackground(UIManager.getColor("List.background"));
if (options.length > 0) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1;
for (int index = 0; index < options.length - 1; index++) {
JCheckBox cb = new JCheckBox(options[index]);
cb.setOpaque(false);
checkBoxes.add(cb);
content.add(cb, gbc);
}
JCheckBox cb = new JCheckBox(options[options.length - 1]);
cb.setOpaque(false);
checkBoxes.add(cb);
gbc.weighty = 1;
content.add(cb, gbc);
}
add(new JScrollPane(content));
}
public class ScrollablePane extends JPanel implements Scrollable {
public ScrollablePane(LayoutManager layout) {
super(layout);
}
public ScrollablePane() {
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(100, 100);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 32;
}
#Override
public boolean getScrollableTracksViewportWidth() {
boolean track = false;
Container parent = getParent();
if (parent instanceof JViewport) {
JViewport vp = (JViewport) parent;
track = vp.getWidth() > getPreferredSize().width;
}
return track;
}
#Override
public boolean getScrollableTracksViewportHeight() {
boolean track = false;
Container parent = getParent();
if (parent instanceof JViewport) {
JViewport vp = (JViewport) parent;
track = vp.getHeight() > getPreferredSize().height;
}
return track;
}
}
}
}
What it doesn't do is return a list of selected items, but how hard would it be to iterate over the checkBoxes List, check to see if the item is selected or not, extract it's text and add it to another List and return the result...?

How to configure JComboBox not to select FIRST element when created?

Problem:
Update:
From the Java SE 6 API:
public JComboBox() Creates a JComboBox
with a default data model. The default
data model is an empty list of
objects. Use addItem to add items. By
default the first item in the data
model becomes selected.
So I changed to JComboBox(model) as the API says:
public JComboBox(ComboBoxModel aModel)
Creates a JComboBox that takes its
items from an existing ComboBoxModel.
Since the ComboBoxModel is provided, a
combo box created using this
constructor does not create a default
combo box model and may impact how the
insert, remove and add methods behave.
I tried the following:
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.setSelectedItem(null);
suggestionComboBox = new JComboBox(model);
suggestionComboBox.setModel(model);
But could not get it to work, the first item is still being selected.
Anyone that can come up with a working example would be very much appreciated.
Old part of the post:
I am using JComboBox, and tried using setSelectionIndex(-1) in my code (this code is placed in caretInvoke())
suggestionComboBox.removeAllItems();
for (int i = 0; i < suggestions.length; i++) {
suggestionComboBox.addItem(suggestions[i]);
}
suggestionComboBox.setSelectedIndex(-1);
suggestionComboBox.setEnabled(true);
This is the initial setting when it was added to a pane:
suggestionComboBox = new JComboBox();
suggestionComboBox.setEditable(false);
suggestionComboBox.setPreferredSize(new Dimension(25, 25));
suggestionComboBox.addActionListener(new SuggestionComboBoxListener());
When the caretInvoke triggers the ComboBox initialisation, even before the user selects an element, the actionPerformed is already triggered (I tried a JOptionPane here):
http://i126.photobucket.com/albums/p109/eXPeri3nc3/StackOverflow/combo1.png
http://i126.photobucket.com/albums/p109/eXPeri3nc3/StackOverflow/combo2.png
http://i126.photobucket.com/albums/p109/eXPeri3nc3/StackOverflow/combo3.png
The problem is: My program autoinserts the selected text when the user selects an element from the ComboBox. So without the user selecting anything, it is automatically inserted already.
How can I overcome the problem in this situation? Thanks.
Here is my SSCCE: (finally)
package components;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
public class Temp extends JFrame {
JTextPane textPane;
AbstractDocument doc;
JTextArea changeLog;
String newline = "\n";
private JComboBox suggestionComboBox;
private JPanel suggestionPanel;
private JLabel suggestionLabel;
private JButton openButton, saveButton, aboutButton;
public Temp() {
super("Snort Ruleset IDE");
//Create the text pane and configure it.
textPane = new JTextPane();
textPane.setCaretPosition(0);
textPane.setMargin(new Insets(5, 5, 5, 5));
StyledDocument styledDoc = textPane.getStyledDocument();
if (styledDoc instanceof AbstractDocument) {
doc = (AbstractDocument) styledDoc;
//doc.setDocumentFilter(new DocumentSizeFilter(MAX_CHARACTERS));
} else {
System.err.println("Text pane's document isn't an AbstractDocument!");
System.exit(-1);
}
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(new Dimension(700, 350));
//Create the text area for the status log and configure it.
//changeLog = new JTextArea(10, 30);
//changeLog.setEditable(false);
//JScrollPane scrollPaneForLog = new JScrollPane(changeLog);
//Create a JPanel for the suggestion area
suggestionPanel = new JPanel(new BorderLayout());
suggestionPanel.setVisible(true);
suggestionLabel = new JLabel("Suggestion is not active at the moment.");
suggestionLabel.setPreferredSize(new Dimension(100, 50));
suggestionLabel.setMaximumSize(new Dimension(100, 50));
suggestionComboBox = new JComboBox();
suggestionComboBox.setEditable(false);
suggestionComboBox.setPreferredSize(new Dimension(25, 25));
//suggestionComboBox.addActionListener(new SuggestionComboBoxListener());
suggestionComboBox.addItemListener(new SuggestionComboBoxListener());
//suggestionComboBox.setSelectedIndex(-1);
//add the suggestionLabel and suggestionComboBox to pane
suggestionPanel.add(suggestionLabel, BorderLayout.CENTER);
suggestionPanel.add(suggestionComboBox, BorderLayout.PAGE_END);
JScrollPane sp = new JScrollPane(suggestionPanel);
JScrollPane scrollPaneForSuggestion = new JScrollPane(suggestionPanel);
//Create a split pane for the change log and the text area.
JSplitPane splitPane = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
scrollPane, scrollPaneForSuggestion);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(1.0);
//Disables the moving of divider
splitPane.setEnabled(false);
//splitPane.setDividerLocation(splitPane.getHeight());
//splitPane.setPreferredSize(new Dimension(640,400));
//Create the status area.
JPanel statusPane = new JPanel(new GridLayout(1, 1));
CaretListenerLabel caretListenerLabel =
new CaretListenerLabel("Status: Ready");
statusPane.add(caretListenerLabel);
//Create the toolbar
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.setRollover(true);
openButton = new JButton("Open Snort Ruleset");
toolBar.add(openButton);
saveButton = new JButton("Save Ruleset");
toolBar.add(saveButton);
toolBar.addSeparator();
aboutButton = new JButton("About");
toolBar.add(aboutButton);
//Add the components.
getContentPane().add(toolBar, BorderLayout.PAGE_START);
getContentPane().add(splitPane, BorderLayout.CENTER);
getContentPane().add(statusPane, BorderLayout.PAGE_END);
JMenu editMenu = createEditMenu();
JMenu styleMenu = createStyleMenu();
JMenuBar mb = new JMenuBar();
mb.add(editMenu);
mb.add(styleMenu);
setJMenuBar(mb);
//Put the initial text into the text pane.
//initDocument();
textPane.setCaretPosition(0);
//Start watching for undoable edits and caret changes.
textPane.addCaretListener(caretListenerLabel);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textPane.requestFocusInWindow();
}
});
}
//This listens for and reports caret movements.
protected class CaretListenerLabel extends JLabel
implements CaretListener {
public CaretListenerLabel(String label) {
super(label);
}
//Might not be invoked from the event dispatch thread.
public void caretUpdate(CaretEvent e) {
caretInvoke(e.getDot(), e.getMark());
}
protected void caretInvoke(final int dot, final int mark) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
Rectangle caretCoords = textPane.modelToView(dot);
//Find suggestion
suggestionComboBox.removeAllItems();
for (int i = 0; i < 5; i++) {
suggestionComboBox.addItem(Integer.toString(i));
}
//suggestionComboBox.setSelectedItem(null);
suggestionComboBox.setEnabled(true);
suggestionLabel.setText("The following keywords are normally used as well. Click to use keyword(s). ");
//changeLog.setText("The following keywords are suggested to be used together: " + str);
} catch (BadLocationException ble) {
setText("caret: text position: " + dot + newline);
System.out.println("Bad Location Exception");
}
}
});
}
}
public class SuggestionComboBoxListener implements ItemListener {
//public void actionPerformed(ActionEvent e) {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
JComboBox cb = (JComboBox)e.getSource();
String selection = (String) cb.getSelectedItem();
JOptionPane.showMessageDialog(null, "Item is selected", "Information", JOptionPane.INFORMATION_MESSAGE);
}
}
}
/*
* Menu Creation
*/
//Create the edit menu.
protected JMenu createEditMenu() {
JMenu menu = new JMenu("Edit");
return menu;
}
protected JMenu createStyleMenu() {
JMenu menu = new JMenu("Style");
return menu;
}
private static void createAndShowGUI() {
//Create and set up the window.
final Temp frame = new Temp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//The standard main method.
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
You need to remove the ItemListener before you make any changes to the combo-box and add it back when you are done.
Something like this:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class Suggestions {
private JFrame frame;
private JTextPane textPane;
private JComboBox suggestionComboBox;
private SuggestionComboBoxListener selectionListener;
public Suggestions() {
frame = new JFrame("Snort Ruleset IDE");
textPane = new JTextPane();
textPane.setCaretPosition(0);
textPane.setMargin(new Insets(5, 5, 5, 5));
textPane.addCaretListener(new SuggestionCaretListener());
JScrollPane textEntryScrollPane = new JScrollPane(textPane);
textEntryScrollPane.setPreferredSize(new Dimension(300, 400));
selectionListener = new SuggestionComboBoxListener(frame);
suggestionComboBox = new JComboBox();
suggestionComboBox.setEditable(false);
suggestionComboBox.setPreferredSize(new Dimension(25, 25));
suggestionComboBox.addItemListener(selectionListener);
JPanel suggestionPanel = new JPanel(new BorderLayout());
suggestionPanel.add(suggestionComboBox, BorderLayout.PAGE_END);
frame.getContentPane().add(textEntryScrollPane, BorderLayout.NORTH);
frame.getContentPane().add(suggestionPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private final class SuggestionCaretListener implements CaretListener {
#Override
public void caretUpdate(CaretEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
generateSuggestions();
}
});
}
}
public static final class SuggestionComboBoxListener implements ItemListener {
Component parent;
public SuggestionComboBoxListener(Component parent) {
this.parent = parent;
}
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
JComboBox cb = (JComboBox) e.getSource();
String selection = (String) cb.getSelectedItem();
JOptionPane.showMessageDialog(parent, "The selected item is: " + selection, "Information",
JOptionPane.INFORMATION_MESSAGE);
}
}
}
void generateSuggestions() {
suggestionComboBox.removeItemListener(selectionListener);
suggestionComboBox.removeAllItems();
for (int i = 0; i < 5; i++) {
suggestionComboBox.addItem(Integer.toString(i));
}
suggestionComboBox.setEnabled(true);
suggestionComboBox.addItemListener(selectionListener);
}
public static void main(String[] args) {
new Suggestions();
}
}
BTW, what you posted is not an SSCCE it is a dump of your code. An SSCCE should only have enough code to reproduce the issue you are experiencing.
use
setSelectedItem(null);
Please try with ItemListener instead of ActionListener.
if You want that after 1st entry you made and immediately you combox is empty then just write down the under mentioned code which is:
jComboBox1.setSelectedIndex(0);
and your combox will reset Automatically

Categories

Resources