Bar chart in javafx does not show anything - mysql

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.chart.BarChart?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" prefHeight="600.0" prefWidth="800.0" styleClass="mainFxmlClass" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Views.MonthlyHoursController">
<children>
<VBox alignment="CENTER" layoutX="121.0" layoutY="121.0" prefHeight="600.0" prefWidth="800.0" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label styleClass="header" text="Monthly Hours" />
<HBox prefHeight="292.0" prefWidth="760.0">
<children>
<BarChart fx:id="barChart" prefHeight="292.0" prefWidth="755.0">
<xAxis>
<CategoryAxis fx:id="months" side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis fx:id="hoursWorked" side="LEFT" />
</yAxis>
</BarChart>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="100.0" prefWidth="200.0" spacing="20.0">
<children>
<Button mnemonicParsing="false" text=" Back" />
</children>
</HBox>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
</children>
</AnchorPane>
Above is my fxml file for the bar chart
package Views;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDate;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
public class MonthlyHoursController implements Initializable {
#FXML private BarChart<?, ?> barChart;
#FXML private CategoryAxis months;
#FXML private NumberAxis hoursWorked;
private XYChart.Series currentYearSeries, previousYearSeries;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
currentYearSeries = new XYChart.Series<>();
previousYearSeries = new XYChart.Series<>();
// barChart.setTitle("Hours Worked");
months.setLabel("Months");
hoursWorked.setLabel("Hours Worked");
currentYearSeries.setName(Integer.toString(LocalDate.now().getYear()));
previousYearSeries.setName(Integer.toString(LocalDate.now().getYear()-1));
try {
populateSeriesFromDB();
} catch (SQLException e) {
e.printStackTrace();
}
barChart.getData().addAll(previousYearSeries);
barChart.getData().addAll(currentYearSeries);
}
private void populateSeriesFromDB() throws SQLException {
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
try{
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bakery?useSSL=false", "root",
"a3756421");
statement = conn.createStatement();
String sql = " Select Year(dateworked), monthname(dateworked), sum(hoursworked)" +
"From hoursworked" +
"Group by year(dateworked), month(dateworked)" +
"Order by Year(dateworked), month(dateworked);";
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
if(resultSet.getInt(1)==LocalDate.now().getYear())
currentYearSeries.getData().add(new XYChart.Data(resultSet.getString(2), resultSet.getString(3)));
else if(resultSet.getInt(1)==LocalDate.now().getYear()-1)
previousYearSeries.getData().add(new XYChart.Data(resultSet.getString(2), resultSet.getString(3)));
}
}
catch (SQLException e){
System.err.println(e.getMessage());
}
finally{
if(conn !=null)
conn.close();
if (statement != null)
statement.close();
if(resultSet != null)
resultSet.close();
}
}
}
this is the controller for the fxml.
If I perform
From hoursworked
Group by Year(dateworked), month(dateworked)
Order by Year(dateworked), month(dateworked);
in workbench, it gives below:
However, when I open the fxml file, it doesnt show anything in the bar chart.
Is there something wrong with my javafx or mysql syntax?
The program itself does not give any error when it's run.
I have no idea where to even start fixing this.

Related

I get "Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException" error in my JavaFX App

