2016-08-04 13 views
1

Ich blieb bei einem Projekt stecken, das ich in der Schule machen muss.Java ListCellRenderer und JList: Handle Auswahl

Ich habe versucht, eine benutzerdefinierte JList für eine "einfache" UI zu erstellen: der Anwendungsfall sollte eine Liste von Bestellungen anzeigen und der Benutzer sollte in der Lage sein, einen zu wählen und zu setzen, wenn er/sie durch Drücken von zwei Tasten (lesen und getan), die auch als "unsetters" (ich verwende 2 boolean in der Klasse Order, die durch t, ​​f, t, f ...) gehen. Wenn Sie auf Fertig klicken, sollte die ausgewählte Zeile grün werden (und dauerhaft auf dieser Farbe bleiben), bis die Schaltfläche "Fertig" erneut in dieser Zeile gedrückt wird (= nicht gesetzt). Das gleiche gilt für die Schaltfläche "Lesen", die die ausgewählte Zeile dauerhaft gelb machen sollte, bezogen auf das Flag "is_read" in der Klasse Order.

Nach einigen verwandten Beiträgen zu lesen, schrieb ich diesen Brauch 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; 
} 

} 

Mein Problem ist, wenn hier meine Testdatei läuft, alles erscheint richtig, aber wenn ich eine Zeile auswählen und drücke ich einer von denen 2 Tasten nichts passiert, bis ich eine neue Zeile auswähle: dann wird die Farbe der Zeile, die ich auswähle, grün oder gelb (abhängig von der Taste, die ich gedrückt habe) angezeigt.

Ich bin mir ziemlich sicher, dass dies ein Problem mit meinem benutzerdefinierten CellRenderer ist, auch weil ich immer noch lerne, wie man es benutzt und ich begann ziemlich verwirrt zu werden.

Hier ist der Rest meines relevanten Codes in Bezug auf die Benutzeroberfläche, vielleicht ist es nützlich. Tasten und ihre Zuhörer sind in einer separaten Klasse (ein benutzerdefinierten JPanel), aber das ist gut funktioniert, so ...

Klasse InitGraphics (direkt von meiner Test-Klasse genannt):

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

empfehle ich, nein, ich ** ** fordern Sie erstellen und veröffentlichen eine gültige [sscce] (http klar/lesen/done Schaltflächen enthält: // sscce.org) wenn Sie ernsthafte und schnelle Hilfe brauchen. Andernfalls ist Ihr Code für uns fast nutzlos und begrenzt unsere Fähigkeit, Ihr Problem zu verstehen. –

+1

Zum Beispiel: keiner von uns kann diesen Code kompilieren oder ausführen.Wir möchten nicht Ihr gesamtes Programm sehen oder eine große Menge Code durchforsten, der für das Problem nicht relevant ist, aber wenn Sie Ihren Code auf das kleinste Beispiel verdichten könnten, das unmodifiziert kompiliert und ausgeführt wird, zeigt uns das Ihr Problem, und Das ist klein genug, um hier mit Ihrer Frage als Code-formatierten Text zu veröffentlichen, wir wären wahrscheinlich in der Lage, Ihr Problem ziemlich schnell zu lösen. –

+0

Tut mir leid, schlechte Internetverbindung hier. Btw ich habe noch nie zuvor von Sscce gehört, aber ich habe versucht ... Nun, ich habe 140 Zeilen Code, was ich nicht für sehr geeignet halte, aber macht seinen Job. Nicht ein "Java-Veteran" Ich versuchte mein Bestes, ich lasse es hier mit einem [Pastebin] (http://pastebin.com/QUP0v8ke) einfach nicht um den bereits geposteten Code zu bearbeiten – A7X

Antwort

3

Dies tötet Sie:

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

Es ändert überhaupt nichts. Ich denke, dass Sie wollen:

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

Beachten Sie, dass jede Arbeit an allen auf diesem Code zu tun, ich hatte mein eigenes SSCCE zu erstellen:

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

} 

In Zukunft bitte für uns, diese Arbeit tun weil du derjenige bist, der um Hilfe bittet, und wir sind Freiwillige.

Auch dies:

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

tun nie diese Art der Sache aus einem Renderer. Dieser Code sollte an die Stelle gehen, an der Sie die JList erstellen, nicht im Renderer.

Hier ist meine neueste SSCCE, eine, die

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

Wow, es gibt eine Menge neuer Dinge hier ... darf ich dich fragen, ob die AbstractAction mit der invokeLater Funktion verwandt ist, die du vorher benutzt hast? Ist das der Grund, warum sich meine Zeilenfarben nach dem Auswählen einer neuen Zeile ändern? Ich habe es wieder versucht, es zu schreiben (und ich fand heraus, dass Sscce auch eine gute Möglichkeit zum Debuggen ist, zwingt mich, meinen Code aufzuräumen und es gründlich zu revidieren ... war total unordentlich, ich verlor zwischen 20 Klassen) und setze jetzt Zeilen richtig grün, aber immer noch nach Auswahl einer neuen Zeile. Tut mir leid, wenn ich dich dazu gebracht habe, Zeit zu verschwenden, jetzt habe ich von sscce erfahren, also werde ich es nächstes Mal definitiv benutzen! – A7X

+1

@ A7X: 'AbstractAction' ist ein bisschen wie ein' ActionListener' auf Steroiden. Es bietet dem JButton seinen Listener und mehrere andere wichtige Statusfelder und Funktionen. 'SwingUtilities.invokeLater (...)' wird verwendet, um zu garantieren, dass der von Ihnen ausgeführte Code im Swing Event Thread oder EDT (Event Dispatch Thread) ausgeführt wird. Dies gilt ausschließlich für die Sicherheit von Swing-Threads und hat auch nichts damit zu tun, dass Ihr Code nicht ausgeführt wird. –

+0

Bekam es. Ich habe auch bemerkt, dass du Repaint in der Liste benutzt hast und insbesondere alle Elemente, die in einer anderen Arraylist ausgewählt bleiben sollen. Ich denke, das ist ein weiterer Grund, warum mein Code nicht wie erwartet funktioniert hat ... Aber ich kann so etwas nicht machen, wenn ich eine einzelne Auswahl auf der Liste erzwinge, ist das richtig? Oder wird sich dies nicht auf die Methode getSelectedValueList auswirken? – A7X