Create an Interactable JList - java

As many might know, components in a JList are not interactable (you can't interact with them) and they are just like snapshots from the component's appearance. I'm working on a simple application and JList is what I want, except that the components in the list should be interactable.
So far I've created this, by implementing a simple AbstractListModel, and ListCellRenderer:
Each component in the JList is a JPanel, which as you can see contains other components like JProgressBar, JLable and JButton. The only problem is that the buttons (and all other components) are not interactable. How can I fix this ?
NOTE: I don't want a single column JTable!

Adding this answer for people in the future.
I just ran into the exact same problem, using JList and ListCellRenderer is wonderful if you only need custom rendered items, but not fully functional components.
This is what I did and works a treat:
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
and then when I have the list of the information I need to dynamically assemble the panel:
public void build(List<Item> items){
panel.removeAll();
for(Item item: items){
panel.add(new ItemEntry(item));
}
}
wrap your panel in a JScrollPane and itll work just like before only all your controls will now function properly :).

I think you answered it yourself, JList is not editable, it was not designed to be and trying to retrofit it to be, is a LOT of hard work (and yes, I've actually tried).
You "could" use a MouseListener on the JList, find the row that was clicked, translate the MouseEvent to be within the context of the ListCellRenderer's Component and try and determine what was clicked ... but, again this is a lot of additional work which can more easily be achieved through other means...
Consider using a layout to generate a list of vertically aligned components instead, maybe VerticalLayout from SwingX or BoxLayout for example

Related

Java: JScrollPane didn't show scroll bars

I am developing a small desktop application in Java using Netbeans. On my jframe i have various pannels and one scroll panes. The purpose of this JScrollPane is to show some visual elements to its users. I achieve this by following the below steps in sequence:
Drag and drop JScrollPane at desired location of my JFrame
Adjust the size of JScrollPane according to my needs.
Write a new java class and extend that class with JPanel
Override the public void paintComponent(Graphics g) method
Then i add that panel to above JScrollPane,
using following code:
JPanel jpnl = new myClass();
jScrollPane2.setViewportView(jpnl);
jScrollPane2.repaint();
Now every thing is working fine as per my requirements, the only thing which is lacking is that when my drwaing is big then no sroll bars are shown at JScrollPane. This is my first application and i don't know much about Java, so any guidence regarding what is missing would be highly appreciated
Remember to add the required component to the JScrollPane object, and the scroll pane object to the panel. Also, it could be that you need to change the scroll bar policy: use scroll pane's setHorizontalScrollBarPolicy() and setVerticalScrollBarPolicy().
Consult the JScrollPane documentation for these methods.

Refresh Panel on CardLayout Swap

How do you refresh a JPanel on the panel change from container CardLayout?
Use the show() method. From the Java API:
Flips to the component that was added to this layout with the specified name, using addLayoutComponent. If no such component exists, then nothing happens.
CardLayout#first(), next(), and previous() do something similar.
Sometimes, when I've made a panel swap like this (though not that I can remember on CardLayout, but it's been a while since I used it), I've also needed to pack the frame again. If that doesn't work, you can call revalidate(), which lets Swing know that the component needs to be redrawn.
You may also want to consider using a tabbed pane, as it does a lot of this for you; I started out a project trying to use CardLayout and decided to use a the tabbed pane instead. Depends on what you want to do, of course.
Is there an actionlistener or something that I can have it reload/refresh my data on that screen?
Assuming you have a model that supplies data to your view (panel), two approaches are common:
Arrange for your model to extend Observable and your view to register as an Observer.
Arrange for your model to manage an EventListenerList, in effect creating you own analog of ActionEvent.
In either approach, use the listener of the control that switches views tell the model to update its registered observers/listeners. The example in How to Use CardLayout uses a JComboBox and itemStateChanged(). There's additional discussion here.
Is there an actionlistener or
something that I can have it
reload/refresh my data on that screen?
You can use an AncestorListener. It fires when a component is added to a Container. So when you swap cards the event is fired. You would need to add the listener to each panel you add to the CardLayout:
Another problem with the CardLayout is that the panel doesn't gain focus when it is swapped. I use this approach to set focus on the panel. Check out Card Layout Focus.
panel.addAncestorListener(...);
The show() method does the trick of switching panels, but it doesn't "refresh" the data. Is there an actionlistener or something that I can have it reload/refresh my data on that screen?

Java Swing Scrollpane in NetBeans

