adding items to JList - java

I want to add items to my List. My list is first initialized by initComponent() called automatically by instructor (I'm using NetBeans, and all GUI componenets are initialized by the prog automatically).
My questions is:
let's say that we have a Frame1, in this frame we have a Button "show images", when click on it
open Frame2 which has JList...
images list are added through Frame3 successfully...
Below is my code where i want to list all images in my list:
private void setImagesToList()
{
***//bLayer is my Business Layer and _getNomOfSelectedImg() returns number of
//images.***
int imagesCount = bLayer._getNomOfSelectedImg();
***// through my searches i fount that i've to create ListModel to hold my items***
DefaultListModel listModel = new DefaultListModel();
if (imagesCount > 0) // there is/are image(s)
{
for(int i=0; i < imagesCount ; i++)
{
// ***i want to add image name and tooltip (image path) ***
String imgName = bLayer._getImageName(i);
String imgPath = bLayer._getImagePath(i);
listModel.add(i, imgName);
break;
}
images_List.setModel(listModel);
}
}
when I run this code it throws NullPointerException in the last line images_List.setModel(listModel);
What to do to display these items, allow multi-selection, adding mouse click event?

Yes, you can add tooltips. You just have to set the tooltip text on the component returned by the renderer. The JList will use those component tooltip's to determine the correct tooltip text. This can be seen in the JList#getTooltipText implementation of which I copied the relevant part
Component rComponent = r.getListCellRendererComponent(
this, getModel().getElementAt(index), index,
lsm.isSelectedIndex(index),
(hasFocus() && (lsm.getLeadSelectionIndex() ==
index)));
if(rComponent instanceof JComponent) {
MouseEvent newEvent;
p.translate(-cellBounds.x, -cellBounds.y);
newEvent = new MouseEvent(rComponent, event.getID(),
event.getWhen(),
event.getModifiers(),
p.x, p.y,
event.getXOnScreen(),
event.getYOnScreen(),
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
String tip = ((JComponent)rComponent).getToolTipText(
newEvent);
if (tip != null) {
return tip;
}
Could you also update your question with those new questions, as your 'answer with the new question' will float to the bottom

i found my great mistake :( :( i called the functions which set the images to the list before calling initComponent(), that's why the exception was thrown..
thnx all for your answer, but i have to more questions:
1) could i add ToolTipText to the list item, i want to add the image path
2) what did you mean about "my accept ratio"...

Related

How to get the index of an Arraylist Through mouselistener?

I have putted the Arraylist into a JList and i want to get the value/index of the Arraylist when the mouse is clicked on the Jlist.
i have tried with these lines but it always shows -1 as index on the console for every elements clicked.
here is the part of my code..
list2.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e){
JPanel MousePanel=new JPanel();
JList listp=new JList(PatientDetailArlist.toArray());
int index = listp.getSelectedIndex();
System.out.println("Index Selected: " + index);
String sp = (String) listp.getSelectedValue();
System.out.println("Value Selected: " + sp.toString());
MousePanel.add(listp);
tab.add("tab4",MousePanel);
visibleGui();
}
You add a MouseListener to "list2" which is your JList.
list2.addMouseListener(new MouseListener(){
But then in your code for some reason you create a new JList? Well that JList is not visible on the GUI so there is no way it could have a selected index.
JList listp=new JList(PatientDetailArlist.toArray());
int index = listp.getSelectedIndex();
All you need in the listener code is:
int index = list2.getSelectedIndex();
Or even better is to get the JList component that was clicked from the MouseEvent:
JList list = (JList)e.getSource();
int index = list.getSelectedIndex();
However, that is still not a good solution. What if the user uses the keyboard to select an item? A proper design of a GUI should allow the user to use the mouse or the keyboard.
So you should not be using a MouseListener. Instead you should be using a ListSelectionListener to listen for changes in selection of an item in the list.
Read the section from the Swing tutorial on How to Write a ListSelectionListener for more information and examples to get you started.

MouseEvents inside JList objects

I am a bit confused regarding a situation I have. I created a ListModel extending DefaultListModel and ListRenderer implementing ListCellRenderer for displaying a custom cell in a JList. The cells are some objects created from a class extending JPanel, that contain a JLabel and a JButton.
My issue is related to the mouse events: I want to trigger a certain event when clicking on the JButton inside a cell of the JList, yet I can not figure out how to match the mouse source point to that of the JButton from the respective index. More exactly, I added a mouse listener to the list, but I want it to trigger something if the mouse point is located inside the bounds of the JButton, and another action if it's on the data item. I added some prints to find out the cause of this, but before that some code to highlight the structure:
public WifiGuiHandler(JButton reference) {
btnReference = reference;
wifiListener = new WifiListener();
wifiPopupContainer = new JScrollPopupMenu("Connections.");
wifiPopupContainer.setMaximumVisibleRows(7);
connectionsHolder = new ArrayList<>();
listOfConnections = new JList();
listOfConnectionsModel = new ListModel(connectionsHolder);
listOfConnectionsRenderer = new ListRenderer();
listOfConnections.setModel(listOfConnectionsModel);
listOfConnections.setCellRenderer(listOfConnectionsRenderer);
wifiPopupContainer.add(listOfConnections);
wifiPopupContainer.pack();
initializeTestVariables();
initializeListeners();
}
Here, the constructor for the class that takes a JButton and adds a mouse listener to it, that triggers the appearance of a JPopupMenu, which has only one component, the JList that hold the entire data. Also, links the ArrayList with the data items to the ListModel.
public void initializeTestVariables() {
for (int i = 0; i <= 10; i++) {
WifiItem item = new WifiItem("Connection number " + i + ".", i);
connectionsHolder.add(item);
}
}
Setting up the data items.
public void initializeListeners() {
listOfConnections.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int index = listOfConnections.locationToIndex(e.getPoint());
if (index >= 0) {
WifiItem item = (WifiItem) ((ListModel) listOfConnections.getModel()).getElementAt(index);
System.out.println("Button of " + item.getConnectionName() + " is at location :" + item.getButton().getLocation());
System.out.println("Button has the bounds : " + item.getButton().getBounds());
System.out.println("MouseEvent detected on : " + e.getPoint().getLocation());
if (item.getButton().getBounds().contains(e.getPoint())) {
item.connectHere();
}
if (item.getButton().isVisible()) {
System.out.println("Set expanded on : " + item.getConnectionName());
item.setExpandedState(false);
listOfConnectionsModel.fireContentsChanged(item, index, index);
updateGui(false);
} else {
System.out.println("Set expanded on : " + item.getConnectionName());
listOfConnectionsModel.fireContentsChanged(item, index, index);
item.setExpandedState(true);
updateGui(false);
}
}
}
});
btnReference.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
updateGui(true);
}
});
}
And this is where the confusion arises. I correctly get the data item( WifiItem) from the mouse event location/point, but when I click on the JButton of the WifiItem, it doesn't trigger that method, like it doesn't seem to detect that the JButton actually is there. I also set up the prints, and what is strange, the Point for the JButton is always the same, even though it actually is different, and this seems to be the problem. More exactly, from the output of the program:
Button of Connection number 2. is at location :java.awt.Point[x=137,y=33]
Button has the bounds : java.awt.Rectangle[x=137,y=33,width=90,height=26]
MouseEvent detected on : java.awt.Point[x=172,y=125]
Button of Connection number 3. is at location :java.awt.Point[x=137,y=33]
Button has the bounds : java.awt.Rectangle[x=137,y=33,width=90,height=26]
MouseEvent detected on : java.awt.Point[x=172,y=125]
The above mouse events points were actually located on the JButton itself, only it didn't get that. As another strange fact, only if I click the JButton of the FIRST element of the list does it trigger the required mouse action.
Another print revealed that all the JButtons have the same Point and Rectangle, and I don't get it. There are 10 items in the JList, each displayed properly, how can all their JButtons have the same location? I must be missing some key element here. I looked at other posts and tried other recommendations: converting the point with SwingUtilities, removing all the mouse listeners from the JList and adding them to the data items.
To sum it up,the issue is that the list triggers the events for the correct data item in it(meaning, I do get the correct index for the item located there), but if the mouse event happens on the JButton of any data item inside the list, it doesn't trigger the required effect (the point is not withing the bounds of the button, even though it should be).
More exactly, I added a mouse listener for the list, but I want it to trigger something if the mouse point is located inside the bounds of the JButton, and another action if it's on the data item.
An easier solution would be to use a JTable. The data is separated into columns and the JTable has an API to let you know which row/column was selected.
You can use the Table Button Column as your renderer/editor for the button.
Edit:
only if I click the JButton of the FIRST element of the list does it trigger the required mouse action
Sounds like your conversion of the mouse point is off.
, how can all their JButtons have the same location?
Again, the button location is releative to the renderer panel. The panel itself is relative to the row in the JList. So I would guess you need to need the row index and add the height of each of the previous rows to your calculation.

