---
# System prepended metadata

title: JAVA-11 Table、Model
tags: [JAVA]

---

20241121(四)
:::success
[TOC]
:::
<span style=color:orange>本文可能存在偏誤或不確定的部分為此色</span>

---
###    <p style="color: #00CCDD;">Table、Model</p>
####    <p style="color: #DA8359;">屬性、介面、方法</p>
javax.swing.JTable extends JComponent

####    <p style="color: #DA8359;">視窗頁面</p>
```java=
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import tw.Issac.apis.FoodTable;

public class MyFood extends JFrame{
	// 宣告將使用到的物件
	private FoodTable foodTable;
	private JButton del;
	
	public MyFood() {
		// 視窗介面
		setLayout(new BorderLayout());
		foodTable = new FoodTable();
		JScrollPane jsp = new JScrollPane(foodTable);
		add(jsp, BorderLayout.CENTER);
		
		// 按鈕介面
		JPanel top = new JPanel(new FlowLayout());
		del = new JButton("Delete");
		top.add(del);
		add(top, BorderLayout.NORTH);
		
		// 視窗規格
		setSize(640, 480);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		initEvent();
	}
	
	// 程式執行指令
	private void initEvent() {
		del.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				foodTable.delRow();
			}
		});
	}
	
	// 程式進入點，new出本程式物件給其他兩隻使用
	public static void main(String[] args) {
		new MyFood();
	}
}
```
---





####    <p style="color: #DA8359;">自訂類別api</p>
```java=
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class FoodTable extends JTable{
	private FoodModel model;
	private FoodDB db;
	
	public FoodTable() {
		try {
			db = new FoodDB();
			db.query();
		}catch(Exception e) {
			System.out.println(e);
		}
		model = new FoodModel();
		setModel(model);
		model.setColumnIdentifiers(db.getFieldNames());
	}
	
	public void delRow() {
//		System.out.println(getSelectedRow());	
		//確認一下刪掉的是哪一列，可以看到這裡是從0匴起，而DB是從1算起，需要特別注意
		db.delData(getSelectedRow());
		repaint();
	}
	
	private class FoodModel extends DefaultTableModel{
		@Override
		public int getRowCount() {
			return db.getRows();
		}
		@Override
		public int getColumnCount() {
			return db.getCols();
		}
		@Override
		public Object getValueAt(int row, int column) {
			return db.getData(row, column);
		}
		@Override
		public boolean isCellEditable(int row, int column) {
			return column != 0;
		}
		@Override
		public void setValueAt(Object aValue, int row, int column) {
			db.updateData((String)aValue, row, column);
		}
	}
}
```
---





####    <p style="color: #DA8359;">串接DB與資料呈現</p>
使用的資料是前一個筆記中導入的[opendata](https://hackmd.io/V0wW2wTlSDyYH2EqXN-HHA#opendata-%E5%B0%8E%E5%85%A5-database)
```java=
import java.sql.*;
import java.util.Properties;

public class FoodDB {
	private final static String URL = "jdbc:mysql://localhost/issac";
	private final static String USER = "root";
	private final static String PASSWORD = "";
	private final static String SQL_QUERY = "SELECT id 編號, name 商家名稱, addr 地址, tel 電話 from food";

	private Connection conn;
	private ResultSet rs;
	private String[] fieldNames;

	public FoodDB() throws Exception {
		Properties prop = new Properties();
		prop.put("user", USER);
		prop.put("password", PASSWORD);
		conn = DriverManager.getConnection(URL, prop);
	}

	public void query() throws Exception {
		query(SQL_QUERY);
	}

	public void query(String sql) throws Exception {
		Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
		rs = stmt.executeQuery(sql);

		ResultSetMetaData rsmd = rs.getMetaData();
		fieldNames = new String[rsmd.getColumnCount()];
		for (int i = 0; i < fieldNames.length; i++) {
			fieldNames[i] = rsmd.getColumnLabel(i + 1);
		}
	}

	public int getRows() {
		try {
			rs.last();
			return rs.getRow();
		} catch (Exception e) {
			return 0;
		}
	}

	public int getCols() {
		return fieldNames.length;
	}

	// row, col => 0-base
	public String getData(int row, int col) {
		try {
			rs.absolute(row + 1);
			return rs.getString(fieldNames[col]);
		} catch (Exception e) {
			return "ERROR";
		}
	}

	public String[] getFieldNames() {
		return fieldNames;
	}

	// 0-base
	public void delData(int row) {
		try {
			rs.absolute(row + 1);
			rs.deleteRow();
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void updateData(String newData, int row, int col) {
		try {
			rs.absolute(row + 1);
			rs.updateString(col + 1, newData);
			rs.updateRow();
		} catch (Exception e) {
			System.out.println(e);
		}
	}
}
```