0

我正在开发一个程序(Java),它应该显示一个允许用户输入 SQL 查询的 GUI,一旦单击执行按钮,结果集应该在 GUI 上显示为表格。我可以看到空白表的初始轮廓,但是一旦执行查询,表就不会更新。我对 Java GUI 很陌生,所以我可能会犯一个非常愚蠢的错误。我想也许我只是显示一个空白的不可编辑的滚动窗格而不是实际的表格,但我不再那么确定了。老实说,我不知道我在哪里搞砸了。

我很确定清除按钮将类似于执行按钮,除了我需要创建一个空白表然后将其显示在那里。我只是无法让表格更新大声笑。无论如何,我要跑题了。我将粘贴下面的代码。下面粘贴了2个类。一个称为 QueryGUI,另一个称为 ResultTable。提前感谢您的帮助!

编辑:有什么我可以做的让这更容易帮助我吗?我已经盯着谷歌、甲骨文的网站和这个网站上的其他线程几个小时了,我不知道为什么表格不会更新/显示。

EDIT2:想通了,我试图将模型设置为我的滚动窗格而不是我的 JTable,这就是它不起作用的原因。

import java.sql.SQLException;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EtchedBorder;

public class QueryGUI extends JFrame implements ActionListener{

private static ResultTable tableModel;

private static String[] jdbcDriverStrings = {"com.mysql.jdbc.Driver", "com.ibm.db2.jdbc.netDB2Driver",
    "oracle.jdbc.driver.OracleDriver", "com.jdbc.odbc.jdbcOdbcDriver"};
private static String[] dbURLStrings = {"jdbc:mysql://localhost:3306/project4", "jdbc://localhost3306/bikedb",
"jdbc:mysql://localhost3306/test"};

static String JDBC_DRIVER = null;
static String DATABASE_URL = null;
static String USERNAME = null;
static String PASSWORD = null;
static String QUERY = null;
private static JComboBox driverList = new JComboBox(jdbcDriverStrings);
private static JComboBox dbURLList = new JComboBox(dbURLStrings);
private static JTextField usernameField = new JTextField(20);
private static JPasswordField passwordField = new JPasswordField(20);
private static JTable resultTable = new JTable(tableModel); // create JTable delegate for tableModel 
private static JTextArea sqlCommandEntry = new JTextArea(7, 30);
private static JScrollPane scrollingSQLCommandEntry = new JScrollPane(
        sqlCommandEntry, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 
        ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
private static JLabel connectionLabel = new JLabel("No Connection Now");

public static void addComponentsToPane(Container pane) {
    JFrame frame = new JFrame("SQL Client GUI - (MJL)");
    pane.setLayout(null);

    //Create all the labels, combo boxes, buttons, and text fields/areas
    JLabel comboAndTextLabel = new JLabel("Enter Database Information");
    JLabel driverLabel = new JLabel("JDBC Driver");
    JLabel dbURLLabel = new JLabel("Database URL");
    JLabel usernameLabel = new JLabel("Username");
    JLabel passwordLabel = new JLabel("Password");
    JLabel SQLEntryLabel = new JLabel("Enter SQL Command");
    JLabel SQLResultLabel = new JLabel("SQL Execution Result");
    JButton connectButton = new JButton("Connect to Database");
    JButton clearButton = new JButton("Clear Command");
    JButton executeButton = new JButton("Execute SQL Command");
    JButton clearResultButton = new JButton("Clear Result Window");


    JScrollPane sqlResultArea = new JScrollPane(resultTable);
    //scrollingSQLCommandEntry.setWrapStyleWord(true);
    //scrollingSQLCommandEntry.setLineWrap(true);

    pane.add(driverList);
    pane.add(dbURLList);
    pane.add(comboAndTextLabel);
    pane.add(driverLabel);
    pane.add(dbURLLabel);
    pane.add(usernameLabel);
    pane.add(passwordLabel);
    pane.add(usernameField);
    pane.add(passwordField);
    pane.add(SQLEntryLabel);
    pane.add(scrollingSQLCommandEntry);
    pane.add(connectionLabel); 
    pane.add(connectButton);
    pane.add(clearButton);
    pane.add(executeButton);
    pane.add(SQLResultLabel);
    pane.add(sqlResultArea);
    pane.add(clearResultButton);
    //pane.add(new JScrollPane(resultTable), BorderLayout.CENTER);


    driverList.addActionListener(driverList);
    dbURLList.addActionListener(dbURLList);

    Insets insets = pane.getInsets();
    //The next giant block of code takes each component and moves them to the
    //desired space on the GUI. It uses absolute positioning
    //This section moves the 5 labels on the top left
    Dimension size = comboAndTextLabel.getPreferredSize();
    comboAndTextLabel.setBounds(8 + insets.left, 5 + insets.top,
            size.width, size.height);
    size = driverLabel.getPreferredSize();
    driverLabel.setBounds(8 + insets.left, 26 + insets.top,
            size.width, size.height);
    size = dbURLLabel.getPreferredSize();
    dbURLLabel.setBounds(8 + insets.left, 54 + insets.top,
            size.width, size.height);
    size = usernameLabel.getPreferredSize();
    usernameLabel.setBounds(8 + insets.left, 80 + insets.top,
            size.width, size.height);
    size = passwordLabel.getPreferredSize();
    passwordLabel.setBounds(8 + insets.left, 105 + insets.top,
            size.width, size.height);

    //This section moves the combo boxes and the text fields on the top left
    size = driverList.getPreferredSize();
    driverList.setBounds(90 + insets.left, 22 + insets.top,
            size.width + 90, size.height);
    size = dbURLList.getPreferredSize();
    dbURLList.setBounds(90 + insets.left, 51 + insets.top,
            size.width + 65, size.height);
    size = usernameField.getPreferredSize();
    usernameField.setBounds(90 + insets.left, 80 + insets.top,
            size.width + 73, size.height);
    size = passwordField.getPreferredSize();
    passwordField.setBounds(90 + insets.left, 104 + insets.top,
            size.width + 73, size.height);

    //This section moves the label and text area on the top right
    size = SQLEntryLabel.getPreferredSize();
    SQLEntryLabel.setBounds(425 + insets.left, 5 + insets.top,
            size.width, size.height);
    size = scrollingSQLCommandEntry.getPreferredSize();
    scrollingSQLCommandEntry.setBounds(425 + insets.left, 24 + insets.top,
            size.width - 1, size.height + 4);
    //Puts a border around the text area on the right
    sqlCommandEntry.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));

