2016-08-04 80 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