JTabbedPane: Change Title from within Tab

I'm trying now for a couple of hours to optimize my user interface but I'm not getting any further right now.
I got a JTabbedPane to show datasets. There is one textfield in there with should also represent the tabs title. Right now there is a button labeled "save" which does nothing else but read this text field from the current tab and updates the tabs title. I'd love to replace this by updating the tab's title when the field is changed. I got the event listener up and running, so no problems here, but how to I get to call the JTabbedPane object?
I tried to put a JTabbedPane variable into my JPanel class and store a reference here, but this keeps crashing the moment I call the setter for this variable...
Well, not actually crashing, but it throws an exception:
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
[...]
The setter is quite simple:
public void setTabContainer(JTabbedPane cont){
container = cont;
}
Any ideas?
I got the event listener up and running, so no problems here, but how to I get to call the JTabbedPane object?
You can use SwingUtilities class as follows to get the tabbed pane that is the ancestor of your text field:
JTabbedPane tabbedPane = (JTabbedPane)SwingUtilities.getAncestorOfClass(JTabbedPane.class, textField);
Then you can iterate over the tabbed pane's components in order to find the index where your text field is placed and finally update the tab's title:
for(int i = 0; i < tabbedPane.getTabCount(); i++) {
if(SwingUtilities.isDescendingFrom(textField, tabbedPane.getComponentAt(i))) {
tabbedPane.setTitleAt(i, textField.getText());
break;
}
}
See the API for:
SwingUtilities#getAncestorOfClass(Class c, Component comp)
SwingUtilities#isDescendingFrom(Component a, Component b)
JTabbedPane#getComponentAt(int index)
Try:
JTabbedPane tabbedPane = (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, this);
tabbedPane.setTitleAt(tabbedPane.indexOfTabComponent(this), title);
Assumes that this is the tab component, and title is the new title. Note that you must have set this as the content for the tab.
Uses:
JTabbedPane#indexOfTabComponent
JTabbedPane#setTitleAt
SwingUtilities#getAncestorOfClass
In IntelliJ IDEA's form designer each tab is a JPanel hence you can use the following method to set the title from within Java code:
public static void setTabTitle(JPanel tab, String title)
{
JTabbedPane tabbedPane = (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, tab);
for (int tabIndex = 0; tabIndex < tabbedPane.getTabCount(); tabIndex++)
{
if (SwingUtilities.isDescendingFrom(tab, tabbedPane.getComponentAt(tabIndex)))
{
tabbedPane.setTitleAt(tabIndex, title);
break;
}
}
}
This solution is very similar to the one given by dic19 though.

