Android populate listview with cursor - java

My app uses a simple SQLite database. Everything works fine I can now present a Toast with a chosen row from the return query using:
{
//etc etc etc...
c.movetofirst();
DisplayTitle(c);
}
public void DisplayTitle(Cursor c)
{
Toast.makeText(main.this,
"id: " + c.getString(0) + "\n" +
"reg: " + c.getString(1) + "\n" +
"type: " + c.getString(2) + "\n",
Toast.LENGTH_LONG).show();
}
I want to prsent all the data in the cursor to the screen using a view but I am not sure how to go about this. Which view should I use? I just wnt a simple looking grid representation which allows me to scroll through each row in the cursor
Thanks in advance.

How can I show ALL rows in the Cursor?
There are several ways if you are working with a Cursor, for example see the "moveTo" related methods, here's an example:
Set<Item> items = new HashSet<Item>(c.getCount());
if (c.moveToFirst()) {
do {
Item i = new Item(select(c.getString(0), c.getString(1), c.getString(2));
set.add(i);
} while (c.moveToNext());
}
if (!c.isClosed()) {
c.close();
}
This assumes Item is a data class that has a constructor with three String parameters. Going with your code, id, reg, and type. Usually column 0 will be a numeric ID (not getString, but SQLite uses "manifest typing" so it will sort of dyna-type a String/Long from column 0 -- you may want to AUTOINCREMENT and use getLong there though).
One you have a collection of items, you can do anything you want with them to display them. If you want a scrolling/selectable list, then ListView is an excellent choice. And, you can back it with a CursorAdapter.
Here's an example of a ListView that is populated by a CursorAdapter from an open source project: http://code.google.com/p/and-bookworm/source/browse/trunk/src/com/totsp/bookworm/Main.java (see the inner BookCursorAdapter class, it should get you pointed in the right direction).

Related

Main Menu Buttons change colour but dont understand how

I have a main menu with buttons (days of the week). If data is stored in the database in reference to these days of the week then they will turn 'green'. I understand the SQL query itself but don't understand how colourChange function identifies each button and 'knows' how to change it. Can someone maybe explain how this works?
MainMenu.java
private void colourChange() {
Cursor result = myDb.checkColour();
if (result.getCount() == 0) { // If the result equals to 0 then do nothing.
// Default colour remains
} else {
// if the result is not 0 then...
while (result.moveToNext()) { // Move through each result...
String day = result.getString(0); // and store the day (column 0) of the result in day
findViewById(getResources().getIdentifier(day + "button", "id", getPackageName())) // Find the view by ID using getResources.getIdentifier and passing the following parameter (day)
.setBackgroundColor(getResources().getColor(R.color.colorSuccess)); // The variable colourSuccess stored in the colours.xml file sets the background colour green.
}
}
}
Database.java
public Cursor checkColour() { // a SELECT statement is used to SELECT DayOfWeek FROM RoutineTable and GROUP BY DayOfWeek and store this as result.
SQLiteDatabase db = this.getWritableDatabase();
Cursor result = db.rawQuery("SELECT DayOfWeek FROM " + RoutineTable + " GROUP BY DayOfWeek", null);
return result;
}
Let's break the code down.
getResources().getIdentifier(day + "button", "id", getPackageName())
The Resources.getIdentifier() method allows you to access the various constants inside R.java dynamically, by name. day + "button" is the name of the resource and "id" is the type of the resource. So this method will return R.id.[day]button. If day holds "sunday", then you're going to get R.id.sundaybutton.
findViewById( [code from above] )
Now that getIdentifier() has returned a "real" id to you (like R.id.sundaybutton), findViewById() will search your layout for a View object with that android:id attribute. So if your layout includes a View with android:id="#+id/sundaybutton", findViewById(R.id.sundaybutton) will return it.
getResources().getColor(R.color.colorSuccess)
Resources.getColor() takes a color identifier (here R.id.colorSuccess) and returns the color value (perhaps it is green, maybe 0xFF00FF00).
setBackgroundColor( [color from above] )
This one is easy: it sets the background color of the specified View.
Altogether, you're going to iterate over the days of the week and
build an identifier from the day of the week
find a view using that identifier
get a color value from your resources
apply that color value to the found view's background
Hope this helps!
Good afternoon,
Without seeing all of the code for the resource file information for the application it will be hard to give you a definite answer. Looking at the code it looks like it matches a resource with the day of the week returned in the query plus the word "button" in the current application. Then it sets the background color by looking in the color resource folder for a resource called "colorSuccess", which changes it to the color green.
That colourChange() function firstly requesting to database return as cursor.
while (result.moveToNext()) is looping while all rows of result.
getResources().getIdentifier(day + "button", "id", getPackageName())
That find resources by specified layout id.Example "#+id/fridaybutton"
Accoriding android api documents. function paramters is here.
getIdentifier(String name, String defType, String defPackage)

Generating random output from SQLite Database

Hi I currently have a database that has 5 questions and answers stored in it. I want to randomly output three of the questions each time the app runs. I have the below code but my app crashes when it loads
public List<Question> getAllQuestions() {
List<Question> quesList = new ArrayList<Question>();
int nQuestions = 3; //select COUNT(*) from questions
Random random = new Random();
int id = random.nextInt(nQuestions);
String selectQuery = "SELECT id FROM " + TABLE_QUEST;
dbase=this.getReadableDatabase();
Cursor cursor = dbase.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Question quest = new Question();
quest.setID(cursor.getInt(0));
quest.setQUESTION(cursor.getString(1));
quest.setANSWER(cursor.getString(2));
quest.setOPTA(cursor.getString(3));
quest.setOPTB(cursor.getString(4));
quest.setOPTC(cursor.getString(5));
quesList.add(quest);
} while (cursor.moveToNext());{
id = random.nextInt(nQuestions);
}
}
// return quest list
return quesList;
}
Sorry that I write this as an answer, but I don't have permissions to write comments to a question, so I want to tell you that first of all you will always become one of the first 3 added questions as a random question, because for the random id you use as limitations 3 id = random.nextInt(nQuestions); instead of nQuestions (which is 3 for you, you should use questList.size() and do it 3 times for the numbers from 0 to questList.size()
The issue is, you are only selected the id from the table, for all entries.
Your random will also select only questions 0, 1 or 2. Your random should be random.nextInt(5) since you have 5 questions.
Finally, this should be in a loop and then add multiple wheres to your query to get multiple questions.
String query = "SELECT * FROM " + TABLE_QUEST + " WHERE ";
for (int x = 0; x < nQuestions; x++) {
if (x > 0) {
query += " OR ";
}
query += "id=" + random.nextInt(5);
}
This will make your query look like this:
SELECT * FROM TABLE_QUEST WHERE id=4 OR id=2 OR id=3
Finally, change the way your cursor.moveToNext() is. Your code should look something like this:
public List<Question> getAllQuestions() {
List<Question> quesList = new ArrayList<Question>();
int nQuestions = 3; //select COUNT(*) from questions
Random random = new Random();
String query = "SELECT * FROM " + TABLE_QUEST + " WHERE ";
for (int x = 0; x < nQuestions; x++) {
if (x > 0) {
query += " OR ";
}
query += "id=" + random.nextInt(5);
}
dbase=this.getReadableDatabase();
Cursor cursor = dbase.rawQuery(query, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Question quest = new Question();
quest.setID(cursor.getInt(0));
quest.setQUESTION(cursor.getString(1));
quest.setANSWER(cursor.getString(2));
quest.setOPTA(cursor.getString(3));
quest.setOPTB(cursor.getString(4));
quest.setOPTC(cursor.getString(5));
quesList.add(quest);
} while (cursor.moveToNext());
}
// return quest list
return quesList;
}
There are a couple of mistakes in your code.
First, your SQL query is wrong:
String selectQuery = "SELECT id FROM " + TABLE_QUEST;
gives you all the values of the "id" column in the table TABLE_QUEST, not the column with the id you determined with your call to Random.nextInt.
String selectQuery = "SELECT * FROM " + TABLE_QUEST + " WHERE id=" + id;
The "*" stands for "all columns in this table" and the "WHERE" enables you to filter your rows according to the conditions that follow (i.e. id=3).
Note while it's not a problem in this case, passing unescaped values (i.e., the WHERE id=" + id part is very bad form because it might make you vulnerable to SQL injections as soon as you use user input for this).
Second: the rest of the code doesn't make much sense for various reasons. I'll try to list a few:
if your code would work (i.e. with * instead of id in the SELECT, but without the WHERE clause), you'd just add all of the questions in your database to the list, because there's no condition.
if the condition would work, you'd get just one row with a certain id. your do-while loop would run only once.
if you had a loop around the select, then it might work, but it'd probably return the same rows TWICE or even more often.
you'd still get occasional crashes for various reasons, among them
primary keys - the id attribute which is probably auto-increment - is not necessarily in the range 0..n-1. it might be in your case, but that's not exactly typical. auto-incrementing primary keys usually start at 1.
if your question-answers records are CRUD (create, read, update, delete), the ids might have holes, i.e. "1, 2, 6, 8, 12".
i'd rewrite the whole method; there are a couple of ways of doing it. just a few hints:
if there are very few records in the table (e.g. less than a couple hundreds) you can just load all the questions into list A.
create list A
add all records from the database to list A
create a list B
as long as there are fewer elements in list B than you want (i.e. listB.size() < 3) remove a random element from List A and add it to List B.
return listB. // this seems wasteful, but would probably be ok in your case.
let the database do the randomizing:
SELECT * FROM table ORDER BY RANDOM() LIMIT 3;
read all the records into a list
return the list
done! (note: this works with sqlite, but is, as far as i know, not universally accepted by different database systems).
there are countless other ways of achieving your goal. but i'd just use the ORDER BY RANDOM() LIMIT x trick, it's probably the easiest way.

