如何用JavaFX中的Sqlite数据库中的图像填充tableview单元格? [英] How to populate a tableview cell with an image from Sqlite database in JavaFX?

查看:214
本文介绍了如何用JavaFX中的Sqlite数据库中的图像填充tableview单元格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用JavaFX使用存储在Sqlite数据库中的图像填充tableView单元格。我在这里找到了一些非常好的信息,感觉我已经非常接近了。如果没有图像,我希望它保持约束,使细胞总是相同的大小。存储在数据库中的图像是300x300,但行将小得多。到目前为止我的代码是:

I am trying to populate a tableView cell with an image stored on a Sqlite database using JavaFX. I have found some really good information on here and feel like I am getting pretty close. If there is no image I would like it to keep the constraints to make the cells the same size always. The images stored on the database are 300x300, but the rows will be much smaller. So far the code I have is :

public void buildDataAseptic(){
    listNum = 1;        
    data = FXCollections.observableArrayList();
    try{   

        String SQL = "Select * from aseptic_parts_list";             //Order By id
        ResultSet rs = con.createStatement().executeQuery(SQL);  
        while(rs.next()){
            Part cm = new Part();
            cm.id.set(listNum++);


            if (rs.getBlob("image") != null ) {
            Blob blob = rs.getBlob("image");
            byte[] ndata = blob.getBytes(1, (int) blob.length());
            image = new Image(new ByteArrayInputStream(ndata));
            ImageView imageView = new ImageView();
            imageView.setImage(image);
            imageView.setFitWidth(70);
            imageView.setFitHeight(80);
            cm.image.set(image);
            }


            cm.vendor_part_number.set(rs.getString("vendor_part_number"));
            cm.description.set(rs.getString("description"));
            cm.quantity.set(rs.getInt("quantity"));
            cm.vendor_name.set(rs.getString("vendor_name"));
            cm.model_number.set(rs.getString("model_number"));
            cm.equipment_id.set(rs.getString("equipment_id"));
            data.add(cm);                  
        }
        tableView.setItems(data);

    }
    catch(Exception e){
          e.printStackTrace();
          System.out.println("Error on Building Data" + e.getMessage());            
    }
    filterData();
    //filterEquipIDData();
}

这只是一个从comboBox调用的特定方法。除了图像之外,所有其他数据都在表中填充。在initialize()方法中,我将列设置为:

this is just one particular method that is called from a comboBox. All of the other data is populating fine in the table except the image. In the initialize() method I have the columns set up as:

assert tableView != null;
     idCol.setCellValueFactory(
            new PropertyValueFactory<Part, Integer>("id"));
     imgCol.setCellValueFactory(
            new PropertyValueFactory<Object,ImageView>("image"));
     pnCol.setCellValueFactory(
            new PropertyValueFactory<Part,String>("vendor_part_number"));
     descCol.setCellValueFactory(
            new PropertyValueFactory<Part,String>("description"));  
     quantityCol.setCellValueFactory(                
        new PropertyValueFactory<Part,Integer>("quantity"));
     venCol.setCellValueFactory(
            new PropertyValueFactory<Part,String>("vendor_name"));
     mnCol.setCellValueFactory(
                new PropertyValueFactory<Part,String>("model_number"));
     equipmentIDCol.setCellValueFactory(                
            new PropertyValueFactory<Part,String>("equipment_id"));

存储图像对象的Part类是:

The Part class where the image object is stored is:

public SimpleObjectProperty<Image> image = new SimpleObjectProperty<>();
public Object getImage() {
    return image.get();
}

我一直在摆弄这几天,感觉非常接近,只是没有雪茄,请帮助和谢谢!

I have been fiddling with this for a few days now and feel pretty close, just no cigar, please help and thanks!

推荐答案

以下是使用图像填充TableView单元格的示例。

Here is an example for populating TableView cells with images.

解决方案的关键是适当地设置单元格值工厂和单元格工厂:

The key to the solution is to set the cell value factory and the cell factory appropriately:

TableColumn<Fish, Image> imageColumn = new TableColumn<>("Picture");
imageColumn.setCellValueFactory(new PropertyValueFactory<>("image"));
imageColumn.setCellFactory(param -> new ImageTableCell<>());

其中ImageTableCell类包含ImageView作为单元格的图形,并将ImageView更新为底层图像数据更改:

Where the ImageTableCell class contains an ImageView as the graphic for the cell and updates the ImageView as the underlying image data changes:

