Java ListCellRenderer 和 JList:处理选择
Java ListCellRenderer and JList: handle selection
我在学校做的一个项目卡住了。
我正在尝试为 "simple" UI 创建自定义 JList
:用例应该显示订单列表并且用户应该能够 select 一个并通过按两个按钮(读取和完成)设置 if read/done 这也充当 "unsetters" (我在 class Order 中使用 2 boolean 继续通过 t,f ,t,f...)。按下完成后,selected 行应变为绿色(并永久保持该颜色),直到再次按下该行上的 "Done" 按钮(=未设置)。与按钮 "Read" 相同,它应该将 selected 行永久变为黄色,与 class 订单中的 "is_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;
}
}
我的问题是,一旦 运行 我的测试文件,所有内容都会正常弹出,但是当我连续 select 并按下这两个按钮之一时,没有任何反应,直到我 select一个新行:然后不断变成绿色或黄色(取决于我按下的按钮)我正在 selecting 的行的颜色。
我很确定这是与我的自定义单元格渲染器相关的问题,也是因为我仍在学习如何使用它并且开始变得很困惑。
这是我剩下的与UI相关的相关代码,也许有用。按钮及其侦听器位于单独的 class(自定义 JPanel
)中,但它们工作正常,所以...
Class InitGraphics
(我测试直接调用class):
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);
}
}
这要了你的命:
} 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,其中包含 clear/read/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;
}
}
我在学校做的一个项目卡住了。
我正在尝试为 "simple" UI 创建自定义 JList
:用例应该显示订单列表并且用户应该能够 select 一个并通过按两个按钮(读取和完成)设置 if read/done 这也充当 "unsetters" (我在 class Order 中使用 2 boolean 继续通过 t,f ,t,f...)。按下完成后,selected 行应变为绿色(并永久保持该颜色),直到再次按下该行上的 "Done" 按钮(=未设置)。与按钮 "Read" 相同,它应该将 selected 行永久变为黄色,与 class 订单中的 "is_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;
}
}
我的问题是,一旦 运行 我的测试文件,所有内容都会正常弹出,但是当我连续 select 并按下这两个按钮之一时,没有任何反应,直到我 select一个新行:然后不断变成绿色或黄色(取决于我按下的按钮)我正在 selecting 的行的颜色。
我很确定这是与我的自定义单元格渲染器相关的问题,也是因为我仍在学习如何使用它并且开始变得很困惑。
这是我剩下的与UI相关的相关代码,也许有用。按钮及其侦听器位于单独的 class(自定义 JPanel
)中,但它们工作正常,所以...
Class InitGraphics
(我测试直接调用class):
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);
}
}
这要了你的命:
} 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,其中包含 clear/read/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;
}
}