how to insert database from jtable?

i have jtable with 2 column then i want to insert value of it to database;
i know it can be done with something like ..
int count=table.getRowCount();
for(int i=0;i<count;i++){
Object obj1 = table.getValueAt(i, 0);
Object obj2 = table.getValueAt(i, 1);
the problem is..
getRowCount doesn't know if the row is empty,
then in database, that empty value will still inserted
(and it will generate my auto increment value in database)
my question
how to insert database from jtable, but the empty row will not inserted?
thanks a lot for any kind of help,,
if i asking too much please just give me a clue to handle the empty row ,
forgive my english
here's the broken method to add data to database
public void addToDatabase(){
for (int i=0;i<table.getRowCount();i++){
//#####################################
//maybe need something in here
if(table.getValueAt(i, 0)==null||table.getValueAt(i, 1) ==null){
return;
//and maybe need something not return, but to get the next row (Just.. maybe ...)
//#####################################
}else{
try{
Connection c = getCon("databasez");
PreparedStatement p = c.prepareStatement("INSERT INTO table_data VALUES (?,?)");
p.setString(1, table.getValueAt(i, 0).toString());
p.setFloat (Float.parseFloat(table.getValueAt(i, 1).toString()));
p.executeUpdate();
p.close();
}catch(Exception e){
JOptionPane.showMessageDialog(this, "THERE WAS AN INVALID DATA");
}
}
}
}
Assuming that you're using DefaultTableModel, the result returned by getValueAt() will be null until you edit the corresponding cell.
You can also register a TableModelListener to receive a TableModelEvent that can tell your listener what has changed.
private JTable table = new JTable(1, 2);
...
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
System.out.println(""
+ e.getType() + " "
+ e.getFirstRow() + " "
+ e.getLastRow() + " "
+ e.getColumn());
}
});
maybe it will help you.
http://www.exampledepot.com/egs/javax.swing.table/InsertRow.html
first, I just saw getData methods here and I didn't see insert or some alike method you invoked, so I think the code doesn't relate to what you said.
second, also you can learn to search the api about jtable.
if you full know the methods of a class and how to use it in the general ways, I think you understand and use it very well.
and this can also improve your understanding to understand something similar.
and you will become stronger and stronger to learn other difficult things without asking questions.
That's my oppion to learn program.
JAVA swing,SIMPLE WAY TO store jTable DATA in database
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) // swing Button
{
String name[] =new String[4]; // name is array and index 4 means no. of row
String age[]=new String[4]; //age is array and index 4 means no. of row
//loop from 0 row to 4
for(int i=0;i<4;i++)
{
name[i]=table.getValueAt(i,0).toString(); // it get value from 0 row and 0 column
age[i]=table.getValueAt(i,1).toString(); // it get value from 0 row and 1 column
//similarly for more column
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/crm","root","");
Statement s1=con.createStatement();
int mc=s1.executeUpdate("insert into testtable(Name,Age) values('"+name[i]+"','"+age[i]+"')");
}
catch(Exception ex)
{
javax.swing.JOptionPane.showMessageDialog(null,ex.getMessage().toString());
}
}