    //Moves the connection status label and 3 middle buttons, also sets label color to red 
    size = connectionLabel.getPreferredSize();
    connectionLabel.setForeground(Color.RED);
    connectionLabel.setBounds(8 + insets.left, 180 + insets.top,
            size.width + 175, size.height);
    size = connectButton.getPreferredSize();
    connectButton.setBounds(297 + insets.left, 175 + insets.top,
            size.width, size.height);
    size = clearButton.getPreferredSize();
    clearButton.setBounds(456 + insets.left, 175 + insets.top,
            size.width, size.height);
    size = executeButton.getPreferredSize();
    executeButton.setBounds(588 + insets.left, 175 + insets.top,
            size.width, size.height);

    //Moves SQL execution label and text area as well as clear result window button
    size = SQLResultLabel.getPreferredSize();
    SQLResultLabel.setBounds(8 + insets.left, 200 + insets.top,
            size.width, size.height);
    size = sqlResultArea.getPreferredSize();
    sqlResultArea.setBounds(8 + insets.left, 217 + insets.top,
            size.width + 295, size.height - 177);
    //puts border around result text area   
    resultTable.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
    size = clearResultButton.getPreferredSize();
    clearResultButton.setBounds(20 + insets.left, 451 + insets.top,
            size.width, size.height);

