2016-08-04 11 views
1

Я застрял в проекте, который мне нужно делать в школе.Java ListCellRenderer и JList: выбор дескриптора

Я пытался создать пользовательский JList для «простого» пользовательского интерфейса: в прецеденте должен отображаться список заказов, и пользователь должен иметь возможность выбирать его и устанавливать, если читать/делать, нажав две кнопки (читать и сделано), который действует также как «unsetters» (я использую 2 булевых в классе Order, которые продолжают идти через t, f, t, f ...). После нажатия «Готово» выбранная строка должна загореться зеленым цветом (и оставаясь постоянно на этом цвете) до тех пор, пока в этой строке не будет нажата кнопка «Готово» (= unset). То же самое в кнопке «Чтение», которая должна включать выбранную строку, постоянно желтую, относящуюся к флагу «is_read» в классе Order.

После прочтения некоторых соответствующие должности, я написал этот обычай 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

Прошу прощения, плохое подключение к Интернету здесь. Btw я никогда не слышал раньше о 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

Получил это. Я также заметил, что вы использовали перерисовку в списке и, в частности, вы поместили все элементы, которые должны оставаться выбранными внутри другого arraylist. Я думаю, что это еще одна причина, почему мой код работал не так, как ожидалось ... Но я не могу так поступать, если я заставляю одиночный выбор в списке, верно? Или не повлияет на метод getSelectedValueList? – A7X