Java Box (BoxLayout) does not work as expected - java

I have a weird problem using the Java Box class. I am using JDK 1.6.21.
I have an own class, DropDownPanel, that inherits from JPanel. The purpose of the DropDownPanel is to be able to hide and show another Component on it. If you click on the title of the DropDownPanel, the hosted Component (now it is a JTable) is set to visible or invisible. It works fine alone.
I am putting these DropDownPanels into a vertical Box class, then the Box into a JScrollPane. All X and Y alignments of the DropDownPanels are set to 0, so there should be no mis-alignment in the Box.
So I have the following logical tree: a JTable in a DropDownPanel in a Box in a JScrollPane.
The problem is that if the Box contains only the DropDownPanels, then I observe the following behaviour, when I add and remove rows from/to the table:
the JScrollPane is correctly shown after a lot of rows added, meaning that the sizes and the layouts are properly calculated. The scrollbar disappears after I remove enough rows, so the table fits the JFrame.
the JTable rows are refreshed properly, i.e. I see the correct number of rows.
But, JTable never seem to resize itself. Added rows are invisible, removed rows disappear, but the table background (with white color) is still visible. I would expect the JTable to be as compact as possible. It does not.
Now comes the weird thing. If I add an empty JPanel as the last component to the Box, everything works as I would expect. The JTable is always as compact as it can. When removing rows, the table size gets smaller and it is repainted correctly. Without the last JPanel however, the JTable resizes itself correclty (I know it from the appearance of the scrollbar), but never will be compact. Resizing the JFrame does not help. The only thing that forces the proper behaviour is to hide and show the JTable via the DropDownPanel. Then it is shown properly.
Since the DropDownPanel is an extended JPanel and the added JPanel is just the default JPanel, I have no clue, why it does not work without the extra JPanel at the end of the Box.
Finally here is the code. Note the commented line. If it is uncommented, the table behaves properly (better start with his setup), if not, then it is not. You need to click on the DropDownPanel title to show the table at all. Then you can add a lot of rows to see that the scrollpane appears after the number of rows do not fit into the JFrame and it disappears properly when they do. Still, the JTable is not as compact as it should be:
package tabletest;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class TableTest {
public class DropDownPanel extends JPanel implements ActionListener, MouseListener {
private static final long serialVersionUID = 1L;
protected JPanel header = new JPanel();
protected JLabel titleLabel;
protected Component content;
protected boolean isExpanded = true;
public DropDownPanel(String title, Component c) {
content = c;
setLayout(new BorderLayout());
titleLabel = new JLabel(title);
header.setLayout(new BorderLayout());
header.add(titleLabel, BorderLayout.WEST);
add(header, BorderLayout.NORTH);
add(content, BorderLayout.CENTER);
header.addMouseListener(this);
titleLabel.addMouseListener(this);
apply();
}
public void toggleExpanded() {
isExpanded = !isExpanded;
apply();
}
protected void apply() {
titleLabel.setText("Drop state: " + (isExpanded ? "Expanded" : "Collapsed"));
content.setVisible(isExpanded);
setMaximumSize(new Dimension(1024, getPreferredSize().height));
invalidate();
}
#Override
public void actionPerformed(ActionEvent e) {
toggleExpanded();
}
#Override
public void mouseClicked(MouseEvent e) {
toggleExpanded();
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
}
public void run() {
JFrame f = new JFrame();
JPanel p = new JPanel();
Box box = Box.createVerticalBox();
p.setLayout(new BorderLayout());
final JTable table = new JTable();
table.setFocusable(false);
table.setFillsViewportHeight(true);
table.setBackground(Color.white);
DefaultTableModel m = (DefaultTableModel) table.getModel();
m.addColumn("Color");
JButton b = new JButton("Remove row");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
((DefaultTableModel) table.getModel()).removeRow(0);
table.invalidate();
}
});
JButton b2 = new JButton("Add row");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
table.invalidate();
}
});
DropDownPanel ddp = new DropDownPanel("Title", table);
ddp.setAlignmentX(0);
ddp.setAlignmentY(0);
box.add(ddp);
// ---------------------------------------------------------------
// Without this line, it does not work; with this line, it is fine
//box.add(new JPanel());
// ---------------------------------------------------------------
JLabel lll = new JLabel("End of Story");
lll.setAlignmentX(0);
lll.setAlignmentY(0);
box.add(lll);
p.add(new JScrollPane(box), BorderLayout.CENTER);
p.add(b, BorderLayout.SOUTH);
p.add(b2, BorderLayout.NORTH);
f.add(p);
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
f.pack();
f.setVisible(true);
f.setSize(new Dimension(600, 400));
}
public static void main(String[] args) {
new TableTest().run();
}
}
I am sweating blood now, so any help is appreciated :)

