0

尝试将 JEditorPane 用于 JTable 中的一列而没有任何成功。这样做的主要原因是我想添加一个 hyperLinkListener 和 JEditorPane 显然应该是比默认 JLabel 更好的选择。

private void createQueueTable (String[] columnNames){
Object[][] rows 

    queueModel      = new DefaultTableModel(rows,columnNames){
        @Override
        public Class getColumnClass(int colNum) {
            switch (colNum) {
                case 0:
                    return String.class;
                ...
                case 9:
                    return String.class;    //Comment
                default:
                    return String.class;
            }
        }
    };

    queueTable.setModel(queueModel)    
    TableColumnModel queueTableColumnModel  = queueTable.getColumnModel();      
    TableCellRenderer tcr = new CustomTableCellRenderer();  
    TableCellRenderer scr = new        CustomTablePaneCellRenderer();                       

    int counter =0
    while(counter<columnNames.size()-1){
        queueTableColumnModel.getColumn(counter).setCellRenderer(tcr);
        counter++
    }

    queueTableColumnModel.getColumn(counter).setCellRenderer(scr);      
    ...     
}    
    public class CustomTablePaneCellRenderer extends JTextPane implements TableCellRenderer {
        public CustomTablePaneCellRenderer() {
            setContentType("text/html");
        }

         public Component getTableCellRendererComponent (JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int column) {
            Component cell = super.getTableCellRendererComponent(table, obj, isSelected, hasFocus, row, column);    
                if (isSelected) {
                 } 
                 else{
                      if (row % 2 == 0) 
                            cell.setBackground(new Color(248,248,248))
                      else
                          cell.setBackground(Color.white)
                 } 
                 return cell;
        }           
    }

Exception in thread "AWT-EventQueue-0" groovy.lang.MissingMethodException: No signature of method: CustomTablePaneCellRenderer.getTableCellRendererComponent() is applicable for argument types: (EMSMonster$1, java.lang.String, java.lang.Boolean, java.lang.Boolean, java.lang.Integer, java.lang.Integer) values: [EMSMonster$1[,0,0,1280x304,alignmentX=0.0,alignmentY=0.0,border=,flags=251658568,maximumSize=,minimumSize=,preferredSize=,autoCreateColumnsFromModel=true,autoResizeMode=AUTO_RESIZE_OFF,cell
SelectionEnabled=true,editingColumn=-1,editingRow=-1,gridColor=javax.swing.plaf.ColorUIResource[r=122,g=138,b=153],preferredViewportSize=java.awt.Dimension[width=450,height=400],rowHeight=16,rowMargin=1,rowSelectionAllowed=true,selectionBackground=javax.swing.plaf.ColorUIResource[r=184,g=207,b=229],selectionForeground=sun.swing.PrintColorUIResource[r=51,g=51,b=51],showHorizontalLines=true,showVerticalLines=true], ...]
Possible solutions: getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:130)
        at CustomTablePaneCellRenderer.getTableCellRendererComponent(EMSMonster.groovy:2613)
        at javax.swing.JTable.prepareRenderer(JTable.java:5731)
        at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2114)
        at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2016)
        at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1812)
        at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
        at javax.swing.JComponent.paintComponent(JComponent.java:778)
        at javax.swing.JComponent.paint(JComponent.java:1054)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JViewport.paint(JViewport.java:731)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JComponent.paintChildren(JComponent.java:887)
        at javax.swing.JComponent.paint(JComponent.java:1063)
        at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221)
        at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1512)
        at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1443)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1236)
        at javax.swing.JComponent._paintImmediately(JComponent.java:5169)
        at javax.swing.JComponent.paintImmediately(JComponent.java:4980)
        at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
        at javax.swing.RepaintManager$3.run(RepaintManager.java:784)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:784)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:757)
        at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:706)
        at javax.swing.RepaintManager.access$1000(RepaintManager.java:62)
        at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1651)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
        at java.awt.EventQueue.access$200(EventQueue.java:103)
        at java.awt.EventQueue$3.run(EventQueue.java:688)
        at java.awt.EventQueue$3.run(EventQueue.java:686)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

这或多或少应该是这样的。 截屏

阅读其他几篇文章,我开始怀疑在同一个表格单元格中是否有可能有文本和可点击的链接。

非常感谢您的进一步帮助!!

4

