How to create an unknown number of Swing components? - java

I need to display a user-inputted number of tabs (JTabbedPane) (with the same initial content, but the ability to individually change the content), is there a way to create these components procedurally so I don't have to know how many there will be before the user input?

Here is an example of change number of tabse depended on user input:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TabbedPaneTest3 implements Runnable {
private final JTabbedPane tabber = new JTabbedPane();
public static void main(String[] args) {
SwingUtilities.invokeLater(new TabbedPaneTest3());
}
#Override
public void run() {
final JSpinner spinner = new JSpinner(new SpinnerNumberModel(3, 1, 10, 1));
spinner.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
Object val = spinner.getValue();
if (val instanceof Number) {
updateTabsNumber((Number) val);
}
}
});
updateTabsNumber(3);
JFrame frm = new JFrame("Tab Pane");
JPanel panel = new JPanel();
panel.add(new JLabel("Number of tabs: "));
panel.add(spinner);
frm.add(panel, BorderLayout.NORTH);
frm.add(tabber);
frm.setSize(600, 400);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
private void updateTabsNumber(Number val) {
int count = val.intValue();
tabber.removeAll();
for (int i = 0; i < count; i++) {
String text = "Tab " + (i + 1);
JTextArea area = new JTextArea(10, 30);
area.setText("Initial text for tab: " + (i + 1));
tabber.addTab(text, new JScrollPane(area));
}
}
}

Related

About getting values from JList

I am trying to get values from a database via Jlist; but when I select a value of Jlist, no values return and the "Jtable" becomes empty instead of titles. That's my code for UI.
Thanks for your help...
package ui;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import model.Category;
import model.Person;
import service.AddressBookService;
import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JSplitPane;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.border.LineBorder;
import java.awt.Color;
import javax.swing.UIManager;
import javax.swing.AbstractListModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
public class UserInterfaceMain extends JFrame {
private JPanel contentPane;
private JPanel panel;
private JButton btnNew;
private JSplitPane splitPane;
private JList list;
private JTable table;
private JScrollPane scrollPane;
private List<Category> categories = new ArrayList<>();
private List<Person> personList = new ArrayList<>();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UserInterfaceMain frame = new UserInterfaceMain();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public UserInterfaceMain() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 624, 395);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
panel = new JPanel();
contentPane.add(panel, BorderLayout.NORTH);
panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
btnNew = new JButton("NEW");
panel.add(btnNew);
splitPane = new JSplitPane();
contentPane.add(splitPane, BorderLayout.CENTER);
list = new JList();
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent arg0) {
do_list_valueChanged(arg0);
}
});
splitPane.setLeftComponent(list);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollPane = new JScrollPane();
contentPane.add(scrollPane, BorderLayout.EAST);
table = new JTable();
splitPane.setRightComponent(table);
scrollPane.setViewportView(table);
loadCategories();
}
public void loadCategories() {
categories = new AddressBookService().getAllCategories();
DefaultListModel<Category> listModel = new DefaultListModel<>();
for (int i = 0; i < categories.size(); i++) {
listModel.addElement(categories.get(i));
//listModel.addElement(categories.get(i).getName());
}
list.setModel(listModel);
}
public void loadPersonList() {
String[] columns = new String[] { "NAME", "LAST NAME", "E-MAIL", "CITY" };
Object[][] personData = new Object[personList.size()][];
for (int i = 0; i < personData.length; i++) {
personData[i] = new Object[] { personList.get(i).getName(), personList.get(i).getLastName(),
personList.get(i).getEmail(), personList.get(i).getCity() };
}
TableModel tableModel = new DefaultTableModel(personData, columns);
table.setModel(tableModel);
}
protected void do_list_valueChanged(ListSelectionEvent arg0) {
personList = new AddressBookService().getPersonsForTable(((Category)list.getSelectedValue()).getId());
loadPersonList();
System.out.println(personList.size());
}
}
I don't understand exactly what you want, but I modified your code to run it in this way:
Obviously I have all hardcoded in order to run your program. If your problem is that in the left side instead of the names of the categories appears the hash code of the object "com.mypackage.Category#12AAAF", you must modify your Category class and override the toString method.
#Override
public String toString() {
return getName();
}
If it isn't your problem, please add a comment describing it.

