JList单元格中的JButton不能单击

时间:2023-01-17 13:34:08

In my current swing project I have a JList displaying all active sockets, and each cell has a JButton to close that socket. But the JButton in the cell is not clickable: listener does not get fired.

在当前的swing项目中,我有一个显示所有活动套接字的JList,每个单元格都有一个JButton来关闭该套接字。但是单元格中的JButton不是可单击的:listener不会被触发。

I have modified the code to minimal as follows.

我将代码修改为最小,如下所示。

private class ConnectionListRenderer extends JButton implements ListCellRenderer {

    public Component getListCellRendererComponent(JList jlist, Object o, int i, boolean bln, boolean bln1) {

        addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                //do something (close the socket in my project)
            }
        });
        return this;
    }
}


jList.setCellRenderer(new ConnectionListRenderer());

The list looks fine, but the button on in is not clickable. Am I wrong or JList just does not support JButton in the getting fired?

列表看起来不错,但是in上的按钮不能点击。是我错了还是JList在被解雇时不支持JButton ?

3 个解决方案

#1


5  

Here's an example that seems to work, although you don't get the same visual effect of a normal button click. Perhaps someone with better painting skill than me could improve this to simulate the visual pressed button effect.

这里有一个例子,虽然你不能像普通的点击按钮那样获得视觉效果,但它似乎是有效的。也许有比我画得更好的人可以改进这个来模拟视觉按键的效果。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

/**
 * A JList of JButtons.
 */
public class JButtonListDemo implements Runnable
{
  private JList jlist;

  public static void main(String args[])
  {
    SwingUtilities.invokeLater(new JButtonListDemo());
  }

  public void run()
  {
    Object[] items = new ButtonItem[] {
        new ButtonItem("Apple"),
        new ButtonItem("Banana"),
        new ButtonItem("Carrot"),
        new ButtonItem("Date"),
        new ButtonItem("Eggplant"),
        new ButtonItem("Fig"),
        new ButtonItem("Guava"),
    };

    jlist = new JList(items);
    jlist.setCellRenderer(new ButtonListRenderer());
    jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jlist.setVisibleRowCount(5);
    jlist.addMouseListener(new MouseAdapter()
    {
      @Override
      public void mouseClicked(MouseEvent event)
      {
        clickButtonAt(event.getPoint());
      }
    });

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new JScrollPane(jlist));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  private void clickButtonAt(Point point)
  {
    int index = jlist.locationToIndex(point);
    ButtonItem item = (ButtonItem) jlist.getModel().getElementAt(index);
    item.getButton().doClick();
//    jlist.repaint(jlist.getCellBounds(index, index));
  }

  public class ButtonItem
  {
    private JButton button;

    public ButtonItem(String name)
    {
      this.button = new JButton(name);
      button.addActionListener(new ActionListener()
      {
        @Override
        public void actionPerformed(ActionEvent e)
        {
          System.out.println(button.getText() + " was clicked.");
        }
      });
    }

    public JButton getButton()
    {
      return button;
    }

    @Override
    public String toString()
    {
      return button.getText();
    }
  }

  class ButtonListRenderer extends JButton implements ListCellRenderer
  {
    public Component getListCellRendererComponent(JList comp, Object value, int index,
                                                  boolean isSelected, boolean hasFocus)
    {
      setEnabled(comp.isEnabled());
      setFont(comp.getFont());
      setText(value.toString());

      if (isSelected)
      {
        setBackground(comp.getSelectionBackground());
        setForeground(comp.getSelectionForeground());
      }
      else
      {
        setBackground(comp.getBackground());
        setForeground(comp.getForeground());
      }

      return this;
    }
  }
}

Alternatively, you could always layout your JButtons vertically on a JPanel (using a new GridLayout(0,1) perhaps) and then put your JPanel in a JScrollPane, thus mocking a JList of JButtons.

或者,您可以始终在JPanel上垂直地布局JButtons(可能使用新的GridLayout(0,1))),然后将JPanel放在JScrollPane中,从而模拟JList的JButtons。

#2


3  

Render's are not "real" components, they are "rubber stamps" painted onto the surface of the parent component. They have no "physical" presence.

渲染的不是“真实的”组件,它们是涂在父组件表面的“橡皮图章”。他们没有“身体”在场。