Get the MYSQL Table Name from ResultSet

I have a SELECT query which combining three tables. I want to add them to a Jtable by separating the MYSQL tables. I just want to know how can I identify the table name in a Resultset?
resultLoad("SELECT sqNum,RegDate,JobNo,DecName,NoOfLines,EntryType,EntrySubType,EntrySubType2,Amount,Status FROM paysheet WHERE TypeBy='" + cmbStaff.getSelectedItem().toString() + "' AND CommissionStatus='no' UNION SELECT sqNum,RegDate,JobNo,DecName,NoOfLines,EntryType,EntrySubType,EntrySubType2,Amount,Status FROM creditsheet WHERE TypeBy='" + cmbStaff.getSelectedItem().toString() + "' AND CommissionStatus='no' ORDER BY RegDate UNION SELECT sqNumber,date,JobNumber,DecName,noOfLines,type,type,type,CommissionAmount,status FROM newjobsheet WHERE TypeBy='" + cmbStaff.getSelectedItem().toString() + "' AND CommissionStatus='no' ORDER BY RegDate");
private void resultLoad(String loadQuery) {
try {
Connection c = DB.myConnection();
Statement s = c.createStatement();
ResultSet r = s.executeQuery(loadQuery);
while (r.next()) {
Vector v = new Vector();
v.addElement(r.getString("sqNum"));
v.addElement(r.getString("RegDate"));
v.addElement(r.getString("JobNo"));
v.addElement(r.getString("DecName"));
v.addElement(r.getString("NoOfLines"));
v.addElement(r.getString("EntryType") + " - " + r.getString("EntrySubType") + " - " + r.getString("EntrySubType2"));
v.addElement(r.getString("Amount"));
v.addElement(r.getString("Status"));
tm.addRow(v);
totalComAmount = totalComAmount + Integer.parseInt(r.getString("Amount"));
}
} catch (Exception e) {
// e.printStackTrace();
JOptionPane.showMessageDialog(this, e, "Error!", JOptionPane.ERROR_MESSAGE);
}
}
I want to add to the Jtable like this by sorting the dates. But the three tables containing different columns.
From your result set, you can get ResultSetMetaData. It looks like this:
rs.getMetaData().getTableName(int Column);
"I want to add them to a table by separating the tables."
Not sure what you mean by that, but:
"I just want to know how can I identify the table name in a Resultset?"
the answer is no, not unless you rewrite the query so that it does it for you.
A SELECT statement yields a new (virtual) table - any columns it delivers are technically columns of that new virtual table. The result does not remember the origin of those columns
However, you can write the query so as to give every expression in the SELECT list a column alias that allows you to identify the origin. For instance, you could do:
SELECT table1.column1 AS table1_column1
, table1.column2 AS table1_column2
, ...
, table2.column1 AS table2_column1
, ...
FROM table1 INNER JOIN table2 ON ... etc
If the underscore is not suitable as a separator for your purpose, then you could consider to quote the aliases and pick whatever character as separator you like, including a dot:
SELECT table1.column1 AS `table1.column1`
, ....
etc.
UPDATE:
I just noticed your query is a UNION over several tables. Obviously this method won't work in that case. I think your best bet is still to rewrite the query so that it reads:
SELECT 'paysheet' as table_name, ...other columns...
FROM paysheet
UNION
SELECT 'creditsheet', ...other columns...
...
It seems to me like you want to SELECT data from three separate tables and have it returned in one query as one ResultSet, then you want to separate the results back out into individual tables.
This is completely counter intuitive.
If you want to have your results separated so that you are able to look at each table's results separately, your best bet is to perform 3 different SELECT queries. Basically, what you are asking it to combine 3 things and then separate them again in one pass. Don't do this; if you leave them uncombined in the first place, separating them back out won't be an issue for you.