netbeans does not run javaswing application

The JavaSwing application shows no errors in netbeans. When I try to run it, it takes forever and nothing is happening(JDK 8 + Netbeans 8.1). The same problem in eclipse. A simple hello world program works. The program is divided in 4 classes. Sorry for the long code.
package test2;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class MainWindow extends JFrame {
private Navigator navigator = new Navigator(this);
private Field spielfeld = new Field();
public MainWindow() {
super("GameTest");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.add(spielfeld);
this.setResizable(false);
this.pack();
}
public static void main(String[] args) {
new MainWindow();
}
}
package test2;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
public class Field extends JPanel {
private static int x = 10;
private static int y = 10;
private JLabel[][] fields = new JLabel[10][10];
public Field() {
Dimension dim = new Dimension();
dim.setSize(50, 50);
this.setLayout(new GridLayout(x, y));
for(int i = 0; i < y; i++){
for(int j = 0; j < x; j++){
fields[i][j] = new JLabel();
fields[i][j].setPreferredSize(dim);
fields[i][j].setOpaque(true);
if((i+j)%2 == 0){
fields[i][j].setBackground(Color.BLACK);
}
else {
fields[i][j].setBackground(Color.WHITE);
}
this.add(fields[i][j]);
}
}
}
}
package test2;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
public class Navigator extends JWindow {
public Navigator(JFrame parent) {
super(parent);
JPanel frame = new JPanel();
frame.setLayout(new BorderLayout());
frame.setBorder(BorderFactory.createLineBorder(Color.RED));
frame.add(new Keypad(), BorderLayout.NORTH);
this.getContentPane().add(frame);
this.updateLocation();
this.pack();
}
public void updateLocation()
{
this.setLocation((int)this.getParent().getLocation().getX() + this.getParent().getWidth() + 550,
(int)this.getParent().getLocation().getY());
}
public MainWindow getMainWindow()
{
return (MainWindow)this.getParent();
}
}
package test2;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Keypad extends JPanel {
public Keypad() {
Dimension dim = new Dimension(60, 30);
this.setLayout(new GridLayout(3, 3));
this.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
for(int i = 9; 0 < i; i--) {
JButton button = new JButton(String.valueOf(i));
button.setPreferredSize(dim);
button.setVisible(true);
if(i != 5) {
this.add(button);
this.add(button);
}
}
this.setVisible(true);
}
}
You are missing setVisible(true) inside your MainWindow constructor.
The code will "run forever" with or without this line. The only difference is that the window will be shown.

How set size of specified String to JTextField?