This is the error.
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml#19-ea/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1857)
at javafx.fxml#19-ea/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
at javafx.base#19-ea/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base#19-ea/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base#19-ea/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base#19-ea/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base#19-ea/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base#19-ea/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19-ea/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19-ea/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19-ea/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19-ea/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19-ea/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base#19-ea/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base#19-ea/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics#19-ea/javafx.scene.Node.fireEvent(Node.java:8797)
at javafx.controls#19-ea/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls#19-ea/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
at javafx.controls#19-ea/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base#19-ea/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base#19-ea/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base#19-ea/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base#19-ea/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base#19-ea/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base#19-ea/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base#19-ea/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19-ea/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19-ea/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19-ea/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base#19-ea/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base#19-ea/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base#19-ea/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base#19-ea/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics#19-ea/javafx.scene.Scene$MouseHandler.process(Scene.java:3881)
at javafx.graphics#19-ea/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
at javafx.graphics#19-ea/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2607)
at javafx.graphics#19-ea/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics#19-ea/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19-ea/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics#19-ea/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics#19-ea/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics#19-ea/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
at javafx.graphics#19-ea/com.sun.glass.ui.View.notifyMouse(View.java:937)
at javafx.graphics#19-ea/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics#19-ea/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at javafx.base#19-ea/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml#19-ea/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
at javafx.fxml#19-ea/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1852)
... 46 more
Caused by: java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:675)
at java.base/java.lang.Integer.valueOf(Integer.java:992)
at com.example.studentdatabase/com.example.studentdatabase.Register.register(Register.java:99)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 53 more
These are my classes and FXMLs
Main class -
package com.example.studentdatabase;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class Main extends Application {
InputStream stream = new FileInputStream("C:\\Users\\dinira francisco\\Desktop\\DDSlogo.jpg");
Image image = new Image(stream);
public Main() throws FileNotFoundException {
}
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("Register.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("Student Database 2023");
stage.getIcons().add(image);
stage.setResizable(false);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
// type here
Register class -
package com.example.studentdatabase;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Statement;
public class Register {
private int studentID=0;
private boolean hasFirstName = false;
private boolean hasLastName = false;
private boolean hasAge = false;
private boolean hasGrade = false;
#FXML
private TextField GradeTF;
#FXML
private Button ageSubmit;
#FXML
private TextField ageTF;
#FXML
private TextField firstNameTF;
#FXML
private Button firstSubmit;
#FXML
private Button gradeSubmit;
#FXML
private TextField lastNameTF;
#FXML
private Button lastsubmit;
#FXML
private Button registerButton;
#FXML
private Label warning;
public void getFirstName(ActionEvent event){
if(firstNameTF.getText().length()>=1){
hasFirstName=true;
firstNameTF.setDisable(true);
}
}
public void getLastName(ActionEvent event){
if(lastNameTF.getText().length()>=1){
hasLastName=true;
lastNameTF.setDisable(true);
}
}
public void getAge(ActionEvent event){
if(ageTF.getText().length()>=1){
hasAge=true;
ageTF.setDisable(true);
}
}
public void getGrade(ActionEvent event){
if(GradeTF.getText().length()>=1){
hasGrade=true;
GradeTF.setDisable(true);
}
}
public void register(ActionEvent event){
if(hasFirstName && hasLastName && hasAge && hasGrade){
studentID++;
warning.setText("Registration Completed!");
warning.setVisible(true);
firstNameTF.setText("");
lastNameTF.setText("");
ageTF.setText("");
GradeTF.setText("");
firstNameTF.setDisable(false);
lastNameTF.setDisable(false);
ageTF.setDisable(false);
GradeTF.setDisable(false);
hasFirstName=false;
hasLastName = false;
hasAge = false;
hasGrade = false;
DatabaseConnection databaseConnection = new DatabaseConnection();
Connection connection = databaseConnection.getConnection();
String registerString = "INSERT INTO student_data(student_id,first_name,last_name,age,grade) VALUES('"+studentID+"','"+firstNameTF.getText()+"','"+lastNameTF.getText()+"','"+Integer.valueOf(ageTF.getText())+"','"+Integer.valueOf(GradeTF.getText())+"')";
try{
Statement statement = connection.createStatement();
statement.executeUpdate(registerString);
}catch(Exception e){
e.printStackTrace();
e.getCause();
}
}else{
warning.setText("Fields are Empty!");
warning.setVisible(true);
}
}
}
Database Connection class -
package com.example.studentdatabase;
import java.sql.Connection;
import java.sql.DriverManager;
public class DatabaseConnection {
public Connection databaseLink;
public Connection getConnection(){
String databaseName = "student_db";
String databaseUser = "root";
String databasePassword = "***";
String url = "jdbc:mysql://localhost/"+databaseName;
try{
Class.forName("com.mysql.cj.jdbc.Driver");
databaseLink = DriverManager.getConnection(url,databaseUser,databasePassword);
}catch (Exception e){
e.printStackTrace();
e.getCause();
}
return databaseLink;
}
}
and FXML -
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="443.0" prefWidth="458.0" style="-fx-background-color: #f0db24;" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.studentdatabase.Register">
<children>
<Label layoutX="161.0" layoutY="25.0" text="Student Database">
<font>
<Font size="17.0" />
</font>
</Label>
<Label layoutX="95.0" layoutY="52.0" text="Sinhala Oratory & Debating Society">
<font>
<Font size="17.0" />
</font>
</Label>
<Label layoutX="106.0" layoutY="78.0" text="D.S.Senanayake College - Col. 08">
<font>
<Font size="17.0" />
</font>
</Label>
<Label layoutX="161.0" layoutY="125.0" text="Registration Form">
<font>
<Font size="17.0" />
</font>
</Label>
<Label layoutX="66.0" layoutY="177.0" text="First Name ">
<font>
<Font size="15.0" />
</font>
</Label>
<Label layoutX="67.0" layoutY="226.0" text="Last Name ">
<font>
<Font size="15.0" />
</font>
</Label>
<Label layoutX="66.0" layoutY="269.0" text="Age">
<font>
<Font size="15.0" />
</font>
</Label>
<Label layoutX="66.0" layoutY="315.0" text="Grade">
<font>
<Font size="15.0" />
</font>
</Label>
<TextField fx:id="firstNameTF" layoutX="154.0" layoutY="175.0" />
<TextField fx:id="lastNameTF" layoutX="154.0" layoutY="224.0" />
<TextField fx:id="ageTF" layoutX="154.0" layoutY="267.0" />
<TextField fx:id="GradeTF" layoutX="154.0" layoutY="313.0" />
<Button fx:id="firstSubmit" layoutX="318.0" layoutY="175.0" mnemonicParsing="false" onAction="#getFirstName" text="Submit" />
<Button fx:id="gradeSubmit" layoutX="318.0" layoutY="313.0" mnemonicParsing="false" onAction="#getGrade" text="Submit" />
<Button fx:id="ageSubmit" layoutX="318.0" layoutY="267.0" mnemonicParsing="false" onAction="#getAge" text="Submit" />
<Button fx:id="lastsubmit" layoutX="318.0" layoutY="224.0" mnemonicParsing="false" onAction="#getLastName" text="Submit" />
<Button fx:id="registerButton" layoutX="192.0" layoutY="358.0" mnemonicParsing="false" onAction="#register" text="Register" />
<Label fx:id="warning" layoutX="175.0" layoutY="399.0" text="Fields are Empty!" textFill="#f70909" visible="false" />
</children>
</AnchorPane>
I searched some solutions in stackoverflow but couldn't solve the issue.
First some notes about your code.
Class DatabaseConnection
Class.forName("com.mysql.cj.jdbc.Driver");
This is no longer needed.
Because of the catch block in method getConnection, the method may return null which means that other methods, that call method getConnection, need to check if null was returned. In my opinion, better to declare that method getConnection throws SQLException. Also, class DatabaseConnection should probably be a singleton which means that method getConnection should be a static method.
Class Register
I think that you should use PreparedStatement rather than Statement.
You should also use try-with-resources
I don't see the need for this line:
e.getCause();
Method printStackTrace will also print the cause – if there is one.
Rather than using variables hasFirstName, hasLastName, hasAge and hasGrade, use bindings which you can set up in method initialize since class Register is your FXML controller. Then you don't need a Submit button for every TextField in your registration form. Data entry forms usually don't require submitting each field individually.
Rather than explicitly setting sizes and locations for each Node, better to use layouts.
Regarding the top Label, you can use a single Label rather than a separate Label for each line of text. You can insert line breaks and you can center align the text.
Now to your problem. You need to "clear" the registration form after you have updated the database (and not before, as you are currently doing in your code).
Here is my version of your application.
Class DatabaseConnection
package com.example.studentdatabase;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static Connection databaseLink;
public static Connection getConnection() throws SQLException {
if (databaseLink == null) {
String databaseName = "student_db";
String databaseUser = "root";
String databasePassword = "***";
String url = "jdbc:mysql://localhost/" + databaseName;
databaseLink = DriverManager.getConnection(url, databaseUser, databasePassword);
}
return databaseLink;
}
}
Class Register
Note that it uses text blocks. It also uses [JavaFX] alerts.
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class Register {
private int studentID = 0;
#FXML
private TextField gradeTF;
#FXML
private TextField ageTF;
#FXML
private TextField firstNameTF;
#FXML
private TextField lastNameTF;
#FXML
private Button registerButton;
public void register(ActionEvent event) {
String registerString = """
INSERT INTO student_data (student_id, first_name, last_name, age, grade)
VALUES (?, ?, ?, ?, ?)
""";
try (Connection connection = DatabaseConnection.getConnection();
PreparedStatement statement = connection.prepareStatement(registerString)) {
statement.setInt(1, ++studentID);
statement.setString(2, firstNameTF.getText());
statement.setString(3, lastNameTF.getText());
statement.setInt(4, Integer.valueOf(ageTF.getText()));
statement.setInt(5, Integer.valueOf(gradeTF.getText()));
statement.executeUpdate();
Alert alert = new Alert(AlertType.INFORMATION);
alert.setContentText("Registration Completed!");
alert.setHeaderText(null);
alert.showAndWait();
firstNameTF.setText("");
lastNameTF.setText("");
ageTF.setText("");
gradeTF.setText("");
firstNameTF.setDisable(false);
lastNameTF.setDisable(false);
ageTF.setDisable(false);
gradeTF.setDisable(false);
}
catch (Exception e) {
e.printStackTrace();
}
}
#FXML
private void initialize() {
registerButton.disableProperty().bind(firstNameTF.textProperty().isEmpty()
.or(lastNameTF.textProperty().isEmpty())
.or(ageTF.textProperty().isEmpty())
.or(gradeTF.textProperty().isEmpty()));
}
}
FXML file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.text.Font?>
<BorderPane style="-fx-background-color: #f0db24;" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.studentdatabase.Register">
<top>
<Label text="Student Database
Sinhala Oratory & Debating Society
D.S.Senanayake College - Col. 08
Registration Form">
<font>
<Font size="17.0" />
</font>
<textAlignment>CENTER</textAlignment>
</Label>
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</BorderPane.margin>
</top>
<center>
<GridPane hgap="10.0" vgap="10.0">
<alignment>CENTER</alignment>
<children>
<Label text="First Name">
<font>
<Font size="15.0" />
</font>
<GridPane.rowIndex>0</GridPane.rowIndex>
<GridPane.columnIndex>0</GridPane.columnIndex>
</Label>
<TextField fx:id="firstNameTF">
<GridPane.rowIndex>0</GridPane.rowIndex>
<GridPane.columnIndex>1</GridPane.columnIndex>
</TextField>
<Label text="Last Name">
<font>
<Font size="15.0" />
</font>
<GridPane.rowIndex>1</GridPane.rowIndex>
<GridPane.columnIndex>0</GridPane.columnIndex>
</Label>
<TextField fx:id="lastNameTF">
<GridPane.rowIndex>1</GridPane.rowIndex>
<GridPane.columnIndex>1</GridPane.columnIndex>
</TextField>
<Label text="Age">
<font>
<Font size="15.0" />
</font>
<GridPane.rowIndex>2</GridPane.rowIndex>
<GridPane.columnIndex>0</GridPane.columnIndex>
</Label>
<TextField fx:id="ageTF">
<GridPane.rowIndex>2</GridPane.rowIndex>
<GridPane.columnIndex>1</GridPane.columnIndex>
</TextField>
<Label text="Grade">
<font>
<Font size="15.0" />
</font>
<GridPane.rowIndex>3</GridPane.rowIndex>
<GridPane.columnIndex>0</GridPane.columnIndex>
</Label>
<TextField fx:id="gradeTF">
<GridPane.rowIndex>3</GridPane.rowIndex>
<GridPane.columnIndex>1</GridPane.columnIndex>
</TextField>
</children>
</GridPane>
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</BorderPane.margin>
</center>
<bottom>
<Button fx:id="registerButton" mnemonicParsing="false" onAction="#register" text="Register" />
<BorderPane.alignment>CENTER</BorderPane.alignment>
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</BorderPane.margin>
</bottom>
</BorderPane>
Class Main was not changed and so is omitted.

JavaFX Table view using MySQL database 'No content in table'

I am new to JavaFX. I develop an JavaFX application. I want to show data from MySQL database in TableView.
When I add data from JavaFX, data is perfectly stored in database, but it shows 'No content in table' in tableview. There is no error in my code, I could not find where I made the mistake. I am using Eclipse IDE.
This is Customer class:
package application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Customer {
private final StringProperty pname;
private final IntegerProperty pphno;
private final StringProperty paddress;
public Customer(String pname,int pphno,String paddress){
this.pname = new SimpleStringProperty(pname);
this.pphno = new SimpleIntegerProperty(pphno);
this.paddress = new SimpleStringProperty(paddress);
}
public StringProperty getpname() {
return pname;
}
public IntegerProperty getpphno() {
return pphno;
}
public StringProperty getpaddress() {
return paddress;
}
}
This is Cust.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="575.0" prefWidth="760.0" xmlns:fx="http://javafx.com/fxml/1"
xmlns="http://javafx.com/javafx/11.0.1" fx:controller="application.CustController">
<children>
<TableView fx:id="tbl_cust" layoutX="16.0" layoutY="249.0" prefHeight="315.0"
prefWidth="730.0">
<columns>
<TableColumn fx:id="tcol_name" prefWidth="235.0" text="Name" />
<TableColumn fx:id="tcol_phno" prefWidth="223.0" text="Phone Number" />
<TableColumn fx:id="tcol_add" prefWidth="271.0" text="Address" />
</columns>
</TableView>
<VBox layoutX="37.0" layoutY="72.0" prefHeight="150.0" prefWidth="169.0" spacing="30.0">
<children>
<Label text="Name" textFill="#a86905">
<font>
<Font name="Georgia Bold" size="20.0" />
</font>
</Label>
<Label layoutX="10.0" layoutY="10.0" text="Phone Number" textFill="#9e5f02">
<font>
<Font name="Georgia Bold" size="20.0" />
</font>
</Label>
<Label layoutX="10.0" layoutY="27.0" text="Address" textFill="#a4450a">
<font>
<Font name="Georgia Bold" size="20.0" />
</font>
</Label>
</children>
</VBox>
<VBox layoutX="220.0" layoutY="79.0" prefHeight="150.0" prefWidth="223.0" spacing="25.0">
<children>
<TextField fx:id="txt_name" />
<TextField fx:id="txt_phno" layoutX="10.0" layoutY="10.0" />
<TextField fx:id="txt_add" layoutX="10.0" layoutY="35.0" />
</children>
</VBox>
<VBox layoutX="559.0" layoutY="56.0" prefHeight="160.0" prefWidth="156.0" spacing="25.0">
<children>
<Button fx:id="btn_save" mnemonicParsing="false" prefHeight="44.0" prefWidth="105.0"
text="Save" textFill="#2d8d07">
<font>
<Font name="Impact" size="22.0" />
</font>
</Button>
<Button fx:id="btn_update" layoutX="10.0" layoutY="10.0" mnemonicParsing="false"
prefHeight="44.0" prefWidth="105.0" text="Update" textFill="#0a85d7">
<font>
<Font name="Impact" size="24.0" />
</font>
</Button>
<Button fx:id="btn_del" layoutX="10.0" layoutY="35.0" mnemonicParsing="false"
prefHeight="44.0" prefWidth="105.0" text="Delete" textFill="#c91c1c">
<font>
<Font name="Impact" size="23.0" />
</font>
</Button>
</children>
</VBox>
<Label layoutX="212.0" layoutY="6.0" prefHeight="34.0" prefWidth="307.0" text="
Customer Details" textFill="#2e66ae">
<font>
<Font name="Impact" size="30.0" />
</font>
</Label>
</children>
</AnchorPane>
This is CustController class:
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
public class CustController implements Initializable {
#FXML
private TableView<Customer> tbl_cust;
#FXML
private TableColumn<Customer, String> tcol_name;
#FXML
private TableColumn<Customer, Integer> tcol_phno;
#FXML
private TableColumn<Customer, String> tcol_add;
#FXML
private TextField txt_name;
#FXML
private TextField txt_phno;
#FXML
private TextField txt_add;
#FXML
private Button btn_save;
#FXML
private Button btn_update;
#FXML
private Button btn_del;
private String query, cname, cphno, cadd;
DataAccessObj dao;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
dao = new DataAccessObj();
btn_save.setOnAction(e->{
insertNewCustomer();
});
refreshTable();
}
private void initTable() {
tcol_name.setCellValueFactory(cell->cell.getValue().getpname());
tcol_phno.setCellValueFactory(cell->cell.getValue().getpphno().asObject());
tcol_add.setCellValueFactory(cell->cell.getValue().getpaddress());
}
private void refreshTable() {
initTable();
query = "select a.Name, a.Phno, a.Address from customer ordered by a.Name";
tbl_cust.setItems(dao.getCustomerData(query));
}
private void insertNewCustomer() {
cname = txt_name.getText();
cphno = txt_phno.getText();
cadd = txt_add.getText();
query = "insert into customer values('"+cname+"', '"+cphno+"', '"+cadd+"');";
dao.savedata(query);
txt_name.setText("");
txt_phno.setText("");
txt_add.setText("");
refreshTable();
}
}
This is DataAccessObject class:
package application;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.sql.ResultSet;
public class DataAccessObj {
private DBConnection database = new DBConnection();
private ResultSet rs;
private PreparedStatement ps;
private Connection connect;
public DataAccessObj() {
}
public void savedata(String query) {
try {
connect = database.getConnection();
ps = connect.prepareStatement(query);
ps.executeUpdate();
}catch(Exception e) {
e.printStackTrace();
}finally {
database.close(connect, ps, null);
}
}
public ObservableList<Customer> getCustomerData(String query){
ObservableList list = FXCollections.observableArrayList();
try {
connect = database.getConnection();
ps = connect.prepareStatement(query);
rs = ps.executeQuery();
while(rs.next()) {
list.add(new Customer(rs.getString(1), rs.getInt(2), rs.getString(3)));
}
}catch(Exception e) {
e.printStackTrace();
}
return list;
}
}
I am trying to get customer details from database. Database is connected to the javafx and it stores data from javafx but doesn't show data in javafx tableview.

