java - JList 使用 jbutton 突出显示

标签 java swing highlight jlist

我用 Java 编写了一个小注释器,带有一个基于 Swing 的简单 GUI,但我遇到了一个让我害怕的问题。 问题是:我有一个 jlist 和两个 jbuttons 修改这样的 jlist,这两个按钮具有相同的监听器,但它们的工作方式不同。 它应该像这样工作:一旦您在 jlist 中选择一行,您可以将其标记为 ON TOPIC 或 OFF TOPIC(使用两个按钮),该行会更改颜色,然后选择下一行,但是;即使选择位于右行(下一行),它也会突出显示下一行,只是为了“关闭主题”按钮,为什么?

代码如下:

public class TweetsAnnotator {

static Boolean[] annotations = null;
@SuppressWarnings("rawtypes")
static JList jl;
static JButton offbutton = new JButton("OFF Topic");
static JButton onbutton = new JButton("ON Topic");
static String file = "inception_TweetList";

public TweetsAnnotator() {
}

/**
 * @param args
 * @throws IOException 
 * @throws FileNotFoundException 
 * @throws ClassNotFoundException 
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {

    // Read Tweets from file
    ObjectInputStream load = new ObjectInputStream(new FileInputStream(file));
    ArrayList<String> list = (ArrayList<String>) load.readObject();
    load.close();
    System.out.println(list.size() + " Tweets read from: " + file);

    // Check and read annotations
    File fileannot = new File(file + "Annotations");
    if (fileannot.exists()) {
        System.out.println("esiste, leggo");
        ObjectInputStream loadannot = new ObjectInputStream(new FileInputStream(file + "Annotations"));
        annotations = (Boolean[]) loadannot.readObject();
        loadannot.close();
    } else {
        System.out.println("non esiste, creo poi leggo");
        ObjectOutputStream save = new ObjectOutputStream(new FileOutputStream(file + "Annotations"));
        Boolean[] creatannotations = new Boolean[list.size()];
        for (int i=0; i<list.size(); i++) {
            creatannotations[i] = (Boolean) null;
        }
        save.writeObject(creatannotations);
        save.close();
        ObjectInputStream loadannot = new ObjectInputStream(new FileInputStream(file + "Annotations"));
        annotations = (Boolean[]) loadannot.readObject();
        loadannot.close();
    }
    System.out.println(annotations.length + " Annotations loaded");     

    // Buttons
    offbutton.setActionCommand("off");
    offbutton.addActionListener(new ButtonListener());
    offbutton.setEnabled(false);
    onbutton.setActionCommand("on");
    onbutton.addActionListener(new ButtonListener());
    onbutton.setEnabled(false);

    // ButtonPanel
    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
    buttonPane.add(onbutton);
    buttonPane.add(offbutton);

    // JList
    jl = new JList((Object[])list.toArray());
    jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jl.setLayoutOrientation(JList.VERTICAL);
    jl.setVisibleRowCount(-1);
    jl.setCellRenderer(new MyCellRenderer());
    ListSelectionListener listSelectionListener = new ListSelectionListener() {

        public void valueChanged(ListSelectionEvent e) {
            if (e.getValueIsAdjusting() == false) {
                if (jl.getSelectedIndex() == -1) {
                    //No selection, disable buttons.
                    onbutton.setEnabled(false);
                    offbutton.setEnabled(false);
                } else {
                    //Selection, enable buttons.
                    onbutton.setEnabled(true);
                    offbutton.setEnabled(true);
                }
            }
        }
    };
    jl.addListSelectionListener(listSelectionListener);

    // JScrollPane
    JScrollPane listScroller = new JScrollPane(jl);

    // JFrame
    JFrame frame = new JFrame(file);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);
    frame.addWindowListener(new WindowCloseHandler());

    // Add and show
    frame.getContentPane().add(listScroller, BorderLayout.CENTER);
    frame.getContentPane().add(buttonPane, BorderLayout.PAGE_END);
    frame.pack();
    frame.setVisible(true);

}

private static class MyCellRenderer extends DefaultListCellRenderer {   

    private static final long serialVersionUID = 1L;

    @SuppressWarnings("rawtypes")
    public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus ) {   
        Component c = super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );   
        if ( annotations[index] == null ) {   
            c.setBackground( Color.white );   
        }   
        else if (annotations[index] == true) {   
            c.setBackground( Color.green );   
        } else {
            c.setBackground( Color.red);
        }
        return c;   
    } 
}

private static class ButtonListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        int ind = jl.getSelectedIndex() +1;
        if (e.getActionCommand().equals("on")) {
            System.out.println("ON");
            annotations[jl.getSelectedIndex()] = true;
        }
        if (e.getActionCommand().equals("off")) {
            System.out.println("OFF");
            annotations[jl.getSelectedIndex()] = false;

        }
        jl.clearSelection();
        jl.setSelectedIndex(ind);
    }
}

private static class WindowCloseHandler extends WindowAdapter {

    public void windowClosing(WindowEvent evt) {
        ObjectOutputStream save = null;
        try {
            save = new ObjectOutputStream(new FileOutputStream(file + "Annotations"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            save.writeObject(annotations);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            save.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Saved.");
    }
}
}

尽管 jl.requestFocus();工作正常,我尝试了另一件事使其工作:我交换了这两行

buttonPane.add(onbutton);
buttonPane.add(offbutton);

但是,为什么呢? 抱歉,如果我再问一次,但这真的很奇怪,不是吗?

最佳答案

在你的单元格渲染中,试试这个

if (annotations[index] == null) {
    //c.setBackground(Color.white);
} else if (annotations[index] == true) {
    c.setBackground(Color.green);
} else {
    c.setBackground(Color.red);
}

对于一些“一点”扩展的东西,你也可以尝试

private static class MyCellRenderer extends DefaultListCellRenderer {

    private static final long serialVersionUID = 1L;

    private static final Border SELECTION_BORDER = new LineBorder(UIManager.getColor("List.selectionBackground"));
    private static final Border EMPTY_BORDER = new EmptyBorder(1, 1, 1, 1);

    @SuppressWarnings("rawtypes")
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        setBorder(EMPTY_BORDER);
        if (annotations[index] == null) {

            if (isSelected) {

                setBorder(SELECTION_BORDER);

            }

            c.setBackground(Color.white);
        } else if (annotations[index] == true) {
            c.setBackground(Color.green);
        } else {
            c.setBackground(Color.red);
        }
        return c;
    }
}

基本上,您所做的是更改选择突出显示颜色,隐藏选择。至于为什么你确实得到了一个“似乎”突出显示所选行的绘画伪影,对我来说仍然是一个谜:P

已更新,了解原因

您有时得到的绘制伪影是单元格渲染器的 hasFocus 参数绘制焦点矩形的结果。

现在,如果您想保留现有的单元格渲染器,请在 ActionEvent 中尝试此操作

 //jl.clearSelection();
 jl.setSelectedIndex(ind);
 jl.requestFocus();

据我所知,重绘管理器似乎有点问题。如果我将 jl.repaint() 添加到您现有的代码中(在 setSelectedIndex 调用下),我可以让它永远不绘制焦点矩形:P

关于java - JList 使用 jbutton 突出显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11807210/

相关文章:

java - 在 selenium 中无限滚动

java - 使用 Spring 的类属性更改监听器

java - 使用 hatoas 的休息应用程序 : Multiple markers at this line

java - 在 IDREF 属性中找到获取对象 ""的 JAXB,但此对象没有 ID

java - 制作基于文本的 RPG 时遇到麻烦(与文本区域/字段相关)

typescript - 如何导入使用此给定导出构造导出的函数?

java - 处理 JTextField 中的编辑事件

java - 界面 : Changing panels based on value of combo box

Android - 在 Android 版本 4.0.3 以上的 WebView 中突出显示文本

javascript - 突出显示事件(打开)链接