I have Java application which adds JTextFields # runtime to JPanel. Basically user clicks a button and new JTextField is added, clicks again added again...
Each new JTextField is directly below the previous one. Obviously I run out of space pretty soon so I'm trying to use JScrollPane and thats where the hell begins, because it just doesnt work no matter what I try.
Right click on JPanel and Enclose in Scroll Pane. Didnt work.
After reading some examples I realized I must have JPanel as an argument for JScrollPane constructor. Which I did via right clicking on ScrollPane and CustomizeCode. Because apparently auto-generated code is protected in NetBeans and I cannot just change all those declarations, etc. manually. Still doesnt work.
I did try to set PreferedSize to null for JPanel and/or JScrollPane, didnt help.
JScrollPane is a child of lets call it TabJPanel (which in turn is a tab of TabbedPane). I tried to mess with their relationships, basically trying every possible way of parentship between JFrame, JPanel(holding textfields), TabJPanel and JScrollPane, but nothing worked.
I also made VerticalScrollBar "always visible" just in a case. So I see the scrollbar, it's just that populating that JPanel with JTextFields does not affect it.
When there are too many JTextFields I they go "below" the bottom border of JPanel and I cannot see them anymore.
Code for adding new JTextFields is like this, in a case it's relevant.
JTextField newField = new JTextField( columns );
Rectangle coordinates = previousTextField.getBounds();
newField.setBounds(coordinates.x , coordinates.y + 50, coordinates.width, coordinates.height);
JPanel.add(newField);
JPanel.revalidate();
JPanel.repaint();
Sorry for a long post I'm just trying to provide as much info as possible, because being newbie I dont know whats exactly relevant and whats not. Thanks in advance :)
As there is another answer now, I'm adding my suggestion too.
This sounds exactly like a problem to use a JTable with a single column. JList is not yet editable (and might never be).
JTable would handle the layout problems for you, and you can easily access the values via the table.
Use your own TableModel (a simple Vector should be sufficient in your case), and add values to it.
An option you have is to utilize a LayoutManager, instead of setting the bounds directly on the components. To test this, a simple single column GridLayout with the alignment set to vertical should prove the concept.
panel.setLayout(new GridLayout(0,1));
zero in the rows param allows for rows to be added to the layout as needed.
I do this way to add a scrollpane, create a panel and fill it with few components, then create a scrollpane in the component you want to add it, cut and paste the panel in which all your details will fall in and resize the scrollpane.Because the components take a larger space than the one visible right click on the scrollpane and select design this container, there you can increase the size of the scrollpane and add as many components as you have.

Adjusting positions of swing components

I have a JFrame in which i have to insert JLabels, textfields and JButtons. I am able to these but how can i adjust them to the required position, i want to add one label and textfield in one row and then nxt label and textfield in the next row but they are coming in the same horizontal line. i have used flowLayout with the JFrame. please tell me how to adjust them accordingly. thanks
The key to distributing components in a Container in Swing is the Layout Manager. There are various types out there. To do what you are looking for, you might want to consider the GridLayout. It is pretty easy to set up. You first need to create the layout. The following will create a two columned layout with as many rows as you provide:
GridLayout gl = new GridLayout(0,2);
Then you apply it to your panel:
JPanel panel = new JPanel(gl);
Then you add your items:
panel.add(textfield1);
panel.add(button1);
panel.add(textfield2);
panel.add(button2);
The GridLayout will handle moving from row to row after you fill in the columns with components.
had a look at gridbaglayout? Should serve your purpose.
A GridLayout may be what you want, or a combination of a GridLayout and a FlowLayout. Look at the LayoutManager tutorial to get a better idea of when and how to use and combine the various layout managers.
You need to study the various types of layouts swing provides.
Also you can have a look at FormLayout,provide by JGoodies. I prefer to use this than swing layouts as i find it easy to code and less lines of code
You are using the default Swing Layout Manager. If you want different behaviour (which is very reasonable) then you need to use another LayoutManager. Several exists both from Sun and "out there".
In order for you to be able to choose, you need to know how they work. I can strongly recommend using the Java Tutorial for this:
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html
Let us know if you need more than provided by e.g. nested BorderLayout's or TableLayout.
If you want to be able to position the UI elements in your application (nearly) absolutely, consider using a decent GUI builder like Matisse in NetBeans or Swing UI Designer in IntelliJ IDEA.

In Java Swing how can you manage a list of panels allowing multiple panels to be selected?

I’m working on an in-house app that tracks a bunch of tasks. I wanted to have a simple task monitor that would list the task name and the task’s status. I need this to look just a little nice, I’m no designer so whatever I do is going to suck, but a basic text display won’t work for the project requirements.
What I am essentially attempting to do is show something similar to the Firefox download window, the I-Tunes download window, and well I could name more but they all look basically the same. In each of these apps, each of the ‘progress panels’ is selectable. So to implement this I thought it would be simple to just use a list of JPanels each with a JProgressBar and a JLabel, each of which can just accept focus to determine if it and others are selected. I thought this was going to be an easy task, but if I use a JList it just displays text. I then just figured I would show all the task panels in a larger panel, but I cannot get the inner panels to recognize focus.
Is there a pattern for this? Is there a rolled standard solution that I just have not found? Or is there a better method for doing this? I don’t want to re-invent the wheel, but I thought this was just going to be simple.
It sounds like what you may be looking for is an JList.
You can add your items to the JList's by first adding your "task" to the JList object's ListModel (see the Create a Model section from The Java Tutorials), and then you'll want to assigned a custom ListCellRenderer which will accept your "task" and render on the JList as a JPanel in the list itself. The key here is to make your custom ListCellRenderer be able to display your "task" in the JList the way you want to have it show on the JList.
Take a look into the Writing a Custom Cell Renderer section from the How to Use Lists page of The Java Tutorials. It will describe how to make your custom ListCellRenderer so you can represent your "task" as anything you want.
To keep it short, you will implement the ListCellRenderer interface by implementing the getListCellRendererComponent which will return a Component which is the representation of your task in the JList. You'll probably want to either construct or instantiate your JPanel in this method and return it as the Component.
The standard way of doing this kind of things is to use JTable (or JList) as a container.
You don't have to use default renderes fot table cells, but you can specify your own renderer for specific cells. Take a look at CellRenderer
How about a JTable (which you can set to allow multiple rows to be selected) with an internal JPanel occupying the single cell in each row, which contains a JProgressBar and a JLabel. Or you could use a JList with the same structure as I just described.

Categories