Name [jdbc/mydb] is not bound in this Context. Unable to find [jdbc]

My OS is Windows 10.
I downloaded Tomcat 9.0 from https://tomcat.apache.org/download-90.cgi
I downloaded Eclipse from https://www.eclipse.org/downloads/packages/release/2018-12/r/eclipse-ide-enterprise-java-developers
I use MySQL 5.5 on an external server.
I downloaded Connector/J 8.0 from https://dev.mysql.com/downloads/connector/j/8.0.html
I successfully connected to the MySQL Database with the DriverManager class.
Now I want to use the Tomcat JNDI to establish the database connection but it does not work.
Tomcat is installed in C:\MyPrograms\Tomcat.
My Eclipse workspace is C:\Users\Felix\eclipse-workspace.
I copied the JDBC driver mysql-connector-java-8.0.13.jar to C:\MyPrograms\Tomcat\lib.
My C:\MyPrograms\Tomcat\conf\server.xml (without comments):
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="jdbc/mydb" global="jdbc/mydb" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" auth="Container" type="javax.sql.DataSource" username="felix1_0" password="mypassword" driverClassName="com.mysql.jdbc.Driver" description="mydb example" url="jdbc:mysql://192.168.88.88:3306/felix1_0" maxTotal="8" maxIdle="4" maxWaitMillis="10000" removeAbandonedTimeout="300" defaultAutoCommit="true"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="9999" protocol="HTTP/1.1"
URIEncoding="UTF-8"
maxThreads="200"
minSpareThreads="10"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
my C:\Users\Felix\eclipse-workspace\DynamicWebProjectTest\WebContent\WEB-INF\web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>DynamicWebProjectTest</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<resource-ref>
<description>This is a reference to the global Resource for MySQL database connetion.</description>
<res-ref-name>jdbc/mydb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
My C:\Users\Felix\eclipse-workspace\DynamicWebProjectTest\WebContent\META-INF\context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Context>
<ResourceLink name="jdbc/mydb" global="jdbc/mydb" type="javax.sql.DataSource"/>
</Context>
My Servlet:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.ResultSet;
#WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public MyServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h3>Hello Eclipse</h3><br><br>");
out.println("<p>A Random Number: <strong>" + Math.random() + "</strong></p>");
try {
establishJNDIDatabaseConnection(out);
} catch (NamingException e) {
out.println("<br>Error: NamingException: " + e.getMessage());
} catch (SQLException e) {
out.println("<br>Error: SQLException: " + e.getMessage());
}
out.println("</body></html>");
}
void establishJNDIDatabaseConnection(PrintWriter out) throws NamingException, SQLException {
/*
* Get initial context that has references to all configurations and
* resources defined for this web application.
*/
Context initialContext = new InitialContext();
out.println("<br>Context initialContext = new InitialContext();");
/*
* Get Context object for all environment naming (JNDI), such as
* Resources configured for this web application.
*/
Context environmentContext = (Context) initialContext.lookup("java:comp/env");
out.println("<br>Context environmentContext = (Context) initialContext.lookup(\"java:comp/env\");");
/*
* Get the DataSource for MySQL to request a connection
*/
DataSource dataSource = (DataSource) environmentContext.lookup("jdbc/mydb");
out.println("<br>DataSource dataSource = (DataSource) environmentContext.lookup(\"jdbc/mydb\");");
/*
* Request a Connection from the pool of connection threads
*/
Connection con = dataSource.getConnection();
out.println("<br>Connection con = dataSource.getConnection();");
/*
* Query the database
*/
StringBuilder msg = new StringBuilder();
try (Statement stm = con.createStatement()) {
ResultSet rs = stm.executeQuery("SHOW TABLES;");
while(rs.next()) {
msg.append(rs.getString("Tables_in_felix1_0"));
}
} catch(SQLException e) {
out.println("<br>Error: " + e.getMessage());
} finally {
if(con != null) {
con.close();
}
con = null; //prevent future access
}
out.println("<br>Returned from SQL: " + msg.toString());
}
}
The Error: "NamingException: Name [jdbc/mydb] is not bound in this Context. Unable to find [jdbc]." is thrown by this line of code:
DataSource dataSource = (DataSource) environmentContext.lookup("jdbc/mydb");
How can I fix this problem?
Default value of useSSL is true when using MySQL Connector/J 8.0.13.(https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html). Change the JDBC URL in the server.xml as jdbc:mysql://192.168.88.88:3306/felix1_0?useSSL=false and restart the tomcat.
You could also use lower version of mysql driver (e.g) mysql-connector-java-5.1.18-bin.jar with jdbc:mysql://192.168.88.88:3306/felix1_0 the JDBC URL.

