2016-01-12 3 views
-1

Я делаю проект GUI Для базы данных есть два класса, которые относятся к GUI's. Класс соединителя используется для подключения к учетным данным пользователя. Если учетные данные верны, то они извлекают все данные в диапазоне от AbstractTableModel. При первом запуске программы GUI есть кнопка, в которой мы нажимаем ее, и она извлекает все данные в базовом TableModel. Но я столкнулся с двумя проблемами. Сначала в классе GUI2, иногда он открывается так.AbstractTableModel GUI display issue

enter image description here

и иногда показывают, как этот

http://imageshack.com/i/p3gBDt9Ej

Я не знаю, почему это происходит. И вторая проблема - когда мы выбираем любую строку из таблицы и нажимаем на кнопку DeleteSelectedRow, она удаляет строку. Эта кнопка имеет ActionListener в классе GUI2. Но я хочу, чтобы я автоматически обновлял таблицу, когда строка была удалена. Как я могу это сделать?

класс для первого 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); 
    } 

} 
+0

поиск TableFromDatabase, ResultSetTableModel – mKorbel

+0

@mKorbel, что вы имеете в виду поиск TableFromDatabase, ResultSetTableModel – hamel123

+0

, например, например, [ТаблицаFromDatabase] (http://stackoverflow.com/search?q=%5Bjtable%5D+TableFromDatabase) и [ResultSetTableModel] (http://stackoverflow.com/search?q=%5Bjtable%5D+ResultSetTableModel) – mKorbel

ответ

6

Поскольку доступ к базе данных по сути асинхронен, вы обязательно захотите извлечь строки в фоновом режиме, чтобы избежать блокировки event dispatch thread; SwingWorker делает это относительно простым. Извлеките строки в вашей реализации doInBackground(), publish() промежуточных результатов и добавьте их в таблицу в вашей реализации process(). Полный пример, который описывает общие преимущества, показан here. Пример прорисовывается через файл, но вы можете заменить свои операции ResultSet.

while (rs.next()) { 
    //collect row data 
    publish(rowData); 
} 

Defer tableData.add() к вашей реализации process().

Сосредоточение на взаимодействии между обычаем TableModel и его содержимым SwingWorker следующего complete example создает тестовую базу данных, имеющую N строк и отображает JTable, показывающие результаты запроса этой таблицы. В частности,

  • JDBCModel расширяет AbstractTableModel. Для простоты модель data хранится в List<Row>, а для названий столбцов используется ResultSetMetaData. В качестве более абстрактной альтернативы см. Apache Commons DbUtils, который использует Class Literals as Runtime-Type Tokens и ResultSetMetaData для безопасного создания экземпляров данных строки.

  • JDBCModel делегировать поиск строк частному JDBCWorker; он вызывает publish() в каждой строке, полученной из ResultSet; потому что process() работает на EDT, рабочий может оптимизировать количество событий модели таблицы, которые он запускает от имени родительской модели, используя fireTableRowsInserted().

  • Аналогичным образом, ваша реализация delete() должна распространяться в JDBCModel, не GUI; он должен fireTableRowsDeleted() после того, как строка успешно удалена из базы данных и удалена с data.

  • Добавить Thread.sleep() в фоновый цикл работника, чтобы увидеть эффект искусственно увеличивающейся задержки.

  • setProgress() и PropertyChangeListener, показаны here, для отображения хода; a JOptionPane, когда done() может быть излишним.

  • Переопределить getPreferredScrollableViewportSize(), чтобы настроить размер прилагаемой таблицы JScrollPane.

  • Избегайте имен классов, например. TableModel, которые сталкиваются с общими именами API.

  • Рассматривается вариант, который реализует живые filtering на вид here.

image

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); 
    } 
} 
+0

Я не знаю, что вы говорите, можете ли вы изменить свой ответ с кодом, который я могу понять? – hamel123

+0

Я не знаю, как писать потоки с моим кодом, как автоматическая таблица обновлений при удалении строки – hamel123

+0

Простите, я не знаю знать любой ярлык для понимания потоков и привязок; подробнее [здесь] (http://stackoverflow.com/q/3422516/230513). – trashgod