1 回答 1

2

这样做的主要原因是我想添加一个 hyperLinkListener 和 JEditorPane 显然应该是比默认 JLabel 更好的选择。

我实际上会反对这一点。主要原因是,单元格渲染器只是渲染器组件的“快照”,它不是活动组件。这意味着它不响应用户输入,例如键或鼠标侦听器。

就个人而言,我会简单地“渲染” aDefaultTableCellRenderer看起来像一个标准的超链接。

然后我会建立一个“特殊”编辑器,它只响应鼠标点击并相应地激活超链接......

例如...

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.EventObject;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

public class TableHyperLink {

    public static void main(String[] args) {
        new TableHyperLink();
    }

    public TableHyperLink() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    MyModel model = new MyModel();
                    JTable table = new JTable(model);
                    table.setDefaultRenderer(URL.class, new URLTableCellRenderer());
                    table.setDefaultEditor(URL.class, new URLTableCellEditor());

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JScrollPane(table));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (MalformedURLException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class MyModel extends DefaultTableModel {

        public MyModel() throws MalformedURLException {
            super(new Object[][]{{new URL("http://stackoverflow.com")}}, 
                    new Object[]{"Link"});
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return URL.class; // Only have one column :P
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return true;
        }

    }

    public class URLTableCellRenderer extends DefaultTableCellRenderer {

        public URLTableCellRenderer() {
            setForeground(Color.BLUE);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); //To change body of generated methods, choose Tools | Templates.
            if (value instanceof URL) {
                value = "<html><u>" + ((URL)value).toString() + "</u></html>";
                setText(value.toString());
            }
            setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            return this;
        }

    }

    public class URLTableCellEditor extends AbstractCellEditor implements TableCellEditor {

        private URL url;

        @Override
        public Object getCellEditorValue() {
            return url;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            JLabel editor = new JLabel("Clicked");
            if (value instanceof URL) {
                url = (URL) value;
                editor.setText("<html><ul>" + url.toString() + "</ul></html>");
            }
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    stopCellEditing();
                    try {
                        Desktop.getDesktop().browse(url.toURI());
                    } catch (IOException | URISyntaxException ex) {
                        ex.printStackTrace();
                    }
                }
            });
            return editor;
        }

        @Override
        public boolean isCellEditable(EventObject e) {
            boolean editable = false;
            if (e instanceof MouseEvent) {
                MouseEvent me = (MouseEvent) e;
                if (me.getClickCount() == 1 && SwingUtilities.isLeftMouseButton(me)) {
                    editable = true;
                }
            }
            return editable;
        }
    }        
}

您的另一个选择是将 a 附加MouseListener到表格并监视鼠标点击。这将涉及您必须将鼠标点转换为列索引并确定该列是否是模型中的正确列,查找模型中的值,然后根据需要对其进行处理。

它更凌乱,更不便携且容易出错 - 恕我直言

基于反馈的附加示例

我只想指出这是黑客行为。URL 提取基于处理超链接右键单击 JTextPane的答案

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.text.AttributeSet;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;

public class TableHyperLink {

    public static final String PASSWORD_PROMPT = "";

    public static void main(String[] args) {
        new TableHyperLink();
    }

    public TableHyperLink() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    MyModel model = new MyModel();
                    JTable table = new JTable(model);
                    TableColumn column = table.getColumn(table.getColumnName(0));
                    column.setCellEditor(new URLTableCellEditor());
                    column.setCellRenderer(new URLTableCellRenderer());

