我正在为数据库制作一个GUI项目,有两个类用于GUI.连接器类用于连接用户凭据.如果凭据正确,则获取AbstractTableModel中的所有数据.当程序运行时,首先GUI有一个按钮,我们在其中单击它并获取底层TableModel中的所有数据.但我面临两个问题.首先在GUI2类中,有时它会像这样打开.
有时它显示这样
http://imageshack.com/i/p3gBDt9Ej
我不知道为什么会这样.第二个问题是当我们从表中选择任何行并单击DeleteSelectedRow按钮时它会删除该行.此按钮在GUI2类中有一个ActionListener.但我想要的是我删除行时自动更新表.我怎样才能做到这一点?
第一个GUI的类
public class Gui extends JFrame {
private static Connector conni;
private Connection conn = null;
private JButton bt;
private JPanel panel;
public Gui() {
super("Frame");
panel = new JPanel();
bt = new JButton("Connect to Database 'World'");
panel.add(bt);
bt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
conn = conni.Connector();
if (conn != null) {
dispose();
new Gui2(conn);
} else {
System.out.println("Return false");
}
}
});
add(panel);
pack();
setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeto(null);
setVisible(true);
}
}
连接器类
public class Connector {
private static Connection conn = null;
public static Connection Connector() {
String data = "jdbc:MysqL://localhost/world";
String user = "root";
String pass = "toot";
try {
conn = DriverManager.getConnection(data, user, pass);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
if (conn != null) {
System.out.println("Connection Suceess");
return conn;
} else {
return conn;
}
}
}
第二个GUI2的类
public class Gui2 extends JFrame {
private Statement state = null;
private ResultSet rs = null;
private JButton bt, delete;
private JTextField text;
private JPanel panel;
private GridBagLayout layout;
private GridBagConstraints constraints;
public Gui2(Connection conn) {
layout = new GridBagLayout();
constraints = new GridBagConstraints();
panel = new JPanel();
panel.setLayout(layout);
text = new JTextField(15);
bt = new JButton("Submit Query");
delete = new JButton("Delete Selected Row");
constraints.insets = new Insets(5, 2, 5, 10);
constraints.gridy = 0;// row 0
constraints.gridx = 0;// column 0
// TextField add on JPanel with given constraints
panel.add(text, constraints);
constraints.gridx++;
panel.add(delete, constraints);
constraints.gridx++;
panel.add(bt, constraints);
// north BorderLayout
add(panel, BorderLayout.norTH);
try {
state = conn.createStatement();
rs = state.executeQuery("select * from city");
} catch (sqlException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
JTable table = new JTable();
JScrollPane spane = new JScrollPane(table);
add(spane, BorderLayout.CENTER);
table.setModel(new TableModel(rs));
delete.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int rowIndex = table.getSelectedRow();
Object columnIndexValue = table.getModel().getValueAt(rowIndex, 0);
String columnName = table.getModel().getColumnName(0);
String query = "delete from world.city" + " where " + columnName + "=" + columnIndexValue;
try {
PreparedStatement pre = conn.prepareStatement(query);
pre.executeUpdate();
JOptionPane.showMessageDialog(null, "Row Deleted Successfully");
} catch (Exception e1) {
JOptionPane.showMessageDialog(null, e1.getMessage());
}
}
});
setSize(817, 538);
setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeto(null);
setVisible(true);
}
}
Tablemodel类
public class TableModel extends AbstractTableModel {
private List ColumnHeader;
private List tableData;
private List rowData;
private int totalcolumn;
public TableModel(ResultSet rs) {
try {
ResultSetMetaData Meta = rs.getMetaData();
totalcolumn = Meta.getColumnCount();
ColumnHeader = new ArrayList(totalcolumn);
tableData = new ArrayList();
for (int i = 1; i <= totalcolumn; i++) {
ColumnHeader.add(Meta.getColumnName(i));
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
SwingWorker<Boolean, List<Object>> worker = new SwingWorker<Boolean, List<Object>>() {
@Override
protected Boolean doInBackground() throws Exception {
while (rs.next()) {
rowData = new ArrayList(totalcolumn);
for (int i = 1; i <= totalcolumn; i++) {
rowData.add(rs.getobject(i));
}
publish(rowData);
}
return true;
}
@Override
protected void process(List chunks) {
tableData.add(chunks);
}
@Override
protected void done() {
try {
Boolean status = get();
JOptionPane.showMessageDialog(null, "Task is DONE");
} catch (InterruptedException e) {
e.printstacktrace();
} catch (ExecutionException e) {
e.printstacktrace();
}
}
};
worker.execute();
}// constructor end
@Override
public int getColumnCount() {
return ColumnHeader.size();
}
public String getColumnName(int columnIndex) {
return (String) ColumnHeader.get(columnIndex);
}
@Override
public int getRowCount() {
return tableData.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
List rowData2 = (List) tableData.get(rowIndex);
return rowData2.get(columnIndex);
}
}
解决方法:
因为数据库访问本质上是异步的,所以你肯定希望在后台检索行以避免阻塞event dispatch thread; SwingWorker
使这相对容易.获取doInBackground(),publish()临时结果的实现中的行,并将它们添加到process()实现中的表模型中. 0700显示了一个概述附带好处的完整示例.该示例循环遍历文件,但您可以替换ResultSet操作.
while (rs.next()) {
//collect row data
publish(rowData);
}
将tableData.add()推迟到process()的实现.
关注自定义TableModel与其包含的SwingWorker之间的交互,以下complete example创建一个具有N行的测试数据库,并显示一个JTable,显示该表的查询结果.特别是,
> JDBCModel扩展了AbstractTableModel.为简单起见,模型的数据存储在List< Row>中,ResultSetMetaData用于列名.作为一个更抽象的替代方案,请参阅Apache Commons DbUtils
,它使用Class Literals as Runtime-Type Tokens和ResultSetMetaData来安全地创建行数据的实例.
> JDBCModel将行检索委托给私有JDBCWorker;它在从ResultSet检索的每一行上调用publish();因为process()在EDT上运行,所以worker可以使用fireTableRowsInserted()优化代表父模型触发的表模型事件的数量.
>同样,delete()的实现应该驻留在JDBCModel中,而不是GUI中;在从数据库中成功删除行并从数据中删除之后,应该使用fireTableRowsDeleted().
>将Thread.sleep()添加到worker的后台循环中,以查看人为增加延迟的效果.
>使用setProgress()和Propertychangelistener(如here所示)显示进度;完成()时的JOptionPane可能是多余的.
>重写getPreferredScrollableViewportSize()以自定义包含JScrollPane的表的大小.
>避免使用类名,例如TableModel,与常见的API名称冲突.
>检查在视图中实现实时filtering的变体here.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.sqlException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
/**
* @see https://stackoverflow.com/a/34742409/230513
* @see https://stackoverflow.com/a/24762078/230513
*/
public class WorkerTest {
private static final int N = 1_000;
private static final String URL = "jdbc:h2:mem:test";
private static final Random r = new Random();
private void display() {
JFrame f = new JFrame("WorkerTest");
f.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
createTestDatabase(N);
JDBCModel model = new JDBCModel(getConnection(), "select * from city");
f.add(new JScrollPane(new JTable(model) {
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(320, 240);
}
}));
f.pack();
f.setLocationRelativeto(null);
f.setVisible(true);
}
private static class Row {
int ID;
String name;
}
private static class JDBCModel extends AbstractTableModel {
private final List<Row> data = new ArrayList<>();
private ResultSet rs = null;
private ResultSetMetaData Meta;
public JDBCModel(Connection conn, String query) {
try {
Statement s = conn.createStatement();
rs = s.executeQuery(query);
Meta = rs.getMetaData();
JDBCWorker worker = new JDBCWorker();
worker.execute();
} catch (sqlException e) {
e.printstacktrace(System.err);
}
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
try {
return Meta.getColumnCount();
} catch (sqlException e) {
e.printstacktrace(System.err);
}
return 0;
}
@Override
public Object getValueAt(int rowIndex, int colIndex) {
Row row = data.get(rowIndex);
switch (colIndex) {
case 0:
return row.ID;
case 1:
return row.name;
}
return null;
}
@Override
public String getColumnName(int colIndex) {
try {
return Meta.getColumnName(colIndex + 1);
} catch (sqlException e) {
e.printstacktrace(System.err);
}
return null;
}
private class JDBCWorker extends SwingWorker<List<Row>, Row> {
@Override
protected List<Row> doInBackground() {
try {
while (rs.next()) {
Row r = new Row();
r.ID = rs.getInt(1);
r.name = rs.getString(2);
publish(r);
}
} catch (sqlException e) {
e.printstacktrace(System.err);
}
return data;
}
@Override
protected void process(List<Row> chunks) {
int n = getRowCount();
for (Row row : chunks) {
data.add(row);
}
fireTableRowsInserted(n, n + chunks.size());
}
}
}
private static void createTestDatabase(int n) {
Connection conn = getConnection();
try {
Statement st = conn.createStatement();
st.execute("create table city(id integer, name varchar2)");
PreparedStatement ps = conn.prepareStatement(
"insert into city values (?, ?)");
for (int i = 0; i < n; i++) {
ps.setInt(1, i);
ps.setString(2, (char) ('A' + r.nextInt(26))
+ String.valueOf(r.nextInt(1_000_000)));
ps.execute();
}
} catch (sqlException ex) {
ex.printstacktrace(System.err);
}
}
private static Connection getConnection() {
try {
return DriverManager.getConnection(URL, "", "");
} catch (sqlException e) {
e.printstacktrace(System.err);
}
return null;
}
public static void main(String[] args) {
EventQueue.invokelater(new Workertest()::display);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。