Итак, у вас, похоже, есть ряд сложных проблем. Давайте начнем здесь, где вы загружаете данные из базы данных ...
while(rs.next())
{
row = new Vector(columnsNumber);
for(int i=1; i<=columnsNumber; i++)
{
// adding the rows in "row vector"
InputStream binaryStream = rs.getBinaryStream(i);
row.add(rs.getString(i));
row.add(rs.getBinaryStream(8));
}
// adding the rows in the database
rowdata.add(row);
}
Таким образом, для каждой строки в ResultSet
вы смотрите через колонку, НО, для каждого столбца, добавьте значение String
И каплю из последнего столбца, поэтому blob будет добавлен 6 раз (на основе вашего снимка экрана). Это, очевидно, не то, что вы хотите, а также причина, по которой вы получаете [email protected]
в каждом другом столбце.
Вместо этого, вы хотите, чтобы петли через колонку 1
- columnsNumbers - 1
, потому что мы не хотим, чтобы последний столбец, и добавить изображение в последнюю колонку, может быть что-то вроде ...
while(rs.next())
{
row = new Vector(columnsNumber);
for(int i=1; i < columnsNumber; i++)
{
// adding the rows in "row vector"
InputStream binaryStream = rs.getBinaryStream(i);
row.add(rs.getString(i));
}
row.add(rs.getBinaryStream(8));
// adding the rows in the database
rowdata.add(row);
}
Следующей проблемы ...
Все еще печатает [email protected]
в последней колонке !?
Это просто потому, что все, что вы добавили в row
Vector
, было двоичным потоком, представляющим двоичные данные в базе данных, JTable
не имеет средств для этого.Вы должны начать иметь взгляд на Concepts: Editors and Renderers и Using Custom Renderers для получения более подробной информации о том, как вы можете настроить представление этих компонентов
Во-первых, нужно преобразовать двоичные данные в формат изображения, который мы можем использовать
row.add(ImageIO.read(rs.getBinaryStream(8)));
и использовать что-то подобное тому, что описано в Rendering BufferedImage in JTable cell
или
row.add(new ImageIcon(ImageIO.read(rs.getBinaryStream(8))));
, который должен позволить «по умолчанию» TableCellRenderer
, чтобы сделать его
Runnable Пример ...
Предупреждение: Этот пример немного долго, потому что я должен был построить базу данных и заполнить его. Для простоты он использует автономный H2 Database engine, но его следует переводить в большинство других баз данных. В примере также используется тип столбца blob
, это преднамеренно, так как это улучшает производительность механизма базы данных.
Проблема с получением изображений для отображения в JTable
при использовании DefaultTableModel
есть DefaultTableModel
возвращает Object.class
от метода TableModel#getColumnClass
Даже документация DefaultTableModel
делает это к сведению ...
Предупреждения :DefaultTableModel
возвращает класс столбцов Object
. Когда DefaultTableModel
используется с TableRowSorter
это приведет к широкому использованию toString
, который для не String
типов данных стоит дорого. Если вы используете DefaultTableModel
с TableRowSorter
, настоятельно рекомендуется переопределить getColumnClass
, чтобы вернуть соответствующий тип.
я преодолел это, настраивая DefaultTableModel
я вернулся из TestPane#makeTableModel
...
DefaultTableModel model = new DefaultTableModel(new String[]{"Name", "Image"}, 0) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return columnIndex == 1 ? Icon.class : super.getColumnClass(columnIndex);
}
};
Это позволило JTable
использовать правильный TableCellRenderer
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
public class Main {
public static void main(String[] args) {
try {
Class.forName("org.h2.Driver");
makeDatabase();
populateDatabase();
new Main();
} catch (ClassNotFoundException | SQLException | IOException exp) {
exp.printStackTrace();
}
}
protected static Connection makeConnection() throws SQLException {
String path = "jdbc:h2:./TestDatabase";
return DriverManager.getConnection(path, "sa", "");
}
protected static void makeDatabase() throws SQLException {
String cmd = "create table if not exists fruits ("
+ "key BIGINT IDENTITY, "
+ "name varchar(128), "
+ "image longblob)";
try (Connection con = makeConnection()) {
try (PreparedStatement stmt = con.prepareStatement(cmd)) {
System.out.println("> Make fruits table");
stmt.executeUpdate();
}
}
}
protected static void populateDatabase() throws SQLException, IOException {
removeAlFruits();
insert("Apple", ImageIO.read(new File("Apple.png")));
insert("Banana", ImageIO.read(new File("Banana.png")));
insert("Cherries", ImageIO.read(new File("Cherries.png")));
insert("Grapes", ImageIO.read(new File("Grapes.png")));
insert("Orange", ImageIO.read(new File("Orange.png")));
insert("Pear", ImageIO.read(new File("Pear.png")));
insert("Pine Apple", ImageIO.read(new File("PineApple.png")));
insert("Strewberry", ImageIO.read(new File("Strewberry.png")));
insert("Water Melon", ImageIO.read(new File("WaterMelon.png")));
}
protected static void insert(String name, BufferedImage image) throws SQLException, IOException {
String cmd = "insert into fruits (name, image) values (?, ?)";
try (Connection con = makeConnection()) {
try (PreparedStatement stmt = con.prepareStatement(cmd)) {
try (InputStream is = convertImageToInputStream(image)) {
System.out.println("> Insert " + name);
stmt.setString(1, name);
stmt.setBinaryStream(2, is);
int rows = stmt.executeUpdate();
System.out.println("> " + rows + " rows updated");
}
}
}
}
protected static InputStream convertImageToInputStream(BufferedImage image) throws IOException {
ByteArrayOutputStream baos = null;
ByteArrayInputStream bais = null;
try {
baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
baos.close();
bais = new ByteArrayInputStream(baos.toByteArray());
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException ex) {
}
}
}
return bais;
}
protected static void removeAlFruits() throws SQLException {
String cmd = "delete from fruits";
try (Connection con = makeConnection()) {
try (PreparedStatement stmt = con.prepareStatement(cmd)) {
System.out.println("> Remove all fruits");
int rows = stmt.executeUpdate();
System.out.println("> " + rows + " rows updated");
}
}
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (SQLException | IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws SQLException, IOException {
setLayout(new BorderLayout());
DefaultTableModel model = makeTableModel();
JTable table = new JTable(model);
table.setRowHeight(100);
add(new JScrollPane(table));
}
protected DefaultTableModel makeTableModel() throws SQLException, IOException {
DefaultTableModel model = new DefaultTableModel(new String[]{"Name", "Image"}, 0) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return columnIndex == 1 ? Icon.class : super.getColumnClass(columnIndex);
}
};
String cmd = "select name, image from fruits";
try (Connection con = makeConnection()) {
try (PreparedStatement stmt = con.prepareStatement(cmd)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
String name = rs.getString(1);
Blob blob = rs.getBlob(2);
ImageIcon icon = null;
try (InputStream is = blob.getBinaryStream()) {
BufferedImage img = ImageIO.read(is);
icon = new ImageIcon(img);
}
model.addRow(new Object[]{name, icon});
}
}
}
}
return model;
}
}
}
Альтернативного заключается в использовании пользовательское TableCellRender
как показано в Rendering BufferedImage in JTable cell
Массив байт является двоичным представлением изображения, то вам необходимо преобразовать это обратно в «образ» своего рода – MadProgrammer
@MadProgrammer на самом деле это не дубликат, потому что я пытаюсь добавить это в определенном столбце в зависимости от того, сколько строк у меня есть. Так что это динамически сделано, и sql имеет как изображение, так и текст в то же время, в отличие от «возможного дубликата» – rullzing
. Итак, вы не знаете, какие данные действительно находятся в столбце, и вы не знаете, как его декодировать?Как общий комментарий к вашим требованиям, это просто звучит безумно. Вам либо нужны два столбца, один для текста и один для изображения, либо вам нужен другой столбец для указания типа данных. В качестве общей концепции столбец должен быть репрезентативным для типа данных, которые он хранит, например 'image' и' text', а не 'data', что исключает возможность когда-либо узнать, какой тип данных он фактически представляет – MadProgrammer