Tabs don't display on Kindle Fire

I have an Android app that uses tabs for its start menu. The tabs don't display when I port the app to a Kindle Fire. Here's the code:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:isScrollContainer="true" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TabHost
android:id="#+id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TabWidget
android:id="#android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</TabWidget>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/Beginning"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
<LinearLayout
android:id="#+id/Intermediate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
<LinearLayout
android:id="#+id/Advanced"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
</ScrollView>
package com.myproject.project;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Environment;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
import android.widget.Toast;
public class TabsTestActivity extends Activity {
/** Called when the activity is first created. */
public static final String KEY_ROWID = "_id";
public static final String KEY_NAME = "name";
public static final String KEY_LEVEL = "level";
public static final String KEY_CHART = "charted";
public String extStorageDirectory = Environment
.getExternalStorageDirectory().toString();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
PopulateDatabase();
CopyVideoFiles();
TabHost tabhost = (TabHost) findViewById(R.id.tabhost);
tabhost.setup();
TabSpec spec_beg = tabhost.newTabSpec("Beginning");
spec_beg.setContent(R.id.Beginning);
TextView txtTabInfo = new TextView(this);
txtTabInfo.setText("JUST STARTING");
Typeface font = Typeface.createFromAsset(getAssets(), "danielbd.ttf");
txtTabInfo.setTypeface(font);
txtTabInfo.setGravity(Gravity.CENTER);
txtTabInfo.setHeight(50);
txtTabInfo.setBackgroundColor(Color.parseColor("#CCDE8A"));
txtTabInfo.setTextColor(Color.parseColor("#262405"));
spec_beg.setIndicator(txtTabInfo);
TabSpec spec_int = tabhost.newTabSpec("Intermediate");
spec_int.setContent(R.id.Intermediate);
txtTabInfo = new TextView(this);
txtTabInfo.setText("GETTING THERE");
txtTabInfo.setTypeface(font);
txtTabInfo.setGravity(Gravity.CENTER);
txtTabInfo.setHeight(50);
txtTabInfo.setBackgroundColor(Color.parseColor("#CCDE8A"));
txtTabInfo.setTextColor(Color.parseColor("#262405"));
spec_int.setIndicator(txtTabInfo);
TabSpec spec_adv = tabhost.newTabSpec("Advanced");
spec_adv.setContent(R.id.Advanced);
txtTabInfo = new TextView(this);
txtTabInfo.setText("REALLY GOOD");
txtTabInfo.setTypeface(font);
txtTabInfo.setGravity(Gravity.CENTER);
txtTabInfo.setHeight(50);
txtTabInfo.setBackgroundColor(Color.parseColor("#CCDE8A"));
txtTabInfo.setTextColor(Color.parseColor("#262405"));
spec_adv.setIndicator(txtTabInfo);
// get data from database, create buttons and name them
SQLData myTable = new SQLData(this);
myTable.open();
Cursor c = myTable.getallData();
int iRow = c.getColumnIndex(KEY_ROWID);
int iName = c.getColumnIndex(KEY_NAME);
int iLevel = c.getColumnIndex(KEY_LEVEL);
// create the buttons
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
final String RowNum = c.getString(iRow);
String Name = c.getString(iName);
final String Level = c.getString(iLevel);
Button button = new Button(this);
button.setText(Name);
button.setHeight(20);
button.setTextColor(Color.BLACK);
button.setBackgroundColor(Color.parseColor("#A89E0A"));
button.setHighlightColor(Color.WHITE);
button.setTypeface(font);
button.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent choice = new Intent(getApplicationContext
(),
com.myproject.project.myclass.class);
Bundle dataBundle = new Bundle();
dataBundle.putString("RowID", RowNum);
dataBundle.putString("Level", Level);
choice.putExtras(dataBundle);
try {
startActivity(choice);
} catch (Exception e) {
Dialog d = new Dialog(getApplicationContext());
d.setTitle("TabsTestActivity line 131");
TextView tv = new TextView(getApplicationContext());
tv.setText(e.toString());
d.setContentView(tv);
d.show();
} finally {
}
}
});
LinearLayout lbeg = (LinearLayout) findViewById(R.id.Beginning);
LinearLayout lint = (LinearLayout) findViewById(R.id.Intermediate);
LinearLayout ladv = (LinearLayout) findViewById(R.id.Advanced);
if (Level.equals("Beginning"))
lbeg.addView(button);
else if (Level.equals("Intermediate"))
lint.addView(button);
else if (Level.equals("Advanced"))
ladv.addView(button);
}
tabhost.addTab(spec_beg);
tabhost.addTab(spec_int);
tabhost.addTab(spec_adv);
myTable.close();
}}
Does anyone know why? The tabs and their contents show up fine in the emulator and on my Android phone. Thanks!
I have since learned that the Kindle Fire does not support Tabs