Issue with JTabbedPane

I am having problems with the following code:
public void detachTab(TabComponent tc) {
Logger.add("Detaching Tab");
for (int i = 0; i < globalTabbedPane.getTabCount(); i++) {
if (tc == globalTabbedPane.getTabComponentAt(i)) {
Logger.add("Detaching panel: " + i);
SeparateWindow sw = new SeparateWindow((JPanel) globalTabbedPane.getComponentAt(i));
sw.setVisible(true);
globalTabbedPane.remove(i);
return;
}
}
}
It simply removes a tab from a JTabbedPane and places it in a separate window. Pretty self explanitory. The issue is that the method also removes the tab below it. I dont see how this is possible. Maybe there is something im overlooking.
I've not tested this, but...
SeparateWindow sw = new SeparateWindow((JPanel) globalTabbedPane.getComponentAt(i))
Is likely adding the Component to the window, removing it from the JTabbedPane, the tabbedpane may be then be removing the associated tab, now meaning that the index positions have changed, so when you call
globalTabbedPane.remove(i);
you are now removing the following tab...
You could try getting a reference to the component, removing it and the creating the window...
JPanel pane = (JPanel) globalTabbedPane.getComponentAt(i);
globalTabbedPane.remove(i);
SeparateWindow sw = new SeparateWindow(pane);