    connectButton.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){
                    try {
                        char[] tempPass = null;
                        USERNAME = usernameField.getText();
                        tempPass = passwordField.getPassword();
                        PASSWORD = String.valueOf(tempPass);
                        JDBC_DRIVER = (String)QueryGUI.driverList.getSelectedItem();
                        DATABASE_URL = (String)QueryGUI.dbURLList.getSelectedItem();
                        tableModel = new ResultTable(JDBC_DRIVER, DATABASE_URL, USERNAME, PASSWORD);
                        connectionLabel.setText("Connected to " + DATABASE_URL);
                    } 
                    catch(ClassNotFoundException classNotFound){
                        JOptionPane.showMessageDialog(null, 
                                "MySQL driver not found", "Driver not found",
                                JOptionPane.ERROR_MESSAGE);

                        System.exit(1); // terminate application
                    } 
                    catch(SQLException sqlException){
                        JOptionPane.showMessageDialog(null, sqlException.getMessage(), 
                                "Database error", JOptionPane.ERROR_MESSAGE);

                        // ensure database connection is closed
                        tableModel.disconnectFromDatabase();

                        System.exit(1);   // terminate application
                    } 
                }
            }
            );

    //create event listener for executeButton
    executeButton.addActionListener( 
            new ActionListener(){
                // pass query to table model
                public void actionPerformed(ActionEvent event){
                    // perform a new query
                    try{
                        tableModel.setQuery(sqlCommandEntry.getText());
                        //These next 2 lines don't work. Bottom one line throws an eror message window
                        //stating can't execute query
                        //tableModel = new ResultTable(JDBC_DRIVER, DATABASE_URL, USERNAME, PASSWORD);
                        //tableModel.setUpdate(sqlCommandEntry.getText());
                    }
                    catch(SQLException sqlException){
                        JOptionPane.showMessageDialog(null, sqlException.getMessage(),
                                "Database error", JOptionPane.ERROR_MESSAGE );
                    } 
                } 
            }            
            ); 
}

//JDBC Driver combo box action
public void actionPerformed(ActionEvent e){
    if(e.getSource() == QueryGUI.driverList){
        //JComboBox cb = (JComboBox)e.getSource();
        JDBC_DRIVER = (String)QueryGUI.driverList.getSelectedItem();            
    }
    if(e.getSource() == QueryGUI.dbURLList){
        DATABASE_URL = (String)QueryGUI.dbURLList.getSelectedItem();
    }
}

//Create the GUI and show it.
private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("SQL Client GUI - (MJL)");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Set up the content pane.
    addComponentsToPane(frame.getContentPane());

    //Size and display the window.
    Insets insets = frame.getInsets();
    frame.setSize(785 + insets.left + insets.right,
            525 + insets.top + insets.bottom);
    frame.setVisible(true);

    //dispose of window when user quits application (this overrides
    // the default of HIDE_ON_CLOSE)
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

    // ensure database connection is closed when user quits application
    frame.addWindowListener(
            new WindowAdapter(){
                // disconnect from database and exit when window has closed
                public void windowClosed(WindowEvent event){
                    tableModel.disconnectFromDatabase();
                    System.exit(0);
                } 
            } 
            ); 

}

public static void main(String[] args) {

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            //new QueryGUI();
            createAndShowGUI();
        }
    });
}
}

这是二等

import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.swing.table.AbstractTableModel;