Dynamically updating a ListView from JSON object using a custom ListViewAdapter

As usual the question comes from a first time user of Android. Its three weeks later and im tearing my hair out will do my best to explain the problem.
Firstly I am using Exlipse 3.7.1 and SDK r15 as of today because I thought Ill try upgrade maybe thats whats causing the issues but seems to be the same while using r13.
Here is a working copy of my code:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_horizontal"
android:id="#+id/llMain"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:background="#drawable/header"
android:id="#+id/linearLayout1"
android:layout_height="50dp"
android:layout_width="fill_parent">
<ImageButton
android:background="#null"
android:id="#+id/ibHome"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight=".25"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:src="#drawable/trophy_cup" />
<ImageView
android:background="#000000"
android:id="#+id/imageView1"
android:layout_height="match_parent"
android:layout_width="1dp" />
<TextView
android:gravity="center_horizontal"
android:id="#+id/lblHome"
android:layout_height="50dp"
android:layout_width="0dp"
android:layout_weight="1"
android:paddingTop="14dp"
android:text="#string/helloHome"
android:textColor="#color/txtYellow"
android:textSize="18dp"
android:textStyle="bold"
android:typeface="serif" />
<ImageView
android:id="#+id/imageView2"
android:layout_height="match_parent" android:background="#000000"
android:layout_width="1dp" />
<ImageButton
android:background="#null"
android:focusable="true"
android:id="#+id/ibQuit"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight=".25"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:src="#drawable/yellow_flag" />
</LinearLayout>
<!-- Body code goes here -->
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_weight="1"
android:gravity="center_horizontal" android:paddingTop="10dp">
<TextView
android:id="#+id/lblHeading"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_weight="0.17"
android:gravity="center_horizontal"
android:isScrollContainer="true"
android:text="Top"
android:textColor="#color/txtYellow"
android:textSize="22dp"
android:textStyle="bold" android:paddingTop="7dp" android:typeface="serif"/>
<Spinner
android:entries="#array/strArrTop"
android:id="#+id/spinTop"
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_weight="0.44"
android:focusableInTouchMode="true"
android:longClickable="true"/>
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:padding="25dp"
android:orientation="vertical" >
<ListView
android:id="#+id/list1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:isScrollContainer="true" />
</LinearLayout>
<!-- End Body code goes here -->
<LinearLayout
android:id="#+id/linearLayout4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal" >
<TextView
android:id="#+id/lblWidth"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
<ImageView
android:layout_height="120dp"
android:layout_width="201dp"
android:scaleType="fitXY"
android:src="#drawable/ddo_logo" />
<TextView
android:id="#+id/lblHeight"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</LinearLayout>
</LinearLayout>
mylist.xml (the custom list adapter)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content" android:gravity="left|center">
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<TextView
android:id="#+id/txt1"
android:layout_width="182dp"
android:layout_height="wrap_content"
android:layout_weight="0.21"
android:textColor="#color/txtYellow" />
<TextView
android:id="#+id/txt2"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:textColor="#color/txtYellow" />
</LinearLayout>
</LinearLayout>
The manifest file, uses minSDK 8.0
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hunta.DDOFastestTimes"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET"/>
<supports-screens
android:normalScreens="true"
android:largeScreens="true" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:label="#string/app_name"
android:name=".DDOFastestTimesActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
and finally the offending java file:
package com.hunta.DDOFastestTimes;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.net.ParseException;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class DDOFastestTimesActivity extends Activity implements OnClickListener {
/** JSON variables */
String jc1, jc2 = null;
/** END JSON variables */
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/** JSON variables */
String result = null;
InputStream is = null;
StringBuilder sb = null;
/** END JSON variables */
ImageButton closeApp = (ImageButton) findViewById(R.id.ibQuit);
closeApp.setOnClickListener(this);
/** http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */
/** Populating the spinner from that string-array */
Spinner s = (Spinner) findViewById( R.id.spinTop );
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( this, R.array.strArrTop, android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
/** END Populating the spinner from that string-array */
/** Create a reference to our spinner */
s.setAdapter( adapter );
/** END Create a reference to our spinner */
/** END http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */
s.setOnItemSelectedListener(new MyOnItemSelectedListener());
/** JSON code to initiate the php */
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://url-to-my-php-file/fastag.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection"+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
//paring data
JSONArray jArray;
try{
jArray = new JSONArray(result);
JSONObject json_data=null;
// Adding the JSON data to the list view
int length = jArray.length();
List<String> listContents1 = new ArrayList<String>(length);
List<String> listContents2 = new ArrayList<String>(length);
// Convert ListString Array to an ArrayList
ArrayList<tblRecord> arrTxt = new ArrayList<tblRecord>();
// Changing the ListViews
for(int i=0;i<jArray.length();i++){
json_data = jArray.getJSONObject(i);
jc1 = json_data.getString("c1");
jc2 = json_data.getString("c2");
listContents1.add(json_data.getString("c1"));
listContents2.add(json_data.getString("c2"));
// Create an Array to pass to our custom view
tblRecord addRecord = new tblRecord(jc1, jc2);
arrTxt.add(addRecord);
}
ListView myListView1 = (ListView) findViewById(R.id.list1);
myListView1.setAdapter(new UserItemAdapter(this, android.R.layout.simple_list_item_1, arrTxt));
// END Adding the JSON data to the list view
}
catch(JSONException e1){
Toast.makeText(getBaseContext(), "No Results Found" ,Toast.LENGTH_LONG).show();
} catch (ParseException e1) {
e1.printStackTrace();
}
/** END JSON code to initiate the php */
}
/** End Called when the activity is first created. */
/** Using a custom List View */
public class UserItemAdapter extends ArrayAdapter<tblRecord> {
private ArrayList<tblRecord> arrList;
public UserItemAdapter(Context context, int textViewResourceId, ArrayList<tblRecord> arrList) {
super(context, textViewResourceId, arrList);
this.arrList = arrList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.mylist, null);
}
tblRecord user = arrList.get(position);
if (user != null) {
TextView c1 = (TextView) v.findViewById(R.id.txt1);
TextView c2 = (TextView) v.findViewById(R.id.txt2);
if (c1 != null) {
c1.setText(user.c1);
}
if(c2 != null) {
c2.setText(user.c2);
}
}
return v;
}
}
public class tblRecord {
public String c1;
public String c2;
public tblRecord(String c1, String c2) {
this.c1 = c1;
this.c2 = c2;
}
}
/** END Using a custom List View */
/** Listener for the spinner, we will handle changes made to the spinner here */
public class MyOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View v, int position, long id) {
Toast.makeText(parent.getContext(), "The top " +
parent.getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
}
/** END Listener for the spinner, we will handle changes made to the spinner here */
#Override
public void onClick(View v) {
int id = v.getId();
// Intent myIntent;
switch (id) {
case R.id.ibQuit:
finish();
break;
}
}
}
Up until this point everything is working, if not 100% at least it works but now I need to try dynamically change the contents of the list view when the user changes the spinner.
The emulator uses -dns-server xxx.xxx.xxx.xxx in its run configuration
I am running 3.7in WVGA
Now after an 8 hour attempt to find a way to do this, this is as far as I have gotten but it just crashes:
package com.hunta.DDOFastestTimes;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.net.ParseException;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class DDOFastestTimesActivity extends ListActivity implements OnClickListener {
private UserItemAdapter myAdapter;
private ArrayList<tblRecord> arrTxt = null;
private Runnable viewJSON;
/** JSON variables */
String jc1, jc2, result = null;
InputStream is = null;
StringBuilder sb = null;
/** END JSON variables */
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageButton closeApp = (ImageButton) findViewById(R.id.ibQuit);
closeApp.setOnClickListener(this);
/** http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */
/** Populating the spinner from that string-array */
Spinner s = (Spinner) findViewById( R.id.spinTop );
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( this, R.array.strArrTop, android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
/** END Populating the spinner from that string-array */
/** Create a reference to our spinner */
s.setAdapter( adapter );
/** END Create a reference to our spinner */
/** END http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */
s.setOnItemSelectedListener(new MyOnItemSelectedListener());
arrTxt = new ArrayList<tblRecord>();
this.myAdapter = new UserItemAdapter(this, R.layout.mylist, arrTxt);
setListAdapter(this.myAdapter);
viewJSON = new Runnable(){
#Override
public void run() {
arrTxt = MyJSONFetch(0);
}
};
Thread thread = new Thread(null, viewJSON, "MagentoBackground");
thread.start();
ListView myListView1 = (ListView) findViewById(R.id.list1);
myListView1.setAdapter(new UserItemAdapter(this, android.R.layout.simple_list_item_1, arrTxt));
}
/** End Called when the activity is first created. */
private Runnable returnRes = new Runnable() {
#Override
public void run() {
if(arrTxt != null && arrTxt.size() > 0){
myAdapter.notifyDataSetChanged();
for(int i=0;i<arrTxt.size();i++)
myAdapter.add(arrTxt.get(i));
}
myAdapter.notifyDataSetChanged();
}
};
/** Using a custom List View */
public class UserItemAdapter extends ArrayAdapter<tblRecord> {
private ArrayList<tblRecord> arrTxt;
public UserItemAdapter(Context context, int textViewResourceId, ArrayList<tblRecord> arrTxt) {
super(context, textViewResourceId, arrTxt);
this.arrTxt = arrTxt;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.mylist, null);
}
tblRecord user = arrTxt.get(position);
if (user != null) {
TextView c1 = (TextView) v.findViewById(R.id.txt1);
TextView c2 = (TextView) v.findViewById(R.id.txt2);
if (c1 != null) {
c1.setText(user.c1);
}
if(c2 != null) {
c2.setText(user.c2);
}
}
return v;
}
}
public class tblRecord {
public String c1;
public String c2;
public tblRecord(String c1, String c2) {
this.c1 = c1;
this.c2 = c2;
}
}
/** END Using a custom List View */
/** Reload JSON Database from onclick listener */
public ArrayList<tblRecord> MyJSONFetch(int position)
{
ArrayList<tblRecord> arrTxt = new ArrayList<tblRecord>();
String tmpUrl = null;
/** JSON code to initiate the php */
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
switch (position)
{
case 0:
tmpUrl = "http://smutlow.comp-degree.uhi.ac.uk/UG409713/DDOFastestTimes/fastag.php";
break;
case 1:
tmpUrl = "http://smutlow.comp-degree.uhi.ac.uk/UG409713/DDOFastestTimes/fastas.php";
break;
}
HttpPost httppost = new HttpPost(tmpUrl);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection"+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
//paring data
JSONArray jArray;
try{
jArray = new JSONArray(result);
JSONObject json_data=null;
// Adding the JSON data to the list view
int length = jArray.length();
List<String> listContents1 = new ArrayList<String>(length);
List<String> listContents2 = new ArrayList<String>(length);
// Changing the ListViews
for(int i=0;i<jArray.length();i++){
json_data = jArray.getJSONObject(i);
jc1 = json_data.getString("c1");
jc2 = json_data.getString("c2");
listContents1.add(json_data.getString("c1"));
listContents2.add(json_data.getString("c2"));
// Create an Array to pass to our custom view
tblRecord addRecord = new tblRecord(jc1, jc2);
arrTxt.add(addRecord);
}
// END Adding the JSON data to the list view
}
catch(JSONException e1){
Toast.makeText(getBaseContext(), "No Results Found" ,Toast.LENGTH_LONG).show();
} catch (ParseException e1) {
e1.printStackTrace();
}
/** END Reload JSON Database from onclick listener */
runOnUiThread(returnRes);
return arrTxt;
}
/** Listener for the spinner, we will handle changes made to the spinner here */
public class MyOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View v, int position, long id) {
MyJSONFetch(position);
Toast.makeText(parent.getContext(), "The top " + parent.getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
MyJSONFetch(position);
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
}
/** END Listener for the spinner, we will handle changes made to the spinner here */
#Override
public void onClick(View v) {
int id = v.getId();
// Intent myIntent;
switch (id) {
case R.id.ibQuit:
finish();
break;
}
}
}
Basically Ive tried to seperate the JSON code from the onCreate and put it into its own public method so I can call it from the MyOnItemSelectedListener but I am out of ideas and have demonstrated my total lack of understanding of java.
Please if you respond try be a simplistic as possible with your answer.
Thank you in advance.
p.s. apologies if the layout isn't what it should be this is my first post
So I have found a solution to this perhaps someone might offer a better one but here is what I did:
Rather than try to fire the PHP I needed from the spinner I opted to use the spinner to load a new Intent with the relevant URL to the PHP I wanted to use added to a Bundle.
if (position == 0) {
Bundle myBundle = new Bundle();
Intent myIntent;
myBundle.putString("myPHP", "http://url-to-my-php-file/fastag.php");
myIntent = new Intent(getBaseContext(), DDOFastestGuilds.class);
myIntent.putExtras(myBundle);
startActivity(myIntent);
onLowMemory();
finish();
}
I then added two new .java files practically identical to the first one, adding two lines at the start:
Bundle myBundle = getIntent().getExtras();
String tmpPHP = myBundle.getString("myPHP");
I amended the line that calls the HttpPost to point to the variable I just created tmpPHP rather than the literal URL I had used in the original file:
HttpPost httppost = new HttpPost(tmpPHP);
And lastly changing the spinners selection to reflect that last selected by the user, if there were more than two options in the spinner I would have used the bundle to pass the last selected index but in my example I only had two options so I knew the selected index was either 0 or 1 depending on the Intent i wanted to open. (Making sure its directly after the setAdapter method):
s.setSelection(1);
Hoping for an alternative method going forward.
If anyone can suggest a way to only have to use one Activity to get the same result I would be grateful.