My main frame contains JScrollPane which lists some objects. Through menu (pop up frame) I create new object and I want to list this object in the JScrollPane (which is created in a constructor of DemoFrame class). How can I do it?
Part of my constructor in DemoFrame
ArrayList<Item> i = g.getAllItems();
Vector allItemsVector = new Vector(i);
JList items = new JList(allItemsVector);
panel.add( new JScrollPane( items ))
In pop up frame I add new object to 'g' object in that case. Have I designed it wrong?
A lot depends on information that you haven't told us, for instance just what is the JScrollPane holding? A JTable? A JList? The key will be to update the component being held by the JScrollPane and then revalidate and repaint this component.
Edit
You need to have a reference to the JList, so it should be declared outside of your constructor. For instance:
// GUI class
public class GuiClass {
private JList items; // declare this in the *class*
// class's constructor
public GuiClass() {
ArrayList<Item> i = g.getAllItems();
Vector allItemsVector = new Vector(i);
// JList items = new JList(allItemsVector); // don't re-declare in constructor
items = new JList(allItemsVector);
panel.add( new JScrollPane( items ))
}
Then later in your menu's listener code you can add an item to the items JList as needed.
This was a problem for me as well. A quick workaround is remove the JScrollPane from the panel, make your changes then readd it. Many may deem it inefficient, but it works with no significant change to runtime
JPanel panel = new Jpanel();
JList list = new JList({"this", "is", "a test", "list"});
JScrollPane sPane = new JScrollPane();
public void actionPerformed(ActionEvent e) {
if (resultsPane!=null){
panel.remove(sPane);
}
sPane = updatePane(list);
panel.add(sPane);
}
public void updatePane(String[] newListItems) {
DefaultListModel model = new DefaultListModel();
for(int i = 0; i < newListItems.length; i++) {
model.addElement(newListItems[i]);
}
JList aList = new JList(model);
JScrollPane aPane = new JScrollPane(aList);
}
Assuming I understood the question correctly:
You have a JFrame with a JScrollPane. And the JScrollPane has a JList.
The JList has a set of strings in it and this shows fine, but later you want to update the list and have it update in the JFrame view, but when you do update the list nothing happens to visualisation?
I had the same problem and how I got it to work was to set the content of the JList using a DefaultListModel. Instead of updating the contents of the JList, I update the contents in the DefaultListModel and then set the JList content to the model content when everything has been added. Then call the JScrollPane repaint function
//Declare list and pane variables up here so that we have a reference
JList<String> list;
JScrollPane pane;
//Set up the frame content
void SetupFrame() {
//instantiate the list
list = new JList();
//sets up the scroll pane to take the list
pane = new JScrollPane();
pane.setViewportView(list);
pane.setBounds(10, 10, 200, 80);
//adds the scrollpane to the frame
add(pane);
//update the list of strings
UpdateList();
}
//Updates the contents of the list (call this whenever you want to update the list)
void UpdateList() {
//model used to update the list
DefaultListModel model = new DefaultListModel();
//Update the contents of the model
for (int i = 0; i < 10; i++)
model.addElement("Test value");
//update the list using the contents of the model
connectionLabels.setModel(model);
//repaint the scrollpane to show the new list content
pane.repaint();
}
Related
I need help understanding how JTable can be implemented. My JTable does not show up when given header names and data, I have tried pack() (makes my everything but my menu disappear), I have tried setFillsViewportHeight(true) and nothing updated. Any help or guidance would be appreciated.
// Main
public static void main(String[] args) {
Main window = new Main("A Project");
window.setBounds(30, 30, 700, 500);
window.setVisible(true);
}
// Displays a box with a menu bar that has file and about options(code not shown):
public Main(String title) {
JMenuBar menuBar = new JMenuBar(); // Window menu bar
setTitle(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setJMenuBar(menuBar); // Add the menu bar to the window
}
// This section of code is inside action listener when you click menu bar's file then load a file:
// Nothing appears:
String[] columnNames = {"ID","First Name","Last Name","Program","Level","USERNAME"};
ArrayList[][] data = loadFileRoster.getRosterData();
JTable table = new JTable(data,columnNames);
JScrollPane scrollPane = new JScrollPane();
table.add(scrollPane);
table.setVisible(true);
ArrayList[][] data = loadFileRoster.getRosterData();
JTable table = new JTable(data,columnNames);
I'm not aware that you can create a JTable using an ArrayList containing your data (unless is new in JDK 14)
JScrollPane scrollPane = new JScrollPane();
table.add(scrollPane);
You don't add a scroll pane to a table. You add a JTable to the JViewport of a JScrollPane. This is done by using:
JScrollPane scrollPane = new JScrollPane( table );
You then add the scroll pane to the frame.
table.setVisible(true);
Swing components are visible by default. The setVisible(true) is unnecessary.
Read the section from the Swing tutorial on How to Use Tables for working examples.
Download the example and modify them. They will show you how to better structure your code.
I'm trying to setup a basic GUI Library that will import a list of books and display each book as a JButton within a scroll pane. But, before getting there I'm just trying to orient the panels first and adding a test button to make sure the basics are working before moving on to the details.
I've tried moving code around to add panels in different orders to see if that was an issue but keep getting the same result. I'm completely new to this, so my understanding of it is very limited.
public class LibraryPanel extends JPanel{
private Library library;
private JPanel bookButtons, importBooks;
JScrollPane bookList;
JTextField importField;
JButton load;
public LibraryPanel() {
setPreferredSize(new Dimension(200,500));
Library library = new Library();
setLayout(new BorderLayout());
this.setBorder(BorderFactory.createTitledBorder("Library"));
// Import Books Panel
importBooks = new JPanel();
importBooks.setLayout(new BoxLayout(importBooks,BoxLayout.X_AXIS));
importBooks.setBorder(BorderFactory.createTitledBorder("Import Books"));
importField = new JTextField(15);
importBooks.add(importField);
load = new JButton("Load");
importBooks.add(load);
this.add(importBooks,BorderLayout.SOUTH);
load.addActionListener(new loadButtonListener());
// Book List buttons
JPanel bookButtons = new JPanel();
bookButtons.setLayout(new BoxLayout(bookButtons,BoxLayout.Y_AXIS));
JButton testButton = new JButton("TEST Button");
bookButtons.add(testButton);
//for(int i = 0; i<library.getBooks().size(); i++) {
// BookButton button = new BookButton(library.getBook(i));
//button.addActionListener(new BookButtonListener());
// bookButtons.add(button);
//}
// Scroll Pane
bookList = new JScrollPane();
bookList.setBorder(BorderFactory.createTitledBorder("Book List"));
bookList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
bookList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.add(bookList,BorderLayout.CENTER);
bookList.add(bookButtons);
}
private class loadButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String filename = new String(importField.getText());
library.loadLibraryFromCSV(filename);
}
}
}
However, I'm having an issue with the test button not showing up at all within the scroll pane. The panels are there but not the test button.
You can't "add" components to a JScrollPane, this isn't how they work. A JScrollPane uses a JViewport as it's primary component, which is then used to determine when the scrollbars should be used.
See How to Use Scroll Panes for more details
Instead of...
bookList = new JScrollPane();
//...
bookList.add(bookButtons);
simply do...
bookList = new JScrollPane(bookButtons);
//...
//bookList.add(bookButtons);
I am new to java swing. I have a code that generates checkboxes. I want to have a button somewhere in my frame, which on clicking, should delete the selected checkbox entries. Here is what I have so far.
public class Scroll extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("JFrame with ScrollBar");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ResultButtonBar();
newContentPane.setOpaque(true);
JScrollPane scrollPane = new JScrollPane(newContentPane);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.getContentPane().add(scrollPane);
frame.setSize(800, 800);
frame.setVisible(true);
JButton startButton = new JButton("Start");
frame.add(startButton, BorderLayout.SOUTH);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null, "basdsadad");
}
});
}
}
and the new ResultButtonBar().java
public class ResultButtonBar extends JPanel {
private HashMap<JCheckBox, ArrayList<Integer>> map = new HashMap<>();
private JLabel _label;
private static final int MAX_CHECKS = 1000;
public ResultButtonBar() {
super();
JButton btn = new JButton();
btn.setVisible(true);
JCheckBox checkBox;
Random r = new Random();
JPanel checkPanel = new JPanel(new GridLayout(0, 1));
_label = new JLabel("You selected nothing");
checkPanel.add(_label);
for (int i = 0; i < MAX_CHECKS; i++) {
StringBuilder sb = new StringBuilder();
ArrayList<Integer> a = new ArrayList<>();
for (int j = 0; j < 2; j++) {
Integer temp = (r.nextInt()) % 100;
a.add(temp);
sb.append(temp).append(" ");
}
checkBox = new JCheckBox(sb.toString().trim());
checkBox.setName("CheckBox" + i);
map.put(checkBox, a);
checkPanel.add(checkBox);
}
add(checkPanel);
}
}
First of all, keep all your check boxes in an ArrayList so you will have a reference to them when you need it.
Then, add a JButton wherever you need. Then iterate over this ArrayList and call invalidate() on the component which contains your check boxes. Next statement would be to call the remove() method on the container; the checkPanel.
Alternatively, you may call removeAll() if all the components in the container are check boxes and you want to remove them.
The alternative pointed by StanislavL is also a good one if you have a lot of different components along with check boxes
I can think of two approaches:
if You are maintaining one JPanel instance which contains only the instances of JCheckBox, then you can first get all the checkbox's using panel.getComponents() method, check their selection state and depending on the state remove it by calling panel.remove(component). For example:
Component checkBox[] = checkBoxPanel.getComponents();
for(Component c:checkBox)
if(((JCheckBox)c).isSelected())
checkBoxPanel.remove(c);
checkBoxPanel.revalidate();
checkBoxPanel.repaint();
The last call revalidate() and repaint() on the checkBoxPanel is important for reflecting changes on the layout and graphics rendering of the components.
You can use ItemListener with the instances of JCheckBox to do things on selection state change. Use an instance of ArrayList<JCheckBox> to add the selected checkBox to the list. However you should use an implemented ItemListener: MyItemListener implements ItemListener and create one instance and add this instances to all the checkboxes to react on state change. You can use event source e.getSource() to get the JCheckBox instance on which the ItemEvent is performed.
Tutorial resource:
How to Write an Item Listener
Here is my code to create a Jlist and filling it up using action listener
At the first place I used an array of string to fill up the Jlist and I had scroller.
Then for upating Jlist I need to change the mode of the Jlist to DefaultListModel and as soon as I did that change I lost my scroller.
I donot know what went wrong
Can any one help me please
private Component makeListView() {
final DefaultListModel<String> listModel = new DefaultListModel<String>();
final JList<String> list = new JList<String>(listModel);
list.setModel(listModel);
updateCourseListPanel(listModel);
notifyObserverInModelForClickingOnListItem(list);
list.setPreferredSize(getSize());
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(-1);
list.setFixedCellWidth(80);
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(getMaximumSize());
setVisible(true);
return list;
}
hard to tell from your snippet (as you didn't show the code that calls it): on face value, the issue is that you return the list instead of the scrollPane it's added to.
The deeper issue is that you seem to (guessing only, though, for lack of details :-) re-create the list whenever the data needs to be updated. A better approach is to separate the creation of the list and its model from its update and only update the model as needed:
private Component makeListView() {
final DefaultListModel<String> listModel = new DefaultListModel<String>();
final JList<String> list = new JList<String>(listModel);
list.setModel(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setFixedCellWidth(80);
JScrollPane listScroller = new JScrollPane(list);
return listScroller;
}
private void update(Jlist list) {
updateCourseListPanel(list.getModel());
notifyObserverInModelForClickingOnListItem(list);
}
BTW, never-ever call any of the setXXSize methods, some reasons
I'm very new to Java.
I've created two JLists in which you can add and remove 'shopping cart' items.
Once the user has added all their items they can click a submit button to view their selected items in a new window.
My first list is itemList (populated with items from array), the second list is shoppinglist which gets populated with whatever the user selects with a JButton.
Additional arrays are created to handle the actions of the buttons moving the items to and from the JLists. I've tried a few things, but haven't been successful in showing the items that get selected and shown in shopinglist to appear in a new window once submit is hit.
Any help is much appreciated.
//Create itemList
itemList = new JList(shopping);
contentPane.add(itemList);
itemList.setVisibleRowCount(10);
itemList.setFixedCellHeight(20);
itemList.setFixedCellWidth(140);
itemList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//Add JScrollPane to maintain size
JScrollPane list1 = new JScrollPane(itemList);
//contentPane.add(list1);
//Create shoppingList
shoppingList = new JList(items);
contentPane.add(shoppingList);
shoppingList.setVisibleRowCount(10);
shoppingList.setFixedCellHeight(20);
shoppingList.setFixedCellWidth(140);
shoppingList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//Add JScrollPane to maintain size
JScrollPane list2 = new JScrollPane(shoppingList);
JPanel buttonPanel = new JPanel();
//contentPane.add(list2);
Buttonin = new JButton(">>");
//Buttonin.setBounds(144, 46, 60, 23);
Buttonin.addActionListener(this);
buttonPanel.add(Buttonin);
ButtonOut = new JButton("<<");
//ButtonOut.setBounds(144, 80, 60, 23);
ButtonOut.addActionListener(this);
buttonPanel.add(ButtonOut);
JPanel submitPanel = new JPanel();
submitButton = new JButton("Submit");
submitPanel.add(submitButton);
submitButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent az) {
JFrame frame = new JFrame ("Go Shopping!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyPanel2());
frame.pack();
frame.setVisible(true);
}
});
contentPane.add(list1);
contentPane.add(buttonPanel);
contentPane.add(list2);
contentPane.setOpaque(true);
contentPane.add(submitPanel);
return contentPane;
}
public void actionPerformed(ActionEvent e)
{
int i = 0;
//When in buttonin is pressed index and value of selected item is output to array
if (e.getSource() == Buttonin)
{
int[] fromindex = itemList.getSelectedIndices();
Object[] from = itemList.getSelectedValues();
//add items to the shoppingList
for (i = 0; i < from.length; i++)
{
items.addElement(from[i]);
}
//Must remove items that are selected from the itemList
for (i = (fromindex.length-1); i >= 0; i--)
{
shopping.remove(fromindex[i]);
}
}
//When out button is pressed index and value of selected item is output to new array
else if (e.getSource() == ButtonOut)
{
Object[] to = shoppingList.getSelectedValues();
int [] toindex = shoppingList.getSelectedIndices();
//add items to previous list
for(i = 0; i < to.length; i++)
{
shopping.addElement(to[i]);
}
//Must remove what's deselected
for (i = (toindex.length-1); i >= 0; i--)
{
items.remove(toindex[i]);
}
}
Ok, bear with me (very very new to java) is this how I would set up the constructor to reference to ProfileFrame objects? And if so how do I change my main to reflect the new constructor?
public class GoShopping extends JPanel {
private JList shopList;
public GoShopping(ProfileFrame slist) {
//construct components
shopList = new JList(slist.getListModel());
shopList.setBounds(6, 6, 123, 166);//don't worry I'm changing the layout
add(shopList);
}
public static void main (String[] args) {
JFrame frame = new JFrame ("MyPanel");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//I need new GoShopping to reflect the new constructor, but not sure how to make it work
frame.getContentPane().add (new GoShopping());
frame.pack();
frame.setVisible (true);
}
}
You're creating a new ProfileFrame object in your MyPanel2 constructor, and since this is not the same instance as the visualized ProfileFrame object, then its JList's model will be null. A bad solution is to use static variables -- just don't do this please. A better solution is to pass a reference to the true visualized ProfileFrame object into your MyPanel2 constructor and call the public methods off of this instance.
And again, don't use null layout and setBounds(...), but instead use the layout managers unless you like making things more difficult than they need to be.