2016-08-04 85 views
1

我陷入了一个项目中,我必须在学校做。Java ListCellRenderer和JList:句柄选择

我试图为一个“简单”UI创建一个自定义JList:用例应该显示一个命令列表,并且用户应该能够选择一个并设置是否通过按下两个按钮来读取/完成(读取并完成),它也充当“unsetters”(我在类Order中使用2布尔值,它继续前进t,t,f,t,f ...)。一旦按下完成,所选行将变为绿色(并永久保持该颜色),直到再次按下该行的“完成”按钮(=未设定)。在类Order中,应该将所选行永久变为黄色,与“is_read”标志相关的按钮“Read”的相同内容。

阅读一些相关的帖子后,我写了这个习俗ListCellRenderer

public class CookListCellRender extends JLabel implements ListCellRenderer<Order>{ 

public CookListCellRender(){ 
    setOpaque(true); 
} 

@Override 
public Component getListCellRendererComponent(JList<? extends Order> list, Order value, int index, boolean isSelected, boolean cellHasFocus) { 

    setLayout(new FlowLayout()); 
    setText(value.getNameEl()); 
    list.setVisibleRowCount(30); 
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
    setFont(new Font("Arial",Font.ITALIC,17)); 

    if (isSelected) { 
     setBackground(Color.BLUE); 
     setForeground(Color.BLUE); 
    } else { 
     setBackground(getBackground()); 
     setForeground(getForeground()); 
    } 

    if(value.getOrderRead()){ 
     setBackground(Color.YELLOW); 
    }else{ 
     setBackground(Color.WHITE); 
    } 

    if(value.getOrderDone()){ 
     setBackground(Color.GREEN); 
    }else{ 
     setBackground(Color.WHITE); 
    } 
    return this; 
} 

} 

我的问题是,一旦运行我的测试文件,一切都弹出正常,但是当我选择一行,我按了2之一按钮什么也没有发生,直到我选择一个新的行:然后保持转动绿色或黄色(取决于我按下的按钮)我选择的行的颜色。

我敢肯定这是一个与我的自定义单元格渲染器有关的问题,也是因为我仍然在学习如何使用它,所以我开始变得非常困惑。

这里是我的相关代码的其余相关的用户界面,也许它是有用的。按钮和听众都在一个单独的类(自定义JPanel),但这些都是做工精细,所以......

InitGraphics(我的测试类直接调用):

public class InitGraphics { 

Cook c; 
JList list; 

public InitGraphics(Cook cuoco){ 
    c=cuoco; 
    initUi(); 
    } 

private void initUi() { 
    JFrame frame = new JFrame("Cucina"); 
    list =new JList(c.getOrdersCopy().toArray()); 
    list.setCellRenderer(new CookListCellRender()); 
    JScrollPane panel = new JScrollPane(list); 
    panel.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
    panel.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
    ButtonPanel buttonPanel = new ButtonPanel(c.getOrdersCopy(),list); 
    buttonPanel.setLayout(new FlowLayout()); 
    frame.add(buttonPanel,BorderLayout.NORTH); 
    frame.add(panel,BorderLayout.CENTER); 
    frame.setVisible(true); 
    frame.setSize(600, 400); 
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    } 
} 
+3

