Java 在JTable cell setDefaultRenderer到jTextArea之后,如何高亮显示jTextArea中的选定行

Java 在JTable cell setDefaultRenderer到jTextArea之后,如何高亮显示jTextArea中的选定行,java,swing,jtable,caret,jtextarea,Java,Swing,Jtable,Caret,Jtextarea,这是我的电脑 class tblCalendarRenderer extends JTextArea implements TableCellRenderer { JTextArea textField; public tblCalendarRenderer() { textField = new JTextArea(); } public Component getTableCellRendererComponent(JTable tabl

这是我的电脑

class tblCalendarRenderer extends JTextArea implements TableCellRenderer {

    JTextArea textField;

    public tblCalendarRenderer() {
        textField = new JTextArea();
    }

    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean selected, boolean focused, int row,
            int column) {
        textField.setText(value == null ? "" : value.toString());
        textField.setLineWrap(true);
        textField.setWrapStyleWord(true);

        if (column == 0 || column == 6) { // Week-end
            textField.setBackground(new Color(255, 220, 220));
        } else { // Week
            textField.setBackground(new Color(255, 255, 255));
        }
        if (row % 2 == 0) {
            if (value != null) {
                if (Integer.parseInt(value.toString()) == realDay
                        && currentMonth == realMonth
                        && currentYear == realYear) { // Today
                    textField.setBackground(new Color(220, 220, 255));
                }
            }
            textField.setFont(new java.awt.Font("Dialog",
                    java.awt.Font.BOLD, 11));
        } else {
            textField.setFont(new java.awt.Font("Dialog",
                    java.awt.Font.BOLD, 12));
        }
        if (selected && row % 2 != 0) {
            textField.setBackground(Color.LIGHT_GRAY);
            textField.setForeground(Color.black);
        }

        textField.setBorder(null);
        return textField;
    }
}
这是我用来突出显示jTextArea中的行的代码。如何将其添加到jTable中?我尝试添加textField.addCaretListener(新示例CaretListener());但它仍然会选择整个jTable单元

    class ExampleCaretListener implements CaretListener {

    public void caretUpdate(CaretEvent e) {
        Color HILIT_COLOR = Color.LIGHT_GRAY;
        final Highlighter.HighlightPainter painter;
        painter = new DefaultHighlighter.DefaultHighlightPainter(
                HILIT_COLOR);
        JTextArea textField = (JTextArea) e.getSource();
        String lineText = "";
        try {
            int dot = e.getDot();
            int rowStart = Utilities.getRowStart(textField, dot);
            int rowEnd = Utilities.getRowEnd(textField, dot);
            System.out.println(dot + " " + rowStart + " " + rowEnd);
            lineText = textField.getText(rowStart, (rowEnd - rowStart));
            textField.getHighlighter().removeAllHighlights();
            textField.getHighlighter().addHighlight(rowStart, rowEnd,
                    painter);
        } catch (BadLocationException ex) {
            System.out.println(ex);
        }

    }

}

我猜每个单元格的内容都是日期编号,所以我不确定您想做什么,或者在单个单元格中实际有多行。 您的意思是选择表格单元格而不是整行吗? 如果这就是您的意思,您可以通过更改表的行/列选择模型来实现。 如果不是这样,请缩小您的问题范围,并提供完整的(清理过的)源代码

编辑:

正如eugener所说,渲染器只是根据单元格的值将单元格内的JTextArea绘制为图像。但是,您可以创建自己的自定义模型来表示单元的状态(而不是使用单个字符串值,例如,可以使用包含字符串和一些附加数据的MyModel),并基于该模型渲染单元。例如:您可以检测鼠标单击(将鼠标侦听器连接到Jtable),然后更改该模型的状态-根据特定单元格值的鼠标位置更新选择开始和选择结束。在getCellRenderer内部,将值强制转换为包含选择开始和选择结束数据的对象类型(MyModel),并使用它渲染文本区域

下面是一个示例代码,它在您单击单元格时增加了选择(您应该修改它以根据单击的鼠标位置设置适当的插入符号位置),代码是脏的(您应该稍微清理一下),但可以工作:

在单元格渲染器中插入此选项:

CellValue myValue = (CellValue)value;
HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(
        Color.green);
textField.getHighlighter().removeAllHighlights();
try {
    textField.getHighlighter().addHighlight(myValue.highlightStart, myValue.highlightEnd, painter);
} catch (BadLocationException e) {
    System.out.println("Miss");
}
下面是MyModel的示例:

public class MyModel extends AbstractTableModel {
    class CellValue {
        String value;
        int highlightStart;
        int highlightEnd;

        CellValue(String val) {
            this.value = val;
        }

        @Override
        public String toString() {
            return value;
        }
    }

    CellValue[][] values = new CellValue[2][7];

    public MyModel() {
        for(int i = 0; i < 2; i++) {
            for(int j=0; j < 7; j++) {
                values[i][j] = new CellValue(i + ":" + j);
            }
        }
    }

    @Override
    public int getColumnCount() {
        return 7;
    }

    @Override
    public int getRowCount() {
        return 2;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return values[rowIndex][columnIndex];
    }
}
公共类MyModel扩展了AbstractTableModel{
类单元值{
字符串值;
int highlightStart;
int高亮显示;
单元格值(字符串值){
this.value=val;
}
@凌驾
公共字符串toString(){
返回值;
}
}
CellValue[][]值=新的CellValue[2][7];
公共MyModel(){
对于(int i=0;i<2;i++){
对于(int j=0;j<7;j++){
值[i][j]=新的单元格值(i+“:”+j);
}
}
}
@凌驾
public int getColumnCount(){
返回7;
}
@凌驾
public int getRowCount(){
返回2;
}
@凌驾
公共对象getValueAt(int行索引、int列索引){
返回值[rowIndex][columnIndex];
}
}
这是一个主要的类:

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(500,500));

        final JTable table = new JTable(new MyModel());
        for(int i =0; i < 7; i++) {
            table.getColumnModel().getColumn(i).setCellRenderer(new tblCalendarRenderer());
        }

        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int row = table.rowAtPoint(e.getPoint());
                int column = table.columnAtPoint(e.getPoint());

                Object obj = table.getValueAt(row, column);
                System.out.println("value " + obj);
                CellValue cellValue = (CellValue)obj;
                cellValue.highlightEnd++;
                table.repaint();
            }
        });
        table.setRowHeight(50);
        JScrollPane scp = new JScrollPane(table);
        frame.add(scp);
        frame.setVisible(true);
    }
}
公共类主{
公共静态void main(字符串[]args){
JFrame=新JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
框架设置尺寸(新尺寸(500500));
最终JTable表=新JTable(新MyModel());
对于(int i=0;i<7;i++){
table.getColumnModel().getColumn(i).setCellRenderer(新的tblCalendarRenderer());
}
表.addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
int row=表.rowAtPoint(e.getPoint());
int column=table.columnAtPoint(如getPoint());
Object obj=table.getValueAt(行、列);
系统输出打印项次(“值”+obj);
CellValue CellValue=(CellValue)obj;
cellValue.Highlighted++;
表1.repaint();
}
});
表1.设置行高(50);
JScrollPane scp=新的JScrollPane(表);
帧。添加(scp);
frame.setVisible(true);
}
}

渲染器只是将单元格内的JTextArea绘制为图像。因此,突出显示文本是行不通的。在我看来,唯一可行的方法是在渲染器中使用JEditorPane,通过文本样式突出显示相应部分


在每一个表单元中读取更多的数据,考虑一个日期,所以如果一个日期包含多个事件,我希望用户可以选择每个事件来编辑它们。嗨,我尝试使用你的代码,但是我得到这个错误,java.郎。整数不能被投到uI. EngestFrimyMyMeal$CyValue.你应该在把它转换成CyValk之前检查值的实例。在渲染器中有一行:“if(Integer.parseInt(value.toString())==realDay”。请删除它以测试代码,当一切正常时,您应该知道如何使用它来解决问题。(请不要忘记这一行:final JTable table=new JTable(new MyModel());)