                    column = table.getColumn(table.getColumnName(1));
                    column.setCellEditor(new URLTableCellEditor());
                    column.setCellRenderer(new URLTableCellRenderer());

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JScrollPane(table));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (MalformedURLException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class MyModel extends DefaultTableModel {

        public MyModel() throws MalformedURLException {
            super(new Object[][]{
                {"<html>This is a <a href='https://stackoverflow.com/questions/18838196/using-jeditorpane-instead-of-default-jlabel-in-jtable/18838244?noredirect=1#comment27831752_18838244'>Test</a>",
                    "<html>This is a <a href='https://stackoverflow.com/questions/18838196/using-jeditorpane-instead-of-default-jlabel-in-jtable/18838244?noredirect=1#comment27831752_18838244'>Test</a>"}},
                    new Object[]{"Link", "Link1"});
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class; // Only have one column :P
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return true;
        }

    }

    /**
     * JEditorPane based renderer.  This gives me issues with fonts, so
     * you may need to do some more playing around with this to 
     * get it to work the way you want
     */
    public class URLTableCellRenderer extends JEditorPane implements TableCellRenderer {

        public URLTableCellRenderer() {
            // Set the content type
            setContentType("text/html");
            // Get rid of the default border
            setBorder(new EmptyBorder(1, 1, 1, 1));
            // Get rid of any margins
            setMargin(new Insets(0, 0, 0, 0));
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            setText(value == null ? null : value.toString());
            return this;
        }

    }

    /**
     * Drop in editor, this really is just a event factory used to capture the events
     * and process them...
     */
    public class URLTableCellEditor extends AbstractCellEditor implements TableCellEditor {

        // This is the value returned to the table model, because I've used a DefaultTableModel
        // this is very important
        private Object value;
        // The point that the mouse click occured
        private Point clickPoint;
        // The url to open
        private URL url;

        @Override
        public Object getCellEditorValue() {
            return value;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            // Capture the current cell value
            this.value = value;
            // Something to return to the table...
            JLabel editor = new JLabel(value == null ? null : value.toString());

            // Get the cell renderer for the current cell
            TableCellRenderer renderer = table.getCellRenderer(row, column);
            // Get the cell component for the renderer (expecting a JEditorPane)
            Component comp = table.prepareRenderer(renderer, row, column);
            // Set the bounds of the component to meet the requirements for the cell rect
            comp.setBounds(table.getCellRect(row, column, false));
            if (comp instanceof JEditorPane) {
                // Get the JEditorPane
                JEditorPane editPane = (JEditorPane) comp;
                // Asdjust the click point to be within the
                // editor context
                clickPoint.x -= comp.getLocation().x;
                clickPoint.y -= comp.getLocation().y;
                try {
                    // Try and get the hyperlink that was clicked
                    url = getHyperlink(editPane, clickPoint);
                } catch (MalformedURLException ex) {
                    ex.printStackTrace();
                }
            }

            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    // Dispose of the editor...
                    // You could use cancelCellEditing() instead and the table won't
                    // try and update the model...
                    stopCellEditing();
                    // Open the URL if possible
                    if (url != null) {
                        try {
                            Desktop.getDesktop().browse(url.toURI());
                        } catch (IOException | URISyntaxException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            });
            return editor;
        }

        @Override
        public boolean isCellEditable(EventObject e) {
            boolean editable = false;
            if (e instanceof MouseEvent) {
                MouseEvent me = (MouseEvent) e;
                if (me.getClickCount() == 1 && SwingUtilities.isLeftMouseButton(me)) {
                    editable = true;
                    // We need to the point that the mouse event occured...
                    clickPoint = me.getPoint();
                }
            }
            return editable;
        }

        /*
         * Try and extract the URL from the hyperlink at the given point
         */
        protected URL getHyperlink(JEditorPane editor, Point p) throws MalformedURLException {
            int pos = editor.viewToModel(p);
            return getHyperlink(editor.getDocument(), pos);
        }

        /*
         * Get the hyperlink from the supplied document at the given position in the document
         */
        protected URL getHyperlink(Document doc, int pos) throws MalformedURLException {
            URL url = null;
            Element h = getHyperlinkElement(doc, pos);
            if (h != null) {
                Object attribute = h.getAttributes().getAttribute(HTML.Tag.A);
                if (attribute instanceof AttributeSet) {
                    AttributeSet set = (AttributeSet) attribute;
                    String href = (String) set.getAttribute(HTML.Attribute.HREF);
                    if (href != null) {
                        url = new URL(href);
                    }
                }
            }
            return url;
        }

        /*
         * Get the element from the document that represents a hyperlink based on the position
         * within teh document.  null if it's not a hyperlink element...
         */
        protected Element getHyperlinkElement(Document doc, int pos) {
            if (pos >= 0 && doc instanceof HTMLDocument) {
                HTMLDocument hdoc = (HTMLDocument) doc;
                Element elem = hdoc.getCharacterElement(pos);
                if (elem.getAttributes().getAttribute(HTML.Tag.A) != null) {
                    return elem;
                }
            }
            return null;
        }
    }
}
于 2013-09-16T22:19:07.023 回答