我强烈建议,没有我** **恳请您创建和发布有效[SSCCE(HTTP:// sscce.org),如果你需要认真和及时的帮助。否则,你的代码对我们来说是无用的,并限制了我们理解你的问题的能力。 –

+1

例如:我们都不能编译也不能运行这段代码。我们不希望看到您的整个程序或通过与该问题无关的大量代码进行浏览,但是如果您可以将代码凝结为未修改编译和运行的最小示例,那会向我们显示您的问题,并且这是小到足以发布您的问题作为代码格式的文本,我们可能会很快解决您的问题。 –

+0

对不起,这里的网络连接不好。顺便说一句,我从来没有听说过sscce之前,但我试图......我有140行代码,至少我不认为是非常合适的,但他的工作。不是“java资深人士”,我尽我所能,把它留在这里[pastebin](http://pastebin.com/QUP0v8ke)只是不要编辑已经发布的代码 – A7X

回答

3

这是杀害你:

} else { 
     setBackground(getBackground()); 
     setForeground(getForeground()); 
    } 

它并没有改变任何东西。我认为,你想要的:

} else { 
     setBackground(null); 
     setForeground(null); 
    } 

注意,做任何工作,在此代码,我要创建我自己的SSCCE

import java.awt.*; 
import javax.swing.*; 

public class InitGraphics { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> { 
      final DefaultListModel<Order> orderModel = new DefaultListModel<>(); 
      orderModel.addElement(new Order("One")); 
      orderModel.addElement(new Order("Two")); 
      orderModel.addElement(new Order("Three")); 
      orderModel.addElement(new Order("Four")); 
      orderModel.addElement(new Order("Five")); 

      JList<Order> orderList = new JList<>(orderModel); 
      orderList.setCellRenderer(new CookListCellRender()); 

      JPanel panel = new JPanel(); 
      panel.add(new JScrollPane(orderList)); 

      JOptionPane.showMessageDialog(null, panel); 
     }); 
    } 
} 

class CookListCellRender extends JLabel implements ListCellRenderer<Order> { 

    public CookListCellRender() { 
     setOpaque(true); 
    } 

    @Override 
    public Component getListCellRendererComponent(JList<? extends Order> list, Order value, int index, 
      boolean isSelected, boolean cellHasFocus) { 

     setLayout(new FlowLayout()); 
     setText(value.getNameEl()); 
     list.setVisibleRowCount(30); 
     list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     setFont(new Font("Arial", Font.ITALIC, 17)); 

     if (isSelected) { 
      setBackground(Color.BLUE); 
      setForeground(Color.BLUE); 
     } else { 
      // TODO: fix! 
      // setBackground(getBackground()); 
      // setForeground(getForeground()); 
      setBackground(null); 
      setForeground(null); 
     } 

     if (value.getOrderRead()) { 
      setBackground(Color.YELLOW); 
     } else { 
      setBackground(Color.WHITE); 
     } 

     if (value.getOrderDone()) { 
      setBackground(Color.GREEN); 
     } else { 
      setBackground(Color.WHITE); 
     } 
     return this; 
    } 

} 

class Order { 

    private String nameE1; 
    private boolean orderDone; 
    private boolean orderRead; 

    public Order(String nameE1) { 
     this.nameE1 = nameE1; 
    } 

    public String getNameEl() { 
     return nameE1; 
    } 

    public boolean getOrderDone() { 
     return orderDone; 
    } 

    public boolean getOrderRead() { 
     return orderRead; 
    } 

    public void setOrderDone(boolean orderDone) { 
     this.orderDone = orderDone; 
    } 

    public void setOrderRead(boolean orderRead) { 
     this.orderRead = orderRead; 
    } 

} 

在未来,请为我们做这项工作,因为你是一个寻求帮助的人,而我们是志愿者。

而且这样的:

list.setVisibleRowCount(30); 
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 

决不做这种事情的渲染器中。这段代码应该在你创建JList的地方,而不是在渲染器中。

这里是我的最新SSCCE,一个包括透明/读/ DONE按钮

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Font; 
import java.awt.event.*; 
import java.util.List; 

import javax.swing.*; 