JTextField in JPanel which in turn in JDialog doesn't take specified size. I tried to use BoxLayout and FlowLayout, but still have not achieved the desired size. I.E. I measure the size of String example and set this size to width of JTextField inputCat, but inputCat doesn't take this size, then I call it. How correctly set size of specified String to JTextField? Here is my code:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.util.Calendar;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DemoJDialog {
static private JInternalFrame internal;
public static void main(String[] args) {
new DemoJDialog();
}
public DemoJDialog() {
EventQueue.invokeLater(new Runnable() {
#SuppressWarnings({ "rawtypes", "unchecked" })
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
internal = new JInternalFrame("Example", true, true, false, true);
internal.setLayout(new BorderLayout());
internal.setVisible(true);
JDesktopPane dp = new JDesktopPane();
dp.add(internal);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(dp);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JTextField inputCat = new JTextField();
String example = new String("Some very-very-very-"
+ "very-very-very-very-very-very long string (really long )");
int heightInputCat = inputCat.getSize().height;
FontMetrics FN = internal.getFontMetrics(internal.getFont());
int widthInputCat = SwingUtilities.computeStringWidth(FN, example);
inputCat.setSize(widthInputCat, heightInputCat);
String[] comboString = { "Telecast", "Radiocast" };
JComboBox comboBox = new JComboBox(comboString);
Calendar now = Calendar.getInstance();
SpinnerModel modelSpinner = new SpinnerDateModel(now.getTime(),
null, null, Calendar.MONTH);
final JSpinner spinner = new JSpinner(modelSpinner);
spinner.setEditor(new JSpinner.DefaultEditor(spinner));
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS));
listPane.add(comboBox);
listPane.add(Box.createHorizontalStrut(10));
listPane.add(inputCat);
listPane.add(Box.createHorizontalStrut(10));
listPane.add(spinner);
Object[] array = {
new JLabel ("Enter a new category:"),
listPane
};
JOptionPane pane = new JOptionPane(array, JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION);
JDialog dialog = pane.createDialog(internal, "Enter a new category:");
dialog.setVisible(true);
}
});
}
}
This works just fine here:
import java.awt.EventQueue;
import java.util.Calendar;
import javax.swing.*;
public class DemoJDialog {
public static void main(String[] args) {
new DemoJDialog();
}
public DemoJDialog() {
EventQueue.invokeLater(new Runnable() {
#SuppressWarnings({"rawtypes", "unchecked"})
#Override
public void run() {
String example = new String("Some very-very-very-"
+ "very-very-very-very-very-very "
+ "long string (really long)");
// create a textfield the size of the string!
JTextField inputCat = new JTextField(example);
inputCat.setCaretPosition(0);
String[] comboString = {"Telecast", "Radiocast"};
JComboBox comboBox = new JComboBox(comboString);
Calendar now = Calendar.getInstance();
SpinnerModel modelSpinner = new SpinnerDateModel(now.getTime(),
null, null, Calendar.MONTH);
final JSpinner spinner = new JSpinner(modelSpinner);
spinner.setEditor(new JSpinner.DefaultEditor(spinner));
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS));
listPane.add(comboBox);
listPane.add(Box.createHorizontalStrut(10));
listPane.add(inputCat);
listPane.add(Box.createHorizontalStrut(10));
listPane.add(spinner);
Object[] array = {
new JLabel("Enter a new category:"),
listPane
};
JOptionPane pane = new JOptionPane(array, JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION);
JDialog dialog = pane.createDialog(listPane, "Enter a new category:");
dialog.setVisible(true);
}
});
}
}
But JTextField is filled by the example String. And I need empty JTextField with this width
Just use constructor which specifies desired colums Count:
JTextField inputCat = new JTextField(example.length());

Get selected element's location in JList

Is it possible to get location of selected element in JList? I would like to get it to place JFrame just below clicked option.
You'll want to use JList#getCellBounds
int selectedIndex = list.getSelectedIndex();
Rectangle bounds = list.getSelectedBounds(selectedIndex, selectedIndex);
This will give you the location of the selected item within context to the JList, you'll need to translate this to screen space...
Point p = bounds.getLocation();
SwingUtilities.convertPointToScreen(p, list);
You may also want to take a look at The Use of Multiple JFrames: Good or Bad Practice?
For example...
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class List {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new List();
}
public List() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
final JFrame selected = new JFrame("Selected");
selected.add(new JLabel("Here I am"));
selected.pack();
DefaultListModel model = new DefaultListModel();
for (int index = 0; index < 1000; index++) {
model.addElement("#" + index);
}
final JList list = new JList(model);
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
int index = list.getSelectedIndex();
Rectangle bounds = list.getCellBounds(index, index);
Point p = bounds.getLocation();
p.y += bounds.height;
SwingUtilities.convertPointToScreen(p, list);
p.x -= selected.getWidth();
selected.setLocation(p);
selected.setVisible(true);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(list));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
You can use indexToLocation() method of JList, for example:
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TestFrame extends JFrame {
public TestFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
init();
pack();
setVisible(true);
}
private void init() {
final JPopupMenu menu = new JPopupMenu("test");
menu.add(new JMenuItem("1"));
final JList<String> list = new JList<String>(new String[]{"1","2","3"});
list.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
int selectedIndex = list.getSelectedIndex();
if(selectedIndex != -1){
Point indexToLocation = list.indexToLocation(selectedIndex);
Rectangle cellBounds = list.getCellBounds(selectedIndex, selectedIndex);
menu.show(list, indexToLocation.x, indexToLocation.y+cellBounds.height);
}
}
});
add(list);
}
public static void main(String... strings) {
new TestFrame();
}
}

How is JSpinner different than other swing components?

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);
}
}
}
}
}

Categories

Resources