private class ImageTableCell<S> extends TableCell<S, Image> {
    final ImageView imageView = new ImageView();

    ImageTableCell() {
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    }

    @Override
    protected void updateItem(Image item, boolean empty) {
        super.updateItem(item, empty);

        if (empty || item == null) {
            imageView.setImage(null);
            setText(null);
            setGraphic(null);
        }

        imageView.setImage(item);
        setGraphic(imageView);
    }
}

有关此实施的一点需要注意的是它假设将所有图像加载到表的基础数据结构中。这意味着如果表中有很多行,则会占用大量数据,因为所有图像都会加载到内存中。另一种解决方案是基础数据结构只是存储图像的地址(url)而不是图像数据本身,然后在单元工厂中加载图像(可能通过LRU缓存机制)。不同方法之间的权衡取决于GUI的操作速度和用户交互时消耗的资源(这是所有内存中方法优化的方式),而不是较慢的GUI但减少了内存占用(这就是在updateItem调用中动态加载图像将优化)。一般来说,我觉得最好尽快保持updateItem调用的速度,这就是解决方案按原样显示的原因。

One thing to note about this implementation is that it assumes that all images are loaded up into the underlying data structure for the table. This means that if you had a lot of rows in the table, you would be consuming massive amounts of data as all images would be loaded into memory. An alternate solution would be for the underlying data structure just to store the address (url) of the image rather than the image data itself, then load up the image in the cell factory (possibly via an LRU cache mechanism). The trade-off between the different approaches, is speed of operation of the GUI and resources consumed as the user interacts (which is what the all in-memory approach here optimizes for), versus a slower GUI but reduced memory footprint (which is what dymanically loading images in the updateItem call would optimize for). In general, I feel it is best to try to keep the speed of the updateItem call very quick, which is why the solution is presented as is.

我不会提供一个也集成了SQLLite的样本,因为我对该技术一无所知,因此解决方案与数据库系统的进一步集成由读者完成。

I won't supply a sample which also integrates SQLLite as I have no knowledge of that technology, so further integration of the solution with a database system is left up to the reader.

完整代码

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.*;
import javafx.stage.Stage;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ImageTable extends Application {

    @Override
    public void start(Stage stage) {
        List<Fish> fish = Arrays.stream(fishData)
                .map(data -> new Fish(data[0], new Image(data[1])))
                .collect(Collectors.toList());

        TableView<Fish> tableView = new TableView<>(FXCollections.observableList(fish));

        TableColumn<Fish, String> nameColumn = new TableColumn<>("Name");
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        tableView.getColumns().add(nameColumn);
        TableColumn<Fish, Image> imageColumn = new TableColumn<>("Picture");
        imageColumn.setCellValueFactory(new PropertyValueFactory<>("image"));
        imageColumn.setCellFactory(param -> new ImageTableCell<>());
        tableView.getColumns().add(imageColumn);

        stage.setScene(new Scene(tableView));
        stage.show();
    }

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

    // image license: linkware - backlink to http://www.fasticon.com
    private static final String[][] fishData = {
            { "Blue Fish", "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Blue-Fish-icon.png" },
            { "Red Fish", "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Red-Fish-icon.png" },
            { "Yellow Fish", "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Yellow-Fish-icon.png" },
            { "Green FIsh", "http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Green-Fish-icon.png" }
    };

    private class ImageTableCell<S> extends TableCell<S, Image> {
        final ImageView imageView = new ImageView();

        ImageTableCell() {
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        @Override
        protected void updateItem(Image item, boolean empty) {
            super.updateItem(item, empty);

            if (empty || item == null) {
                imageView.setImage(null);
                setText(null);
                setGraphic(null);
            }

            imageView.setImage(item);
            setGraphic(imageView);
        }
    }

    public static final class Fish {
        private ReadOnlyStringWrapper name;
        private ReadOnlyObjectWrapper<Image> image;

        public Fish(String name, Image image) {
            this.name = new ReadOnlyStringWrapper(name);
            this.image = new ReadOnlyObjectWrapper<>(image);
        }

        public String getName() {
            return name.get();
        }

        public ReadOnlyStringProperty nameProperty() {
            return name.getReadOnlyProperty();
        }

        public Image getImage() {
            return image.get();
        }

        public ReadOnlyObjectProperty<Image> imageProperty() {
            return image.getReadOnlyProperty();
        }
    }
}

这篇关于如何用JavaFX中的Sqlite数据库中的图像填充tableview单元格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