我正在创建一个包含JTable的程序,该程序由数据库的数据填充。每行上都有对应的图片,所以我要发生的是,当我将鼠标光标放在该行上时,它将弹出一个tooltipText,其中包含其图片,
tblListOfInmates = new JTable(){
private static final long serialVersionUID = 8240878564742150750L;
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (c instanceof JComponent) {
try{
JComponent jc = (JComponent) c;
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:RIM");
st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
String x = tblListOfInmates.getModel().getValueAt(row, 6).toString();
String sql = "select * from records where ID ='"+x+"'";
rs = st.executeQuery(sql);
java.net.URL url = new File(rs.getString("ID")).toURI().toURL();
final String html = "<html><body>" + "<img src='"+ url + "' width=160 height=120> ";
jc.setToolTipText(html + "<br/>"
+ getValueAt(row, column).toString()
+ ": row, col (" + row + ", " + column + ")");
}catch(Exception e){e.printStackTrace();}
}
return c;
}
};
我得到这个错误。
at RecordManagementSystem.MainFrame$18.prepareRenderer(MainFrame.java:860)
at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JViewport.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$3.run(Unknown Source)
at javax.swing.RepaintManager$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1100(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
我不知道如何正确地做到这一点,我也不知道我的想法是否正确。请告诉我您是否有比此更好的主意=)
最佳答案
我猜想您试图在工具提示中加载的图像是数据库中的斑点。问题是无法从数据库对象创建URL。您可以将url中的url存储到文件系统中的url,但是我认为这可能不可行,因为您不想在数据库和文件系统中都拥有图像。
也许您应该做的是在加载TableModel
时,将所有对应的图像临时保存到文件系统中。您可以使用File.createTempFile
来实现。您可以从该img获取URL。
另请注意,您将需要在后台线程中执行此操作。见Concurrency with Swing
然后,您可以从文件系统访问那些映像,这比尝试一次从db数据库访问更为有效。然后,您可以使用File.getUri().getUrl()
在html字符串中使用文件系统中的url。
您可以使用一种方法来清除这些图像的文件系统。您可能希望在每次加载一组新的表数据时和/或在程序关闭时调用它。
您可以从db blob加载图像并将其写入文件,如下所示
Blob blob = rs.getBlob("img");
int blobLength = (int) blob.length();
byte[] bytes = blob.getBytes(1, blobLength);
blob.free();
BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(img, "png", new File("..."));
这是上面提到的大多数要点的示例。除了后台线程。这两个很懒,但是每次从数据库更新表模型时,您都希望这样做
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.URL;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class TableToolTip {
private Map<String, URL> fileMap;
public TableToolTip() {
fileMap = new HashMap<>();
JTable table = createTable();
JFrame frame = new JFrame();
frame.add(new JScrollPane(table));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JTable createTable() {
JTable table = new JTable(createModel()) {
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
URL url = fileMap.get((String) getValueAt(row, column));
String html = "<html><body>"
+ "<img src='"
+ url
+ "' width=150 height=150> ";
jc.setToolTipText(html + "<br/>"
+ getValueAt(row, column).toString()
+ ": row, col (" + row + ", " + column + ")"
+ "</body></html>");
}
return c;
}
};
return table;
}
private DefaultTableModel createModel() {
DefaultTableModel model = null;
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost/mario", "root", "password");
PreparedStatement ps = conn.prepareStatement("select * from characters");
ResultSet rs = ps.executeQuery();
ResultSetMetaData rsMeta = rs.getMetaData();
String colTitle = rsMeta.getColumnName(1);
model = new DefaultTableModel(new String[]{colTitle}, 0);
while (rs.next()) {
String name = rs.getString("NAME");
model.addRow(new Object[]{name});
File temp = File.createTempFile(name, ".png");
Blob blob = rs.getBlob("IMG");
int blobLength = (int) blob.length();
byte[] bytes = blob.getBytes(1, blobLength);
blob.free();
BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(img, "png", temp);
URL fileURL = temp.toURI().toURL();
fileMap.put(name, fileURL);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return model;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TableToolTip();
}
});
}
}