Within DropDownPanel you have added component i.e. JTable to center, So it takes all space available.
Following is quoted from API doc:
The components are laid out according
to their preferred sizes and the
constraints of the container's size.
The NORTH and SOUTH components may be
stretched horizontally; the EAST and
WEST components may be stretched
vertically; the CENTER component may
stretch both horizontally and
vertically to fill any space left
over.
Also have look at this guide : A Visual Guide to Layout Managers
I have changed your code. Hope this is what you are looking for :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class TableTest {
public class DropDownPanel extends JPanel implements ActionListener,
MouseListener {
private static final long serialVersionUID = 1L;
//protected JPanel header = new JPanel();
protected JLabel titleLabel;
protected Component content;
protected boolean isExpanded = true;
public DropDownPanel(String title, Component c) {
content = c;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
titleLabel = new JLabel(title);
//header.setLayout(new BorderLayout());
//header.add(titleLabel, BorderLayout.NORTH);
add(titleLabel);
add(content);
//header.addMouseListener(this);
titleLabel.addMouseListener(this);
apply();
}
public void toggleExpanded() {
isExpanded = !isExpanded;
apply();
}
protected void apply() {
titleLabel.setText("Drop state: "
+ (isExpanded ? "Expanded" : "Collapsed"));
content.setVisible(isExpanded);
//setMaximumSize(new Dimension(1024, getPreferredSize().height));
invalidate();
}
#Override
public void actionPerformed(ActionEvent e) {
toggleExpanded();
}
#Override
public void mouseClicked(MouseEvent e) {
toggleExpanded();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
public void run() {
JFrame f = new JFrame();
JPanel p = new JPanel();
Box box = Box.createVerticalBox();
p.setLayout(new BorderLayout());
final JTable table = new JTable();
table.setFocusable(false);
table.setFillsViewportHeight(true);
table.setBackground(Color.white);
DefaultTableModel m = (DefaultTableModel) table.getModel();
m.addColumn("Color");
JButton b = new JButton("Remove row");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
((DefaultTableModel) table.getModel()).removeRow(0);
table.invalidate();
}
});
JButton b2 = new JButton("Add row");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
((DefaultTableModel) table.getModel())
.addRow(new Object[] { "Red" });
table.invalidate();
}
});
DropDownPanel ddp = new DropDownPanel("Title", table);
ddp.setAlignmentX(0);
ddp.setAlignmentY(0);
box.add(ddp);
// ---------------------------------------------------------------
// Without this line, it does not work; with this line, it is fine
// box.add(new JPanel());
// ---------------------------------------------------------------
JLabel lll = new JLabel("End of Story");
lll.setAlignmentX(0);
lll.setAlignmentY(0);
box.add(lll);
p.add(new JScrollPane(box), BorderLayout.CENTER);
p.add(b, BorderLayout.SOUTH);
p.add(b2, BorderLayout.NORTH);
f.add(p);
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
f.pack();
f.setVisible(true);
f.setSize(new Dimension(600, 400));
}
public static void main(String[] args) {
new TableTest().run();
}
}

Normally a JTable's direct parent should be a JScrollPane, you should add the table this way:
DropDownPanel ddp = new DropDownPanel("Title", new JScrollPane(table));

Related

Different value of components from JPanel when coming through different event types