public class InitGraphics { 
    @SuppressWarnings("serial") 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> { 
      final DefaultListModel<Order> orderModel = new DefaultListModel<>(); 
      orderModel.addElement(new Order("One")); 
      orderModel.addElement(new Order("Two")); 
      orderModel.addElement(new Order("Three")); 
      orderModel.addElement(new Order("Four")); 
      orderModel.addElement(new Order("Five")); 

      final JList<Order> orderList = new JList<>(orderModel); 
      orderList.setCellRenderer(new CookListCellRender()); 
      orderList.setVisibleRowCount(5); 

      JPanel panel = new JPanel(); 
      // panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS)); 
      panel.add(new JScrollPane(orderList)); 

      panel.add(new JButton(new AbstractAction("Read") { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        List<Order> selectedOrders = orderList.getSelectedValuesList(); 
        for (Order order : selectedOrders) { 
         order.setOrderRead(true); 
        } 
        orderList.repaint(); 
       } 
      })); 
      panel.add(new JButton(new AbstractAction("Done") { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        List<Order> selectedOrders = orderList.getSelectedValuesList(); 
        for (Order order : selectedOrders) { 
         order.setOrderDone(true); 
        } 
        orderList.repaint(); 
       } 
      })); 
      panel.add(new JButton(new AbstractAction("Clear") { 

       @Override 
       public void actionPerformed(ActionEvent e) { 

        for (int i = 0; i < orderModel.size(); i++) { 
         orderModel.getElementAt(i).setOrderDone(false); 
         orderModel.getElementAt(i).setOrderRead(false); 
        } 
        orderList.repaint(); 
       } 
      })); 


      JFrame frame = new JFrame("Test List"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.add(panel); 
      frame.pack(); 
      frame.setLocationRelativeTo(null); 
      frame.setVisible(true); 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class CookListCellRender extends JLabel implements ListCellRenderer<Order> { 

    public CookListCellRender() { 
     setOpaque(true); 
    } 

    @Override 
    public Component getListCellRendererComponent(JList<? extends Order> list, Order value, int index, 
      boolean isSelected, boolean cellHasFocus) { 

     // setOpaque(true); // !! 

     // !! setLayout(new FlowLayout()); 
     setText(value.getNameEl()); 
     // !! list.setVisibleRowCount(30); 
     // !! list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     setFont(new Font("Arial", Font.ITALIC, 17)); 

     if (isSelected) { 
      setBackground(Color.BLUE); 
      setForeground(Color.BLUE); 
     } else { 
      // TODO: fix! 
      // setBackground(getBackground()); 
      // setForeground(getForeground()); 
      setBackground(null); 
      setForeground(null); 
     } 

     if (value.getOrderRead()) { 
      setBackground(Color.YELLOW); 
     } else { 
      setBackground(Color.WHITE); 
     } 

     if (value.getOrderDone()) { 
      setBackground(Color.GREEN); 
     } else { 
      setBackground(Color.WHITE); 
     } 
     return this; 
    } 

} 

class Order { 

    private String nameE1; 
    private boolean orderDone; 
    private boolean orderRead; 

    public Order(String nameE1) { 
     this.nameE1 = nameE1; 
    } 

    public String getNameEl() { 
     return nameE1; 
    } 

    public boolean getOrderDone() { 
     return orderDone; 
    } 

    public boolean getOrderRead() { 
     return orderRead; 
    } 

    public void setOrderDone(boolean orderDone) { 
     this.orderDone = orderDone; 
    } 

    public void setOrderRead(boolean orderRead) { 
     this.orderRead = orderRead; 
    } 

} 
+0

哇这里有很多新东西......我可以问你,如果AbstractAction与之前使用的invokeLater函数有关吗?这就是为什么选择一个新行后我的行颜色发生变化的原因?我再次尝试写它(我发现sscce也是一个很好的调试方法,迫使我清理我的代码并深深修改它......是一团糟,我在20个类之间丢失了),现在设置行正确地绿色,但仍然选择一个新的行后。对不起,如果我让你浪费时间,现在我已经学会了sscce,所以下次我会明确地使用它! – A7X

+1

@ A7X:'AbstractAction'类似于类固醇上的'ActionListener'。它为JButton提供了监听器,以及其他几个重要的状态字段和功能。 'SwingUtilities.invokeLater(...)'用于保证您运行的代码在Swing事件线程或EDT(事件分派线程)上运行。这对于Swing线程安全是严格的,并且与代码不运行无关。 –

+0

明白了。我还注意到你在列表上使用了重绘,特别是,你把所有的元素保留在另一个数组列表中。我认为这是为什么我的代码不能按预期工作的另一个原因......但如果我强制单选列表中的代码,我不能做这样的事情,对吗?或者不会影响getSelectedValueList方法? – A7X