I store the score by hole of a round of golf in a database. I want to write a function that sums that column in the table and displays in a toast

This is the function that I have created. The Playgolf table has columns id, holepar, strokes, putts. I'm looking to sum up the strokes.
I have edited the code to this and now I'm getting this error...any ideas?
public void DisplaySum(int sum)
{
//Setup a local variable to store sum
int intRoundsSUM = 0;
db.open();
//Setup your database cursor
Cursor c = db.getPLAYGOLF();
Toast.makeText(getBaseContext(), intRoundsSUM, Toast.LENGTH_LONG).show();
//Iterate through the cursor
//Sum up each value
c.moveToFirst();
while(c.isAfterLast() == false) {
intRoundsSUM += c.getInt(2);
c.moveToNext();
}
Toast.makeText(getBaseContext(), intRoundsSUM, Toast.LENGTH_LONG).show();
}
// LOG CAT MAIN ERROR:
//E/AndroidRuntime(597): android.content.res.Resources$NotFoundException: String resource ID #0xa
You have to manage your cursor, start with
cursor.moveToFirst();
while(cursor.isAfterLast() == false) {
intRoundsSUM += c.getInt(2);
cursor.moveToNext();
}
Also read about letting your activity control the life cycle of the cursor with activity.startManagingCursor(cursor);
You can iterate over the cursor rows with the next cycle:
while (cursor.moveToNext()) {
intRoundsSUM += c.getInt(2);
}
But you can also try to make 'sum' selection from the database. Something like this:
SELECT SUM(strokes_column) FROM golf_table
It will return table with one column and one row that stores the necessary sum.
Try c.moveToFirst() before intRoundsSUM += c.getInt(2); to fix the error.
To sum them all you can use while (c.moveToNext()) or make a sum in your sql query (which would be better). See http://www.w3schools.com/sql/sql_func_sum.asp
There might be two reasons:
Playgolf table is empty. check the size by using c.getCount();
You are at the end of the cursor. use c.moveToFirst() to go to the beginning of the cursor.

Categories