There is one panel which contains 4 components; 1 JLabel, 1 JButton, 1 JTextField and 1 JPopupMenu
There is a method "testMethod()" in which first I get the number of components from the panel and then the type of component(JButton, JLabel etc).
Now there are 2 scenarios occurring when the control flow goes to testMethod():
When coming through JButton click event, it shows 4 components on panel and after get all 4 components
When coming through JMenuItem click event, it shows 3 components on panel(not getting JPopupMenu) and after only 3 components(not getting JPopupMenu)
I don't get it what is causing this behavior. I searched a lot on the internet and also read JPopupMenu documents but found nothing about this.
Following is the code:
(it is a part of very big code so I put here only that code which is showing the scenario)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class TestProject extends JFrame {
JPanel panel;
private JPanel contentPane;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestProject frame = new TestProject();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestProject() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
JLabel lblNewLabel = new JLabel("New label");
panel.add(lblNewLabel);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testMethod();
}
});
panel.add(btnNewButton);
textField = new JTextField();
panel.add(textField);
textField.setColumns(10);
// Creating upper level container
JPopupMenu editMenu = new JPopupMenu("Edit");
JMenuItem item1 = new JMenuItem("Item 1");
item1.setBackground(Color.WHITE);
JMenuItem item2 = new JMenuItem("Item 2");
item2.setBackground(Color.WHITE);
item2.setBackground(Color.WHITE);
// Setting Copy action listener
item2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testMethod();
}
});
// Adding the menu items on the popup menu
editMenu.add(item1);
editMenu.add(item2);
panel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// Added check to open menu only on left click
if (e.getButton() == MouseEvent.BUTTON3)
editMenu.show(panel, e.getX(), e.getY());
}
});
// Adding popup menu to the logAreaPanel
panel.add(editMenu);
}
void testMethod()
{
// Here getting number of components of panel
// When coming through JButton click event, it shows 4 components on panel and after get all 4 components
int items = panel.getComponentCount();
Component c;
// Getting all the trees one by one and storing their data into StringBuilder
for(int loopCounter = 0; loopCounter < items; loopCounter++)
{
// here getting different component types
// When coming through JMenuItem click event, it shows 3 components on panel(not getting JPopupMenu) and after only 3 components(not getting JPopupMenu)
c = panel.getComponent(loopCounter);
}
}
}
Any help would be appreciated. :-)
You don't need to add the popup to the component. The preferred way is to just use
panel.setComponentPopupMenu(editMenu);
As per the tutorial, You could use a MouseListener.
//panel.add(editMenu);
panel.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
editMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
That way the component count will always be three, because it is never added to the panel.

Align text and checkbox of a JCheckBox on opposite sides of parent

Is there a simple way to align just the checkbox of a JCheckBox to the right without creating a separate label and check box component? I am aware of setHorizontalTextPosition(SwingConstants.LEADING); This only results in the box being on the right side of the text, but not right aligned.
What I want:
| Some sample text ☑ |
instead of
| Some sample text ☑ |
Thanks in advance!
You can manually manipulate the icon text gap every time the check box size changes by adding a ComponentListener to the check box:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
setLayout( new BorderLayout() );
JCheckBox checkBox = new JCheckBox("Some Sample Text");
checkBox.setHorizontalTextPosition(JCheckBox.LEADING);
add(checkBox, BorderLayout.PAGE_START);
checkBox.addComponentListener( new ComponentAdapter()
{
#Override
public void componentResized(ComponentEvent e)
{
JCheckBox checkBox = (JCheckBox)e.getComponent();
int preferredWidth = getPreferredSize().width;
int actualWidth = getSize().width;
int difference = actualWidth - preferredWidth;
int gap = checkBox.getIconTextGap() + difference;
gap = Math.max(UIManager.getInt("CheckBox.textIconGap"), gap);
checkBox.setIconTextGap( gap );
}
});
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
You can separate the label and checkbox in a suitable layout. I've made the enclosing frame wider by an arbitrary factor to show the effect.
Addendum: As noted here, "clicking the label doesn't check the box." A suitable MouseListener can toggle the check box in response to a mouse press anywhere in the enclosing panel.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/36369035/230513
* #see http://stackoverflow.com/a/2933256/230513
*/
public class Test {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(0, 1));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createPanel("Some label"));
frame.add(createPanel("Another label"));
frame.add(createPanel("Yet another label"));
frame.pack();
frame.setSize(frame.getWidth() * 2, frame.getHeight());
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createPanel(String s) {
JPanel panel = new JPanel(new BorderLayout());
JCheckBox check = new JCheckBox();
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
check.setSelected(!check.isSelected());
}
});
panel.add(new JLabel(s, JLabel.LEFT), BorderLayout.WEST);
panel.add(check, BorderLayout.EAST);
panel.setBorder(BorderFactory.createLineBorder(Color.blue));
return panel;
}
});
}
}
you can also use method in AbstractButton.java setIconTextGap(int)

JTable autoscroll to the bottom in Java

