ご覧いただき誠にありがとうございます。Java初学者です。
丸3日かけ、あらゆる方法を模索してきたつもりですが、
スキルが不足しており実装できず非常に困っております。
どなたかお助け頂けないでしょうか。どんなアドバイスでも歓迎いたします。
前提・実現したいこと
JavaFXとSceneBuilderにてMySQLと連携させたデスクトップアプリを製作しています。
MySQLから取得するあらゆるカラム数のデータを、TableViewで動的に表示させたいと考えています。
(ユーザーに、複数の検索条件の中から任意のものを選択してもらい、それぞれのデータ結果のカラム数に応じてカラム数を自動で変え、表示させたいです。)
今回参考にしたのがこちらです。
発生している問題・エラーメッセージ
検索を実行してもTableViewに表示されません。
ちなみに特にエラーは出ませんが、Eclipseのエディター上で警告は出ます。
- ObservableList は raw 型です。総称型 ObservableList<E> への参照は、パラメーター化する必要があります
型の安全性: メソッド setCellValueFactory(Callback) は raw 型 TableColumn に属しています。総称型 TableColumn<S,T> への参照はパラメーター化される必要があります
しかし直接的な原因ではないのではと考えています。
該当のソースコード
※文字数制限のため、不要と思われる部分は添削しています。(全文は後述のGitHubリンクをご覧ください。)
※なお、今回は動作表示の実装を優先しているため、
コンボボックスの選択肢の読み取りや、対応するSQL文の実装は、現時点で未完了です。
##### MySQLDaoクラス(データベース接続・SQL文を一括管理)
該当部分は28~58行目のsearchTableViewPays()メソッドです。
Java
1package mysql; 2 3import java.sql.Connection; 4import java.sql.DriverManager; 5import java.sql.PreparedStatement; 6import java.sql.ResultSet; 7import java.sql.SQLException; 8import java.sql.Statement; 9import java.time.LocalDate; 10import controller.TableViewItem; 11import javafx.collections.FXCollections; 12import javafx.collections.ObservableList; 13import javafx.beans.property.SimpleStringProperty; 14import javafx.beans.value.ObservableValue; 15import javafx.scene.control.TableColumn; 16import javafx.scene.control.TableColumn.CellDataFeatures; 17import javafx.scene.control.TableView; 18import javafx.util.Callback; 19 20public class MySQLDao { 21 22 private static final String url = "jdbc:mariadb://localhost:3306/pocketmoney?"; 23 private static final String user = "root"; 24 private static final String password = "root"; 25 26 27 //”支出”履歴画面のTableViewに表示させるデータの取得 28 public ObservableList<ObservableList> searchTableViewPays() throws SQLException { 29 ObservableList<ObservableList> data; 30 data = FXCollections.observableArrayList(); 31 TableView tableview = new TableView(); 32 33 final String SUM_QUERY = "SELECT paid_at, SUM(money) FROM pays GROUP BY paid_at;";//テストクエリ 34 try {Connection conn = DriverManager.getConnection(url, user, password); 35 ResultSet rs = conn.createStatement().executeQuery(SUM_QUERY); 36 37 for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { 38 39 final int j = i; 40 TableColumn col = new TableColumn(rs.getMetaData().getColumnName(i + 1)); 41 42 col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList, String>, ObservableValue<String>>() { 43 44 public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) { 45 46 return new SimpleStringProperty(param.getValue().get(j).toString()); 47 } 48 49 }); 50 51 tableview.getColumns().addAll(col); 52 System.out.println("Column [" + i + "] "); 53 } 54 55 while(rs.next()){ 56 ObservableList<String> row = FXCollections.observableArrayList(); 57 for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { 58 row.add(rs.getString(i)); 59 } 60 System.out.println("Row [1] added " + row); 61 data.add(row); 62 } 63 }catch(SQLException e) { 64 System.out.println("SQLException:" + e.getMessage()); 65 e.printStackTrace(); 66 } 67 return data; 68 } 69}
PaysReportController(コントローラークラス)
該当部分は49~62行目のonSearchButton(ActionEvent event)メソッドです
Java
1package controller; 2 3import java.io.IOException; 4import java.net.URL; 5import java.sql.SQLException; 6import java.util.ResourceBundle; 7import javafx.fxml.Initializable; 8import javafx.event.ActionEvent; 9import javafx.fxml.FXML; 10import javafx.fxml.FXMLLoader; 11import javafx.scene.Node; 12import javafx.scene.Parent; 13import javafx.scene.Scene; 14import javafx.scene.control.Button; 15import javafx.scene.control.ComboBox; 16import javafx.scene.control.TableView; 17import javafx.stage.Stage; 18import javafx.stage.Window; 19import mysql.MySQLDao; 20 21public class PaysReportController implements Initializable{ 22 @FXML 23 private TableView table; 24 25 @FXML 26 private ComboBox<String> cbBox; 27 28 @FXML 29 private Button SearchButton; 30 31 @FXML 32 private Button Homebutton; 33 34 @Override 35 public void initialize(URL location, ResourceBundle resources) { 36 37 } 38 39 @FXML 40 void onSearchButton(ActionEvent event) { 41 42 //コンボボックスで選択された条件をDaoに渡し、結果をTableViewに動的に表示させる 43 try { 44 MySQLDao mysq = new MySQLDao(); 45 table.setItems(mysq.searchTableViewPays()); 46 } catch(SQLException e) { 47 System.out.println("SQLException:" + e.getMessage()); 48 e.printStackTrace(); 49 } 50 51 } 52 53 @FXML 54 void onHomeButtonCliked(ActionEvent event) { 55 /* 56 * 現在表示されている画面を閉じる 57 */ 58 Scene s = ((Node)event.getSource()).getScene(); 59 Window window = s.getWindow(); 60 window.hide(); 61 62 //画面遷移 63 try { 64 FXMLLoader loader = new FXMLLoader(getClass().getResource("/Main.fxml")); 65 loader.setController(new MainController()); 66 Parent root = loader.load(); 67 Scene scene = new Scene(root); 68 69 Stage stage = new Stage(); 70 stage.setTitle("お小遣い管理アプリ"); 71 stage.setScene(scene); 72 stage.show(); 73 }catch(IOException e) { 74 e.printStackTrace(); 75 } 76 } 77}
PaysReport.fxml
fxml
1<?xml version="1.0" encoding="UTF-8"?> 2 3<?import java.lang.String?> 4<?import javafx.collections.FXCollections?> 5<?import javafx.geometry.Rectangle2D?> 6<?import javafx.scene.control.Button?> 7<?import javafx.scene.control.ComboBox?> 8<?import javafx.scene.control.Label?> 9<?import javafx.scene.control.TableView?> 10<?import javafx.scene.image.Image?> 11<?import javafx.scene.image.ImageView?> 12<?import javafx.scene.layout.AnchorPane?> 13<?import javafx.scene.layout.Pane?> 14<?import javafx.scene.text.Font?> 15 16<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" 17 minHeight="-Infinity" minWidth="-Infinity" prefHeight="592.0" 18 prefWidth="488.0" style="-fx-background-color: z;" 19 xmlns="http://javafx.com/javafx/11.0.1" 20 xmlns:fx="http://javafx.com/fxml/1" 21 fx:controller="controller.PaysReportController"> 22 <children> 23 <Pane prefHeight="80.0" prefWidth="650.0" 24 style="-fx-background-color: #ffbf00;" AnchorPane.leftAnchor="0.0" 25 AnchorPane.rightAnchor="0.0"> 26 <children> 27 <Label layoutX="109.0" layoutY="17.0" prefHeight="47.0" 28 prefWidth="271.0" text=" これまでの支出" textFill="#979797"> 29 <font> 30 <Font size="32.0" /> 31 </font> 32 </Label> 33 <ImageView fitHeight="37.0" fitWidth="41.0" 34 layoutX="101.0" layoutY="-31.0" pickOnBounds="true" 35 preserveRatio="true" x="30.0" y="50.0"> 36 <image> 37 <Image url="@../images/search.png" /> 38 </image> 39 <viewport> 40 <Rectangle2D /> 41 </viewport> 42 </ImageView> 43 </children> 44 </Pane> 45 <TableView fx:id="table" layoutX="80.0" layoutY="191.0" 46 prefHeight="291.0" prefWidth="329.0" AnchorPane.bottomAnchor="110.0" 47 AnchorPane.leftAnchor="80.0" AnchorPane.rightAnchor="79.0" 48 AnchorPane.topAnchor="191.0" /> 49 <Button fx:id="Homebutton" layoutX="553.0" layoutY="628.0" 50 mnemonicParsing="false" onAction="#onHomeButtonCliked" 51 prefHeight="47.0" prefWidth="51.0" 52 style="-fx-background-color: #ffbf00;" textFill="WHITE" 53 AnchorPane.bottomAnchor="34.0" AnchorPane.rightAnchor="38.0"> 54 <font> 55 <Font size="19.0" /> 56 </font> 57 <graphic> 58 <ImageView fitHeight="40.0" fitWidth="33.0" 59 onDragDetected="#onHomeButtonCliked" pickOnBounds="true" 60 preserveRatio="true" x="30.0" y="50.0"> 61 <image> 62 <Image url="@../images/home.png" /> 63 </image> 64 <viewport> 65 <Rectangle2D /> 66 </viewport> 67 </ImageView> 68 </graphic> 69 </Button> 70 <ComboBox fx:id="cbBox" layoutX="107.0" layoutY="115.0" 71 prefHeight="30.0" prefWidth="214.0" AnchorPane.bottomAnchor="440.0" 72 AnchorPane.leftAnchor="107.0"> 73 <items> 74 <FXCollections fx:factory="observableArrayList"> 75 <String fx:value="日ごとにいくら使ったか" /> 76 <String fx:value="カテゴリーごとの合計額" /> 77 <String fx:value="総合計額" /> 78 <String fx:value="3000円以上の支出" /> 79 <String fx:value="これまでで一番高い支出" /> 80 </FXCollections> 81 </items> 82 </ComboBox> 83 <Button fx:id="SearchButton" layoutX="357.0" layoutY="115.0" 84 mnemonicParsing="false" onAction="#onSearchButton" prefHeight="30.0" 85 prefWidth="52.0" text="検索" AnchorPane.bottomAnchor="440.0" 86 AnchorPane.leftAnchor="357.0" /> 87 </children> 88</AnchorPane> 89
その他のソースコード
アプリ起動するための最低限のその他のクラスやfxmlを掲載しようとしたのですが、
文字数の関係で掲載できなかった為GitHubのリンク張ります。
必要でしたらご覧ください。
試したこと
私なりに原因として疑っているのは
【MySQLDaoクラス内に実行されないメソッドがある】という点です。
以下、MySQLDaoクラス
Java
1public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) { 2 3 return new SimpleStringProperty(param.getValue().get(j).toString()); 4}
何故かこのメソッドが実行されないのです。
参考サイトのコメント欄に同様の質問があり、
if (param.getValue().get(j) != null) {
return new SimpleStringProperty(param.getValue().get(j).toString());
} else {
return new SimpleStringProperty();
}
to the Table Colum Added Dynamically routine. Then the App doesn’t crash if the cell is empty
を追加とアドバイスがあったので試しましたが解決しませんでした。
【その他試みたこと】
- 異なるSQLクエリでデータ取得。NULL値があるといけないのかと思い、NULL値のないテーブルでの異なるクエリも試しました。
- JavaDocも見ましたが、具体的な解決策は見つけられませんでした。
実行環境
- Windows: 10 Pro 64bit
- Eclipse IDE for Java Developers: 2020-09 (4.17.0)
- JDK: 11.0.9
- JavaFX SDK: 15.0.1
- e(fx)clipse version: 3.6.0
- SceneBuilder: 2.0
以上です。情報が不足していましたら追記致します。宜しくお願い致します。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/01 01:14