简体   繁体   English

JList 单元格中的 JButton 不可点击

[英]JButton in JList cell is not clickable

In my current swing project I have a JList displaying all active sockets, and each cell has a JButton to close that socket.在我当前的 Swing 项目中,我有一个JList显示所有活动的套接字,每个单元格都有一个JButton来关闭该套接字。 But the JButton in the cell is not clickable: listener does not get fired.但是单元格中的JButton不可点击:监听器不会被触发。

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.该列表看起来不错,但 in 上的按钮不可点击。 Am I wrong or JList just does not support JButton in the getting fired?我错了还是JList在被解雇时不支持JButton

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 上垂直布局 JButton(可能使用新的 GridLayout(0,1)),然后将 JPanel 放在 JScrollPane 中,从而模拟 JButton 的 JList。

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不可编辑。

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执行相同操作

Another solution would be to use two lists next to each other.另一种解决方案是使用两个相邻的列表。 The first one renders the actual list content, while the second renders buttons, you can add the two lists to a JPanel and layout them with BorderLayout ( Borderlayout.CENTER and BorderLayout.EAST ).第一个呈现实际列表内容,而第二个呈现按钮,您可以将两个列表添加到JPanel并使用BorderLayoutBorderlayout.CENTERBorderLayout.EAST )对其进行布局。 Add this JPanel to the viewport of a JScrollPane .将此JPanel添加到JScrollPane的视口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM