I've looked for the answer to this on SO and elsewhere but can't find an answer. Is it possible to select an entire jlist rather than a specific item? For example if a user were to click on the white area of a jlist I could call a method which would put that jlist's name in a HashMap or call another method to alter the list as a whole. Hopefully the code gives you an idea. Any info would be helpful. Thanks.
final JList list_1 = new JList(list1);
list_1.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent arg0) {
//make entire list disappear when selected
list_1.setVisible(false);
}
});
GridBagConstraints gbc_list_1 = new GridBagConstraints();
gbc_list_1.gridheight = 3;
gbc_list_1.insets = new Insets(0, 0, 5, 5);
gbc_list_1.fill = GridBagConstraints.BOTH;
gbc_list_1.gridx = 5;
gbc_list_1.gridy = 0;
panel.add(list_1, gbc_list_1);
Is it possible to select an entire jlist rather than a specific item?
Yes, as long as the ListSelectionModel allows you to do that. See Selecting Items in a List.
For example if a user were to click on the white area of a jlist...
Better than that is to have a "Select All" kind of button and work with the ListSelectionModel so you don't have to mess with the focus subsystem at all. For example:
final JList list = new JList();
...
Action selectAllAction = new AbstractAction("Select All") {
#Override
public void actionPerformed(ActionEvent e) {
list.getSelectionModel().setSelectionInterval(0, list.getModel().getSize() - 1);
}
};
...
JButton selectAllButton = new JButton(selectAllAction);
...I could call a method which would put that jlist's name in a HashMap or call another method to alter the list as a whole.
I don't have any idea what do you mean alter the list as whole or why do you want to put that jlist's name in a HashMap, so I'm not able to help you any further. For better help please include a SSCE
Related
I was trying to write the GUI for my program. I have a Product class in which I store price and names of the products in an arraylist. I also have an Order arraylist which consists of the orders given to each waiter.I put all my products in a JComboBox and added an action listener to each to show the price of each product when clicked by updating the text of a JLable. Then there is a JSpinner to get the quantity of the products selected. And lastly there is an "Add" button that I wanted to use to update the Jtable with product name and its quantity and its total price while also adding that product to the arraylist of Orders. I have no idea how populate JTable and couldn't understand much from other answers because they were using netbeans. I thought of just using a simple JLabe but also I couldn't understand how to update the text and add a new line to the label after I select and add each product. Can you explain how I can achieve this? part of my code looks like this
box1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Product prod = (Product) box1.getSelectedItem();
price.setText(String.valueOf(prod.getSellingPrice()));
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int numbs = (Integer) spinner.getValue();
for (int i = 0; i <= numbs; i++) {
order.addProduct(prod);
}
JLabel label = new JLabel();
lists.add(label);
label.setText(prod.getName() + " " + numbs + " " + numbs * prod.getSellingPrice());
}
});
}
});
If I understand your question correctly, you want a JTable in your gui, which shows the orders (or other data possibly) if a button is clicked.
Firstable, I would advise you to check out
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html
as they explain the use of the JTable very well.
Anyway, to answer your question:
Firstable, you have to create a table and add it to your gui:
//creating a new JTable without any data and one column 'Orders'
//you might wanna declare the JTable before that, since it will be referred to in the refresh() method
JTable table = new JTable(new String[][]{{""}}, new String[]{"Orders"});
//creating a scrollpane to put the table in, in case the table data exeeds the table
JScrollPane scrollPane = new JScrollPane();
//here you would e.g. set the bounds of the scrollpane etc
scrollPane.setBounds(x,y,w,h)
//setting the table in the scrollpane
scrollPane.setViewportView(table);
//adding the scrollpane to your contentPane
contentPane.add(scrollPane);
Now you want to refresh the table, if a button is pressed, so I would put a reference to the following method in the actionlistener of the button:
//the method to refresh the table containing the orders (or possibly other data)
void refresh(List<String> orders) {
//creating a new TableModel for the table
DefaultTableModel model = new DefaultTableModel();
//set the data in the model to the data that was given, new Object[]{0} points to the 1st column
model.setDataVector(getDataVector(data), new Object[]{"Orders});
//set the model of the table to the model we just created
table.setModel(model);
}
Since model.setDataVecor() takes rows and not columns as its first parameter, you have to make the list of data fitting as a data vector, for example with the following method:
Object[][] getDataVector(List<String> data){
Object[][] vector = new Object[data.size()][1];
for(int i=0; i<data.size(); i++){
vector[i][0] = data.get(i);
}
return vector;
}
I am creating a JList using swing, I can display and select multiple items, also I can add a new element to it. However, when I select the first element of the list and add a new one to the top, I got two selected elements (the old one and the new one), but when I change the selection mode to single selection it works fine, is it possible to prevent this automatic selection and just keep the old one selected using multiple interval selection mode?
I used this link that contain an example using DataEventListner but I did not succeed to find a solution. Any help please?
Here is my list:
public static void main(String args[]) {
String labels[] = { "A", "B", "C", "D", "E", "F", "G", "H" };
JFrame frame = new JFrame("Selecting JList");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final DefaultListModel model = new DefaultListModel();
for (int i = 0, n = labels.length; i < n; i++) {
model.addElement(labels[i]);
}
JList jlist = new JList(model);
jlist.setSelectionMode(
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane scrollPane1 = new JScrollPane(jlist);
frame.add(scrollPane1, BorderLayout.CENTER);
JButton jb = new JButton("add F");
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
model.add(0, "First");
}
});
frame.add(jb,BorderLayout.SOUTH);
frame.setSize(640, 300);
frame.setVisible(true);
}
I see that you basically copied the code in the link in your question. That example only deals with adding a single element to the JList when clicking the JButton. It does not deal with the JList selection[s]. I don't think the author of that example considered what happens when the user selects one or more elements in the JList before clicking the JButton.
I was able to reproduce the behavior described in your question. It may be a bug in the implementation of JList or ListSelectionModel. The way I fixed it is to add code to method actionPerformed() that handles any existing JList selections.
Here is my modified version of method actionPerformed(). Note that all the rest of the code is unchanged. First I save the indexes of all the selected rows. Then I clear the existing selections. Then I add the new element to the JList. Now I need to re-select the rows that were selected before I added the new element. But note that I need to increment each index by one, because there is a new element at index 0 (zero).
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
int[] indices = jlist.getSelectedIndices();
jlist.getSelectionModel().clearSelection();
model.add(0, "First");
for (int index : indices) {
jlist.getSelectionModel().addSelectionInterval(index + 1, index + 1);
}
}
});
From the documentation of JList#setSelectionMode(int):
ListSelectionModel.SINGLE_SELECTION - Only one list index can be
selected at a time. In this mode, setSelectionInterval and
addSelectionInterval are equivalent, both replacing the current
selection with the index represented by the second argument (the
"lead").
try jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
You can add this in your jb.addActionListner():
int x = jlist.getSelectedIndex();
jlist.clearSelection();
jlist.setSelectedIndex(x);
This should work just the way you want it to!
So my issue that I have is implementing a functioning delete button for my GUI.
While I have just about everything working, I have been stumped with trying to implement this function. What it does is as i click the 'Add' button, it creates a row with text fields and a check box. The 'Delete' works in the sense that it only deletes the most recent field create once I click on the checkbox to delete it. My intention is that the GUI works in a dynamic way to where I can click whatever check boxes and delete only those specific rows with the boxes checked.
I've researched methods of using an ItemListener but I'm still wrestling with that as I figure its the most proficient way to go. I've also done the storing the components in an array to iterate over. I feel I'm close with what I have now, any advice appreciated.
Below is the 'Add' button code to create new rows in my GUI. Then there is the 'Delete' button code which places the components in an array, but only deletes the most recent row created that has been checked.
add = new JButton("Add");
add.addActionListener(e ->{
rowPanel = new JPanel(new GridLayout(1,4,5,5));
for(int i = 0; i < 4; i++ ){
rowPanel.add(new JTextField(8));
}
for(int l=0; l < 1; l++){
rowPanel.add(new JCheckBox(), BorderLayout.EAST);
}
infoPanel.add(rowPanel);
infoPanel.revalidate();
infoPanel.repaint();
});
delete = new JButton("Delete");
delete.addActionListener(e -> {
Component[] components = rowPanel.getComponents();
for(Component c : components){
if(c instanceof JCheckBox){
if(((JCheckBox)c).isSelected()){
infoPanel.remove(rowPanel);
}
}
}
infoPanel.revalidate();
infoPanel.repaint();
});
You can use a JTable as a container and add a custom row that is a checkbox and a textfield. This way you just have to get the checkbox's event and see what index in the JTable it is located and delete it.
This might be useful:
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#editrender
well i am making this system that has a table, and i have to put buttons in the last column. i've been researching but all the codes i saw are really confusing. there is one tho, but there are still some parts that i didn't understand. here's the site where i got it http://www.javaquery.com/2013/05/how-to-implement-jbutton-in-jtable.html
String[] InvoiceArray = new String[20];
//Declare above variable globally. Used by two-three methods. Change variable name as per your need.
/*
* import the ButtonColumn class if you are not working in IDE
* I used formWindowOpened event to load content in Jtable but you can use other event.
* All you need is put the code with in that event.
*/
private void formWindowOpened(java.awt.event.WindowEvent evt) {
Object[][] rowData = new Object[4][2]; // 4: is number of row ; 2: is number of column
Object columnNames[] = {"Invoice No", "View Report"}; // Name of columns
for (int i = 0; i < 4; i++) {
InvoiceArray[i] = i + "-2345";
rowData[i][0] = i + "-2345";
rowData[i][1] = "View Order " + i; // Can change the text of button.
}
DefaultTableModel tm = new DefaultTableModel(rowData, columnNames);
jTable1.setModel(tm);
ButtonColumn buttonColumn = new ButtonColumn(jTable1, showOrder, 1); // 1: is column number. column count starts with 0,1,2...
}
what's the InvoiceArray for? and should i make the showOrder from the last line? and also, i didn't understand the code he posted on how to make a listener on it. here it is:
Action showOrder = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
//JTable table = (JTable) e.getSource(); // If you have multiple component following the ActionEvent
int modelRow = Integer.valueOf(e.getActionCommand());
if (InvoiceArray[modelRow] != null) {
/* We are placing invoice no in array
* And track the button click index
* And fetch index in invoice no
*/
System.out.println("Your Invoice No:" + InvoiceArray[modelRow]);
} else {
JOptionPane.showMessageDialog(rootPane, "No records found!");
}
}
};
i know there are some explanations already. i understand some of them but not all. just a simplier way to add jbutton on jtable and also listeners for the jbutton. thank you so much
just a simplier way to add jbutton on jtable and also listeners for the jbutton.
There is no simple way. You need to understand how renderers and editors work in a JTable. Read the section from the Swing tutorial on Concepts: Renderers and Editors for the basics.
Then you can check out Table Button Column which does the hard work for you. You only need to provide the Action to be invoked when you click on the button.
what's the InvoiceArray for?
It is used to load data into the JTable. This is basic usage of a JTable and has absolutely nothing to do with adding a button to a column of the table.
After the data is loaded you should forget about the invoiceArray. The Action you write should access the data via the TableModel or the JTable.
I'm currently working on the GUI part of our group's first semester exam project, and I ran into a curious issue regarding callbacks and event handling.
A bit off topic: I have googled this SO hard, but have really failed to find any concrete examples of using callbacks in Java, so from what i've gathered... By definition... What i'm doing here is actually a callback (Would be awesome if you could explain why, or point me to a page that explains it thoroughly)
Here's the code:
private FocusListener callback = new FocusListener(){
#Override public void focusGained(FocusEvent e){
if(hasBeenSet){}else{tfield.setText("");hasBeenSet=true;}
} #Override public void focusLost(FocusEvent e){}};
...
tfield = new JTextField("Insert CPR number", 8);
constraint.gridx = 0;
constraint.gridy = 1;
constraint.gridwidth = 2;
panel.add(tfield, constraint);
tfield.addFocusListener(callback);
tfield = new JTextField("Type new password", 8);
constraint.gridx = 0;
constraint.gridy = 2;
panel.add(tfield, constraint);
tfield.addFocusListener(callback);
tfield = new JTextField("Retype new password", 8);
constraint.gridx = 0;
constraint.gridy = 3;
panel.add(tfield, constraint);
tfield.addFocusListener(callback);
When I start up the GUI, it has these three (3) textfields, and the idea is to remove the text when the user focuses on the textfield. This should work for all three textfields, but apparently, whatever textfield you click on, only the last textfield gets set to an empty string. I'm most curious about this since each object is instantiated individually.
The obvious workaround here, is to just rename tfield to like "tfield[1-3]", but would be great if you could humor me with this :)
Also: Please note that all the GUI code is actually inside the constructor. Yes, I know this is completely ridiculous, but our design suggests that all logic and data handling will happen after the constructor has completed... So there shouldn't be any threats here per say, but I don't know if this would somehow conflict the callback method for FocusListener.
Thank you. :)
P.S. For the "Re/type new password" fields, I do acknowledge the JComponent JPasswordField, and that will be changed after this problem is fixed. So no need for the security warning :)
The tfield variable holds the reference to the last instance of JTextField. The way to do what you want is this:
private FocusListener callback = new FocusListener() {
#Override public void focusGained(FocusEvent e){
JTextField jtf = (JTextField) e.getSource();
if(hasBeenSet){}else{jtf.setText("");hasBeenSet=true;}
}
...
Note: as your code reads at the moment, hasBeenSet will be shared across all 3 text fields.
Update:
Java has no support for closures, so when the focusGained runs, it sees the last value of tfield, not the value tfield had when the listerner was installed.
It looks like hasBeenSet is defined as a member of the outer class and as such focusGained is checking the same variable for all 3 textfields. Here is a way of handling what I think you're trying to do:
tfield = new JTextField("Insert CPR number", 8);
tfield.putClientProperty("originalText", tfield.getText());
Then in the focusGained:
#Override public void focusGained(FocusEvent e){
JTextField jtf = (JTextField) e.getSource();
if(jtf.getClientProperty("originalText").equals(jtf.getText())){
jtf.setText("");
}
}
The putClientProperty/getClientProperty methods are defined in JComponent class and so these are available in every Swing GUI component that inherits from JComponent. They store/retrieve an Object given a string. In this case the string "originalText" holds the value originally used to initialize the JTextField. Upon gaining focus, if the field still contains that value, it is set to blank. Likewise, you can perform a similar operation in focusLost where if the field is blank you set it to the value retrieved for "originalText".