public class ResultTable extends AbstractTableModel{
private Connection connection;
private Statement statement;
private ResultSet resultSet;
private ResultSetMetaData metaData;
private int numberOfRows;

// keep track of database connection status
private boolean connectedToDatabase = false;

// constructor initializes resultSet and obtains its meta data object;
// determines number of rows
public ResultTable(String driver, String url, 
        String username, String password) 
                throws SQLException, ClassNotFoundException{

    // load database driver class
    Class.forName(driver);

    // connect to database
    connection = DriverManager.getConnection(url, username, password);
    // create Statement to query database
    statement = connection.createStatement(
            ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

    // update database connection status
    connectedToDatabase = true;

    // set query and execute it
    //setQuery(query);
} 

// get class that represents column type
public Class getColumnClass(int column) throws IllegalStateException{
    // ensure database connection is available
    if(!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    // determine Java class of column
    try{
        String className = metaData.getColumnClassName(column + 1);

        // return Class object that represents className
        return Class.forName(className);
    } 
    catch(Exception exception){
        exception.printStackTrace();
    } 

    return Object.class; // if problems occur above, assume type Object
} 

// get number of columns in ResultSet
public int getColumnCount() throws IllegalStateException{   
    // ensure database connection is available
    System.out.println("inside getColumnCount");
    if(!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    // determine number of columns
    try{
        return metaData.getColumnCount(); 
    } 
    catch(SQLException sqlException){
        sqlException.printStackTrace();
    } 

    return 0; // if problems occur above, return 0 for number of columns
} 

// get name of a particular column in ResultSet
public String getColumnName(int column) throws IllegalStateException{    
    // ensure database connection is available
    if(!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    // determine column name
    try{
        return metaData.getColumnName(column + 1);  
    } 
    catch(SQLException sqlException){
        sqlException.printStackTrace();
    } 

    return ""; // if problems, return empty string for column name
} 

// return number of rows in ResultSet
public int getRowCount() throws IllegalStateException{      
    // ensure database connection is available
    if(!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    return numberOfRows;
} 

// obtain value in particular row and column
public Object getValueAt(int row, int column) throws IllegalStateException{
    // ensure database connection is available
    if(!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    // obtain a value at specified ResultSet row and column
    try{
        resultSet.next();  /* fixes a bug in MySQL/Java with date format */
        resultSet.absolute( row + 1 );
        return resultSet.getObject( column + 1 );
    } 
    catch(SQLException sqlException){
        sqlException.printStackTrace();
    } 

    return ""; // if problems, return empty string object
} 

// set new database query string
public void setQuery(String query) 
        throws SQLException, IllegalStateException{
    // ensure database connection is available
    if(!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    // specify query and execute it
    resultSet = statement.executeQuery(query);

    // obtain meta data for ResultSet
    metaData = resultSet.getMetaData();

    // determine number of rows in ResultSet
    resultSet.last();                   // move to last row
    numberOfRows = resultSet.getRow();  // get row number      

    // notify JTable that model has changed
    fireTableStructureChanged();
} 


// set new database update-query string - this isn't working presently.
//Gives me an error message saying "Cannot issue select".
/*public void setUpdate(String query) 
        throws SQLException, IllegalStateException{
    int res;
    // ensure database connection is available
    if (!connectedToDatabase) 
        throw new IllegalStateException("Not Connected to Database");

    // specify query and execute it
    res = statement.executeUpdate(query);

    // notify JTable that model has changed
    fireTableStructureChanged();
} */

// close Statement and Connection               
public void disconnectFromDatabase(){              
    if (!connectedToDatabase)                  
        return;

    // close Statement and Connection            
    try{                                            
        statement.close();                        
        connection.close();                       
    }                                  
    catch(SQLException sqlException){                                            
        sqlException.printStackTrace();           
    }              
    finally{   // update database connection status                                            
        connectedToDatabase = false;              
    } 
}           
}
4

1 回答 1

1

这是一个很大的努力。但是,有很多代码需要一次进行故障排除。如果您想在未来尽快获得帮助,我建议您扔掉所有不必要的东西。例如,您可能会丢弃除 JTable 之外的所有 GUI 组件。

最终,我相信您的问题是您正在静态创建 JTable。在您创建它时,您的 TableModel 尚未初始化,因此它被设置为 NULL。稍后,当您初始化 TableModel 时,它不会更新 JTable 的引用(它仍将设置为 null)。

我建议使用空构造函数创建 JTable,然后在构造 TableModel 后调用 setModel。

此外,如果您有可用的开发人员,我强烈建议您让经验丰富的开发人员对其进行审查(StackOverflow 并不是真正为此设计的)。虽然很明显,您为此付出了很多努力,但这里有很多事情使代码难以阅读和维护,她可以帮助解释这些问题背后的原因。

例如:

  • 你有很多静态变量,这往往会导致无法测试的代码。
  • 在 GUI 开发中往往不鼓励绝对定位。
  • 您正在连接到数据库并在 Swing 事件线程中执行大量阻塞 I/O。
  • 您的连接在应用程序的整个生命周期内都保持活动状态,这可能会消耗资源,通常您会希望使用连接池或拥有短暂的连接。
于 2013-10-25T23:28:51.793 回答