JList单元格中的JButton不可单击

时间:2012-11-19 05:05:33

标签: java swing jlist

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

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

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());

列表看起来很好,但是上面的按钮不可点击。我错了还是JList只是不支持JButton被解雇?

4 个答案:

答案 0 :(得分:6)

这是一个似乎有用的示例,尽管您没有获得与普通按钮点击相同的视觉效果。也许拥有比我更好的绘画技巧的人可以改进这个以模拟视觉按下的按钮效果。

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;
    }
  }
}

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

答案 1 :(得分:4)

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

JList只有一个渲染实例,用于将列表模型中的每个项目“标记”到视图上。

开箱即用,JList不可编辑。

答案 2 :(得分:0)

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

对你的JList做同样的事情

答案 3 :(得分:0)

另一种解决方案是彼此相邻使用两个列表。第一个呈现实际的列表内容,而第二个呈现按钮,您可以将两个列表添加到class TexManager { public: TexManager* tex() //to access your assets without creating multiple instances of this class { static Texmanager texMan; return &texMan; } void loadTexture(std::string name, std::string filepath) //to load textures { sf::Texture tmp; tmp.loadFromFile(filepath); texMap.insert(std::make_pair(name, tmp)); } sf::Texture& getTexture(st::string name) //to retrieve textures { return texMap.at("name"); } private: std::map<std::string, sf::Texture> texMap; } 并使用JPanelBorderLayoutBorderlayout.CENTER)进行布局。将此BorderLayout.EAST添加到JPanel的视口中。