A JList will have only one instance of the render and this is used to "stamp" each of the items from the list model onto the view.

JList将只有一个呈现实例,它用于将列表模型中的每个项“戳记”到视图中。

Out of the box, JList is not editable.

开箱即用,JList是不可编辑的。

#3


0  

Try the example posted here http://tips4java.wordpress.com/2009/07/12/table-button-column/

请尝试在这里发布的示例http://tips4java.wordpress.com/2009/07/12/table-button-column/

Do the same with your JList

对你的JList做同样的事情

#1


5  

Here's an example that seems to work, although you don't get the same visual effect of a normal button click. Perhaps someone with better painting skill than me could improve this to simulate the visual pressed button effect.

这里有一个例子,虽然你不能像普通的点击按钮那样获得视觉效果,但它似乎是有效的。也许有比我画得更好的人可以改进这个来模拟视觉按键的效果。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

/**
 * A JList of JButtons.
 */
public class JButtonListDemo implements Runnable
{
  private JList jlist;

  public static void main(String args[])
  {
    SwingUtilities.invokeLater(new JButtonListDemo());
  }

  public void run()
  {
    Object[] items = new ButtonItem[] {
        new ButtonItem("Apple"),
        new ButtonItem("Banana"),
        new ButtonItem("Carrot"),
        new ButtonItem("Date"),
        new ButtonItem("Eggplant"),
        new ButtonItem("Fig"),
        new ButtonItem("Guava"),
    };

    jlist = new JList(items);
    jlist.setCellRenderer(new ButtonListRenderer());
    jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jlist.setVisibleRowCount(5);
    jlist.addMouseListener(new MouseAdapter()
    {
      @Override
      public void mouseClicked(MouseEvent event)
      {
        clickButtonAt(event.getPoint());
      }
    });

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new JScrollPane(jlist));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  private void clickButtonAt(Point point)
  {
    int index = jlist.locationToIndex(point);
    ButtonItem item = (ButtonItem) jlist.getModel().getElementAt(index);
    item.getButton().doClick();
//    jlist.repaint(jlist.getCellBounds(index, index));
  }

  public class ButtonItem
  {
    private JButton button;

    public ButtonItem(String name)
    {
      this.button = new JButton(name);
      button.addActionListener(new ActionListener()
      {
        @Override
        public void actionPerformed(ActionEvent e)
        {
          System.out.println(button.getText() + " was clicked.");
        }
      });
    }

    public JButton getButton()
    {
      return button;
    }

    @Override
    public String toString()
    {
      return button.getText();
    }
  }

  class ButtonListRenderer extends JButton implements ListCellRenderer
  {
    public Component getListCellRendererComponent(JList comp, Object value, int index,
                                                  boolean isSelected, boolean hasFocus)
    {
      setEnabled(comp.isEnabled());
      setFont(comp.getFont());
      setText(value.toString());

      if (isSelected)
      {
        setBackground(comp.getSelectionBackground());
        setForeground(comp.getSelectionForeground());
      }
      else
      {
        setBackground(comp.getBackground());
        setForeground(comp.getForeground());
      }

      return this;
    }
  }
}

Alternatively, you could always layout your JButtons vertically on a JPanel (using a new GridLayout(0,1) perhaps) and then put your JPanel in a JScrollPane, thus mocking a JList of JButtons.

或者,您可以始终在JPanel上垂直地布局JButtons(可能使用新的GridLayout(0,1))),然后将JPanel放在JScrollPane中,从而模拟JList的JButtons。

#2


3  

Render's are not "real" components, they are "rubber stamps" painted onto the surface of the parent component. They have no "physical" presence.

渲染的不是“真实的”组件,它们是涂在父组件表面的“橡皮图章”。他们没有“身体”在场。

A JList will have only one instance of the render and this is used to "stamp" each of the items from the list model onto the view.

JList将只有一个呈现实例,它用于将列表模型中的每个项“戳记”到视图中。

Out of the box, JList is not editable.

开箱即用,JList是不可编辑的。

#3


0  

Try the example posted here http://tips4java.wordpress.com/2009/07/12/table-button-column/

请尝试在这里发布的示例http://tips4java.wordpress.com/2009/07/12/table-button-column/

Do the same with your JList

对你的JList做同样的事情