I would like the JTable to autoscroll to the bottom whenever I add a new column and show the last 10 rows. However, I have the option of scrolling to anywhere I want (mouse listener?). Do you know how to do that? Here's the code I have so far. It builds a JTable and adds a new row for every mouse click on the JButton.
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.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class sampleGUI extends JFrame implements ActionListener {
private JButton incrementButton;
private JTable table;
private DefaultTableModel model;
private int count;
private JScrollPane scroll;
public sampleGUI() {
JFrame frame = new JFrame("sample frame");
frame.setLayout(new BorderLayout());
incrementButton = new JButton("Increase the count!");
model = new DefaultTableModel();
model.addColumn("column 1");
table = new JTable(model);
frame.add(incrementButton, BorderLayout.NORTH);
scroll = new JScrollPane(table)
frame.add(scroll, BorderLayout.CENTER);
count = 0;
incrementButton.addActionListener(this);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public synchronized void actionPerformed(ActionEvent e) {
if (e.getSource() == incrementButton) {
count++;
model.addRow(new Object[] { count });
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
sampleGUI gui = new sampleGUI();
}
});
}
}
Thanks!
Required to change selection in JTable, add code line
table.changeSelection(table.getRowCount() - 1, 0, false, false);
to
public (synchronized) void actionPerformed(ActionEvent e) {
I would like the JTable to autoscroll to the bottom whenever I add a new column
I assume you mean scroll to the bottom when you add a new row?
model.addRow(new Object[] { count });
table.scrollRectToVisible(...);
You forget add JScrollPane to the table :
//...
frame.add(new JScrollPane(table), BorderLayout.CENTER);
//...
and don't forget
import javax.swing.JScrollPane;

How to implement ListSelectionListener with JFormDesigner?

I'm trying to get a button to enable/disable itself depending on whether a JTable has any rows selected.
So I believe I need the button to be a ListSelectionListener, listening the JTable's SelectionModel, as described in this Oracle tutorial.
How should I do this with JFormDesigner 5?
Seems like I should be adding the following code to my JButton, but I don't know how to do so in JFormDesigner.
// Implementing this method to be a ListSelectionListener.
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
boolean anyRowsSelected = !(lsm.isSelectionEmpty());
this.setEnabled( anyRowsSelected );
}
In my experience with JFormDesigner adding an actionPerformed handler, JFormDesigner created a method on the JFrame. But my understanding of Swing & OOP says the code for a ListSelectionListener should be inside the listening widget itself (the JButton in my case).
I'm using: JFormDesigner 5.0.0.1, IntelliJ 10.5, Java 1.6.0_24, Mac OS X 10.6.7.
--------SOLVED-----------
Thanks to "Hovercraft Full Of Eels" for answering my question.
Solution: I will add code to my JFrame to create a ListSelectionListener. That gets the job done without interfering with the JFormDesigner tool.
I enhanced example code given by "Hovercraft Full Of Eels", to make it more interactive. I added an ActionListener to the button to clear the user's selection. Now the user can see the button toggle between enabled and disabled.
My version shows a subtle bug: the selected cell turns black when the table's selection is cleared. I don't why. But that is out of scope for this StackOverflow question. Regardless of that bug, this code is a good demo for this question.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
public class TableAndButton extends JPanel {
private static final String[] COLUMN_NAMES = {"Mon", "Tues", "Wed", "Thurs", "Fri"};
private JButton button = new JButton("Clear user's selection");
private DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 10);
private JTable table = new JTable(model);
public TableAndButton() {
JPanel btnPanel = new JPanel();
btnPanel.add(button);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
boolean anyRowSelected = !(lsm.isSelectionEmpty());
button.setEnabled(anyRowSelected);
}
});
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
table.getSelectionModel().clearSelection();
}
});
button.setEnabled(false);
setLayout(new BorderLayout());
add(new JScrollPane(table), BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("TableAndButton");
frame.getContentPane().add(new TableAndButton());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
No, the JButton itself shouldn't be a ListSelectionListener, but rather the JTable needs a separate ListSelectionListener added to it that enables/disables the JButton. Don't think about it as if the button is listening to the JTable because it isn't. Instead a separate entity is doing the listening and changes the state of the program depending on whether or not a row is selected.
e.g.,
import java.awt.BorderLayout;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
public class TableAndButton extends JPanel {
private static final String[] COLUMN_NAMES = {"Mon", "Tues", "Wed", "Thurs", "Fri"};
private JButton button = new JButton("Button");
private DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 10);
private JTable table = new JTable(model);
public TableAndButton() {
JPanel btnPanel = new JPanel();
btnPanel.add(button);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
boolean anyRowSelected = !(lsm.isSelectionEmpty());
button.setEnabled(anyRowSelected);
}
});
button.setEnabled(false);
setLayout(new BorderLayout());
add(new JScrollPane(table), BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("TableAndButton");
frame.getContentPane().add(new TableAndButton());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}

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