The GUI has a search bar that when the user types a book and click search, it pops up on the JList. But I don't know how to write the code for it.
public void actionPerformed(ActionEvent e) {
if (e.getSource() == searchButton) {
// Action for the SEARCH button
Keep the original unfiltered data in a structure (e.g an ArrayList) and add a DocumentListener to the search textfield in order to know whether the search text has been changed. Then, filter the original data and removeAllElements() from JList's model. Finally add the the filtered data to the model of JList.
Example:
public class SearchInJList extends JFrame implements DocumentListener {
private static final long serialVersionUID = -1662279563193298340L;
private JList<String> list;
private List<String> data;
private DefaultListModel<String> model;
private JTextField searchField;
public SearchInJList() {
super("test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
searchField = new JTextField();
searchField.getDocument().addDocumentListener(this);
add(searchField, BorderLayout.PAGE_START);
createData();
list = new JList<>(model = new DefaultListModel<>());
data.forEach(model::addElement);
add(new JScrollPane(list), BorderLayout.CENTER);
setSize(500, 500);
setLocationByPlatform(true);
}
private void createData() {
data = new ArrayList<String>();
for (int i = 0; i < 1000; i++) {
String s = "String: " + i + ".";
data.add(s);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
SearchInJList example = new SearchInJList();
example.setVisible(true);
});
}
#Override
public void insertUpdate(DocumentEvent e) {
search();
}
#Override
public void removeUpdate(DocumentEvent e) {
search();
}
#Override
public void changedUpdate(DocumentEvent e) {
search();
}
private void search() {
List<String> filtered = data.stream().filter(s -> s.toLowerCase().contains(searchField.getText().toLowerCase()))
.collect(Collectors.toList());
model.removeAllElements();
filtered.forEach(model::addElement);
}
}
It does not work with a button, but I guess this is something you can do. I mean add the search() method into button's action listener.
So for every button press you can:
Fill a DefaultListModel with the strings that match the search criteria.
Create a new JList with the model of the previous step.
Pop a JOptionPane with the list of the previous step as its message.
Example code:
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Main {
public static void main(final String[] args) {
final String[] data = new String[]{"abcdef", "ABCdEF", "defGhi", "DEFghi"};
final JTextField textField = new JTextField(20);
final JButton searchButton = new JButton("Search");
searchButton.addActionListener(e -> {
final String searchText = textField.getText().toLowerCase();
final DefaultListModel<String> model = new DefaultListModel<>();
for (final String str: data)
if (str.toLowerCase().contains(searchText))
model.addElement(str);
final JList<String> list = new JList<>(model);
JOptionPane.showMessageDialog(searchButton, list);
});
final JPanel panel = new JPanel();
panel.add(textField);
panel.add(searchButton);
final JFrame frame = new JFrame("Search form");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Related
I was wondering if there is a way, by selecting an item with a JList, to let the program perform some code. This code should run every time a new item is selected.
Previously, I had added a listener. Here is a minimal example I made.
public class Driver {
public static void main(String[] args) {
JFrame frame = new ListFrame();
frame.setVisible(true);
frame.setSize(200,100);
}
}
public class ListFrame extends JFrame {
private JList<String> list;
private JScrollPane scrollPane;
private String[] data = {"A","B","C"};
private JButton addButton = new JButton("Add");
public ListFrame() {
setLayout(new BorderLayout());
list = new JList<String>(data);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollPane = new JScrollPane(list);
add(scrollPane, BorderLayout.CENTER);
add(addButton, BorderLayout.SOUTH);
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
String newEntry = JOptionPane.showInputDialog("Add new entry.");
String[] tempData = new String[data.length + 1];
for(int i = 0; i < data.length; i++)
tempData[i] = data[i];
tempData[data.length] = newEntry;
data = tempData;
list = new JList<String>(data);
scrollPane.setViewportView(list);
}
});
list.addListSelectionListener(
new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
System.out.println("Hi");
}
});
}
}
However, when I click an item on the Jlist, nothing is printed.
Your example uses getSelectionModel() to get the the list's ListSelectionModel, and it adds your listener directly to the selection model. This bypasses the ListSelectionHandler, used internally by JList, which never gets a chance to fireSelectionValueChanged(). Instead, let JList add your listener:
list.addListSelectionListener(new ListSelectionListener() {...}
when I click an item on the JList, nothing is printed.
Your new example prints "Hi" when I click an item, but I see some problems:
Be sure to run on the event dispatch thread.
Check the ListSelectionEvent for details of what happened.
To add elements to the list, don't create a new JList; update the list's ListModel instead.
See How to Write a List Selection Listener for more; here's the example I tested.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Driver {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new ListFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
});
}
private static class ListFrame extends JFrame {
private final String[] data = {"A", "B", "C"};
private final DefaultListModel model = new DefaultListModel();
private final JList<String> list = new JList<>(model);
private final JButton addButton = new JButton("Add");
public ListFrame() {
for (String s : data) {
model.addElement(s);
}
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
add(new JScrollPane(list), BorderLayout.CENTER);
add(addButton, BorderLayout.SOUTH);
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
String newEntry = JOptionPane.showInputDialog("Add new entry.");
model.addElement(newEntry);
}
});
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
System.out.println(e.getFirstIndex() + " " + e.getLastIndex());
}
}
});
}
}
}
I have 2 windows. one got an empty JList and the other one got a button. So I want to add the value to the list whenever I press the button. Here is my code but not completed:
Window 1
final DefaultListModel<String> favouriteNames = new DefaultListModel<String>();
JList namesList = new JList(favouriteNames);
Window 2
public class button extends JFrame {
private JList namesList;
private DefaultListModel<String> favouriteNames;
this.namesList = namesList;
JButton addThis = new JButton("Add");
addThis.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
favouriteNames.addElement("Jack");
}
});
}
}
Pass an instance of your DefaultListModel to Window 2 in the constructor.
Edited to add: Here's how you pass an instance in a constructor.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ButtonFrame implements Runnable {
private JFrame frame;
private DefaultListModel favouriteNames;
public ButtonFrame(final DefaultListModel favouriteNames) {
this.favouriteNames = favouriteNames;
}
#Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton addThis = new JButton("Add");
addThis.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
favouriteNames.addElement("Jack");
}
});
frame.add(addThis);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new ButtonFrame(new DefaultListModel()));
}
}
I made a simpler version of my program, but still have a problem, I believe the ActionPerformed sends the data but the JList does not recognise it or or basically did not expect to receive it. So here is what I have done so far. So it is a bit more of my research and attempts, maybe it gives more details about the problem.
Main Window:
public class main {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new ClassA();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
ClassA:
public class ClassA extends JFrame {
DefaultListModel<String> myList;
JList list;
public ClassA() {
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2,1));
myList = new DefaultListModel<String>();
list = new JList(myList);
//ClassB sendsText = new ClassB(myList, list);
JButton find = new JButton("Find");
find.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
new ClassB().setVisible(true);
}
});
add(panel);
panel.add(find);
panel.add(list);
}
}
ClassB:
public class ClassB extends JFrame {
DefaultListModel<String> myList;
JList list;
public ClassB(DefaultListModel<String> myList, JList list){
this.myList = myList;
this.list = list;
}
public ClassB() {
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2,1));
JButton addMe = new JButton("Add Me");
addMe.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
myList.addElement("Danial");
}
});
add(panel);
panel.add(addMe);
}
}
This is my first post and I think I am doing it right.
I have a program that takes the user input from a AutoComplete jComboBox and then send's the input to be stored into a text file.(AutoComplete is done using the library glazedlists_java15/1.8.0).
After using the Autocomplet feature I had to set the jComboBox to DefaultComboBoxModel.
When the user presses the Enter key, the jComboBox should update the list with the new Item typed from the keyboard, so the user can see the last typed item in the jComboBox list.
This is done by removing all the items from the jComboBox and then inserting them again .
The problem is that before having the AutoComplete feature I could just say jComboBox1.removeAllItems(); but now because of the model I have to do it with model.removeAllElements();
public class Test {
final static DefaultComboBoxModel model = new DefaultComboBoxModel();
static JComboBox c = new JComboBox(model);
private static final long serialVersionUID = 1L;
private static JButton b = new JButton();
static JFrame f = new JFrame();
/**
* #param args
*/
public static void TestFrame() {
String[] a = {"hi1" , "hi2", "hi3", "hi4","hi5"};
AutoCompleteSupport support = AutoCompleteSupport.install(c,
GlazedLists.eventListOf(a));
JPanel test = new JPanel();
test.add(b);
test.add(c);
model.addElement(a);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.removeAllElements();
}
});
f.add(test);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.setSize(500,500);
}
The problem is that model.removeAllElements(); and model.addElement(s); is not working so I can not update the jComboBox. Can you please take your time and help me find a solution. Thanks!
Edit:
I don´t know where your problem is, this is totally working for me
final DefaultComboBoxModel model = new DefaultComboBoxModel();
JComboBox c = new JComboBox(model);
private static final long serialVersionUID = 1L;
private JButton b = new JButton();
public TestFrame() {
JPanel test = new JPanel();
test.add(b);
test.add(c);
model.addElement("hi");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.removeAllElements();
}
});
this.add(test);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setSize(500,500);
}
maybe you don´t reach your keylistener
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.swing.AutoCompleteSupport;
public class TestFrame
{
private static JComboBox c = new JComboBox();
private static JButton b = new JButton();
private static JFrame f = new JFrame();
private static String[] a = {"hi1", "hi2", "hi3", "hi4", "hi5"};
public static void TestFrame()
{
final EventList<String> items = GlazedLists.eventListOf(a);
AutoCompleteSupport.install(c, items);
JPanel test = new JPanel();
test.add(b);
test.add(c);
c.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
c = (JComboBox) e.getSource();
if (e.getActionCommand().equals("comboBoxEdited"))
{
items.clear();
}
}
});
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
items.clear();
}
});
f.add(test);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.setSize(500, 500);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
TestFrame();
}
});
}
}
I am trying to create a way to update a JComboBox so that when the user enters something into the text field, some code will process the entry and update the JComboBox accordingly.The one issue that I am having is I can update the JComboBox, but the first time it is opened, the box has not refresh the length of the options in it and as seen in the code below it displays extra white space. I do not know if there is a better different way to do this, but this is what I came up with.
Thanks for the help,
Dan
import java.awt.event.*;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Catch{
public static JComboBox dropDown;
public static String dropDownOptions[] = {
"Choose",
"1",
"2",
"3"};
public static void main(String[] args) {
dropDown = new JComboBox(dropDownOptions);
final JTextField Update = new JTextField("Update", 10);
final JFrame frame = new JFrame("Subnet Calculator");
final JPanel panel = new JPanel();
frame.setSize(315,430);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Update.addFocusListener(new FocusListener(){
public void focusGained(FocusEvent arg0) {
}
public void focusLost(FocusEvent arg0) {
dropDown.removeAllItems();
dropDown.insertItemAt("0", 0);
dropDown.insertItemAt("1", 1);
dropDown.setSelectedIndex(0);
}
});
panel.add(Update);
panel.add(dropDown);
frame.getContentPane().add(panel);
frame.setVisible(true);
Update.requestFocus();
Update.selectAll();
}
}
1) JTextField listening for ENTER key from ActionListener
2) remove FocusListener
3) example about add new Item as last Item from JTextField to the JList, only you have to modify for JComboBox and add method insertItemAt() correctly
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ListBottom2 {
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame();
private DefaultListModel model = new DefaultListModel();
private JList list = new JList(model);
private JTextField textField = new JTextField("Use Enter to Add");
private JPanel panel = new JPanel(new BorderLayout());
public ListBottom2() {
model.addElement("First");
list.setVisibleRowCount(5);
panel.setBackground(list.getBackground());
panel.add(list, BorderLayout.SOUTH);
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(new Dimension(200, 100));
frame.add(scrollPane);
frame.add(textField, BorderLayout.NORTH);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JTextField textField = (JTextField) e.getSource();
DefaultListModel model = (DefaultListModel) list.getModel();
model.addElement(textField.getText());
int size = model.getSize() - 1;
list.scrollRectToVisible(list.getCellBounds(size, size));
textField.setText("");
}
});
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() {
ListBottom2 frame = new ListBottom2();
}
});
}
}
I am trying to create a JScrollPane component which can be reused depending upon the string parameter that is being passed..
I have created the following code, it works if I use JFrame to embed the JScrollPane inside it,
but when I try to reuse the code in creating different JScrollPane the scrollPane is not displayed at all..
I am implementing it in a java swing project..
Please let me know what should be done in this..any suggestions are highly appreciated.
The same problem I have with regards to the JComboBox, it doesn't display...
public class ListComponent extends JScrollPane {
private String[] selectedNames;
private String[] listNames;
private JButton submit, reset;
private JPanel subPanel = new JPanel();
private JList list;
private JScrollPane scroll;
public String getFirstSelectionInList() {
return selectedNames[0];
}
ListComponent() {
/*submit = new JButton("Submit");
reset = new JButton("Reset");*/
subPanel.setLayout(new FlowLayout());
/*subPanel.add(submit);
subPanel.add(reset);*/
}
ListComponent(String[] listNames) {
this();
/*JFrame frame = new JFrame("Creating a JList Component");*/
this.listNames = new String[listNames.length];
this.listNames = listNames;
//this.setLayout(new BorderLayout());
//this.setLayout(new ScrollPaneLayout());
JPanel panel = new JPanel();
list = new JList(listNames);
scroll = new JScrollPane(list);
scroll.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
/*panel.add(scroll);
panel.add(subPanel,BorderLayout.SOUTH);*/
/*frame.add(panel);
frame.pack();
frame.setVisible(true);*/
this.setVisible(true);
list.addListSelectionListener(listSelectionListener);
}
ListSelectionListener listSelectionListener = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent listSelectionEvent) {
boolean adjust = listSelectionEvent.getValueIsAdjusting();
//System.out.println(", Adjusting? " + adjust);
if (!adjust) {
JList list = (JList) listSelectionEvent.getSource();
int selections[] = list.getSelectedIndices();
Object selectionValues[] = list.getSelectedValues();
int n = selections.length;
selectedNames = new String[n];
for (int i = 0; i < n; i++) {
if (i == 0) {
System.out.print(" Selections: ");
}
selectedNames[i] = (String) selectionValues[i];
System.out.print(selectedNames[i]
+ "/" + selectionValues[i]);
}
}
}
};
/** #return the selectedNames */
public String[] getSelectedNames() {
return selectedNames;
}
/** #param selectedNames the selectedNames to set */
public void setSelectedNames(String[] selectedNames) {
this.selectedNames = selectedNames;
}
public static void main(String args[]) {
String subject[] = {"Math", "Computer", "Phisics", "Chemestry"};
new ListComponent(subject);
}
}
#camickr is correct; JPanel is a better "general-purpose container for lightweight components." You can add additional components to the other areas of the BorderLayout used in the example below. It's also a good habit to build your GUI on the event dispatch thread.
import java.awt.*;
import java.util.Arrays;
import javax.swing.*;
import javax.swing.event.*;
/** #see http://stackoverflow.com/questions/4176343 */
public class ListPanel extends JPanel {
private JList list;
public ListPanel(String[] data) {
super(new BorderLayout());
list = new JList(data);
list.addListSelectionListener(new SelectionHandler());
JScrollPane jsp = new JScrollPane(list);
this.add(jsp, BorderLayout.CENTER);
}
private class SelectionHandler implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
System.out.println(Arrays.toString(list.getSelectedValues()));
}
}
}
private void display() {
JFrame f = new JFrame("ListPanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
String[] data = {"Math", "Computer", "Physics", "Chemistry"};
new ListPanel(data).display();
}
});
}
}
public class ListComponent extends JScrollPane
What? You should not be extending a JScrollPane. You are not adding new functionality to the scroll pane.
If you are trying to add a JList to a JScrollPane, then I suggest you read the JList API and follow the link to the Swing tutorial on "How to Use Lists" for a working example.