How to detect when mouse (pointer) is over text in JList?

I am using a JList to display elements. I want to provide a popup menu to interact with the specific elements under the mouse. I am using a MouseInputListener, isPopupTrigger(), locationToIndex(), getCellBounds(), etc. I haven't posted code for this as it's not the point, just background for the question. What I ultimately want to do is only post the popup menu when the correct (platform- and UI-dependent) action occurs over the text in the JList cell - not just anywhere in the row. My JList is in a ScrollPane which is in a SplitPane. The width of the JList cells can be much larger than the text. If the user is able to post the popup by clicking far to the right of the text in the row when the SplitPane is much larger than the extent of the text, it will be unclear just which row is being operated on. I don't want to select the row that the user would be interacting with using the popup menu because selection has a different meaning in this context. So the basic question is: how can I determine if the mouse location when the popup trigger occurs is actually over the text in the row, rather than just in the row?
If the JList's cell renderer returns JLabels (which it will by default, or if you have set the renderer to a DefaultListCellRenderer), you can use SwingUtilities.layoutCompoundLabel to determine the bounds of the text:
static <E> boolean isOverText(Point location,
JList<E> list) {
int index = list.locationToIndex(location);
if (index < 0) {
return false;
}
E value = list.getModel().getElementAt(index);
ListCellRenderer<? super E> renderer = list.getCellRenderer();
Component c = renderer.getListCellRendererComponent(list, value, index,
list.isSelectedIndex(index),
list.getSelectionModel().getLeadSelectionIndex() == index);
if (c instanceof JLabel) {
JLabel label = (JLabel) c;
Icon icon = null;
if (!label.isEnabled()) {
icon = label.getDisabledIcon();
}
if (icon == null) {
icon = label.getIcon();
}
Rectangle listItemBounds =
SwingUtilities.calculateInnerArea(label, null);
Rectangle cellBounds = list.getCellBounds(index, index);
listItemBounds.translate(cellBounds.x, cellBounds.y);
listItemBounds.width = cellBounds.width;
listItemBounds.height = cellBounds.height;
Rectangle textBounds = new Rectangle();
Rectangle iconBounds = new Rectangle();
SwingUtilities.layoutCompoundLabel(label,
label.getFontMetrics(label.getFont()),
label.getText(),
icon,
label.getVerticalAlignment(),
label.getHorizontalAlignment(),
label.getVerticalTextPosition(),
label.getHorizontalTextPosition(),
listItemBounds,
iconBounds,
textBounds,
label.getIconTextGap());
return textBounds.contains(location);
}

Categories