Home > Software design >  I am Using Jbuttons on Jpanel and addding this jpanel on Jlist. I am using addMouseListener on list.
I am Using Jbuttons on Jpanel and addding this jpanel on Jlist. I am using addMouseListener on list.

Time:09-24

Below is the minimum reproducible code. In MouseClicked method with mouseevent i got that Jpanel is clicked by using getelementat() method. But which button on JPanel is clicked can not figure. Tried with convert point but making some mistake. Need to check which button on Jpanel is clicked. Need some help.

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class JListTest {
    private JList list;
    private DefaultListModel dataModel ;
    private JTableTest tableTest;
    private JPanel panel = new JPanel();
    public JListTest() {
        dataModel = new DefaultListModel();
        list = new JList<>(dataModel);

        list.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                super.mouseClicked(me);
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        JList target = (JList) me.getSource();
                        int index = target.locationToIndex(me.getPoint());
                        JPanel item = (JPanel) target.getModel().getElementAt(index);
                        Point p=SwingUtilities.convertPoint(target,me.getPoint(),item);
                        item.getComponentAt(p);
                    }
                });
            }
        });
        list.setCellRenderer(new PanelRenderer());

    }
    public static void main(String []args){
        JListTest test=new JListTest();
        test.dataModel.addElement("Lable 1");
        test.dataModel.addElement("Lable 2");
        test.dataModel.addElement("Lable 3");

        JButton button1 = new JButton("Button 1");
        JButton button2 = new JButton("Button 2");
        
        test.panel.add(button1);
        test.panel.add(button2);
        test.dataModel.addElement(test.panel);
        test.showUi();
    }
    public void showUi(){
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Demo list");
        frame.setAlwaysOnTop(true);
        frame.setType(Window.Type.UTILITY);
        frame.setResizable(true);
        frame.getContentPane().setLayout(new BorderLayout());
        JScrollPane scrollPane = new JScrollPane(list);
        scrollPane.setPreferredSize(new Dimension(400, 250));
        frame.getContentPane().add(scrollPane, BorderLayout.NORTH);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.setSize(500, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    class PanelRenderer implements ListCellRenderer {

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {

            if(value instanceof String){
                return new DefaultListCellRenderer().getListCellRendererComponent(list,value,index,isSelected,cellHasFocus);
            }

            return (Component) value;
        }
    }
}

Blockquote

CodePudding user response:

item.getComponentAt(p);

What is the point of that statement? How can you tell if the code worked or not since you never assign the result of the method to a variable?

Turns out that because the panel is not really a component displayed on the frame you can't just do as I originally suggested.

If you add code like:

JPanel item = (JPanel) target.getModel().getElementAt(index);
System.out.println( item.getBounds() );

You get output like:

java.awt.Rectangle[x=-487,y=-36,width=0,height=0]

Which doesn't make any sense.

So, I changed the logic to assign the bounds to the panel as if it was displayed on the JList:

item.setBounds(target.getCellBounds(index, index));

Now, I get output like:

java.awt.Rectangle[x=0,y=54,width=487,height=36]

Which does make more sense. However, that still doesn't help because if you add:

Point p = SwingUtilities.convertPoint(target,me.getPoint(),item);
System.out.println( p );

You get something like:

java.awt.Point[x=834,y=166]

The conversion of the point does do what I expected.

So, I decided to convert the point manually:

int y = me.getY() - item.getBounds().y;
Point p = new Point(me.getX(), y);

Putting it all together you get something like:

JList target = (JList) me.getSource();
int index = target.locationToIndex(me.getPoint());
JPanel item = (JPanel) target.getModel().getElementAt(index);
item.setBounds(target.getCellBounds(index, index));
int y = me.getY() - item.getBounds().y;
Point p = new Point(me.getX(), y);
JButton button = (JButton)item.getComponentAt(p);
System.out.println(button.getText());

And you get the text of the button when you click on it.

Of course, you get Exceptions if you click anywhere else. I'll leave it up to you do handle the Exception logic.

Note, I see your latest question is about adding labels and a panel to a frame. It is a much better approach to use real components as you can add ActionListeners to your buttons.

  • Related