I was trying to implement a TableView where between the rows of my source I would like to insert a GADBannerView (sponsored ads by Google AdMob). I currently have a datasource which every time I come to the end add 10 elements like an infinite scroll.
My intention would be to insert an element GADBannerView every 6 rows. How could I do?
UPDATE
As suggested
public override int RowsInSection (UITableView tableview, int section)
{
return (int)Math.Floor (Convert.ToDouble(ViewModel.ListElements.Count / 6) )+ ViewModel.ListElements.Count;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
if(indexPath.Row % 6 == 0 && indexPath.Row > 0){
var cell = tableView.DequeueReusableCell (BannerGATableCell.Key) as BannerGATableCell ?? BannerGATableCell.Create ();
_bannerView.LoadRequest (GADRequest.Request);
cell.AddSubview(_bannerView);
return cell;
}
if (indexPath.Row >= 6) {
return base.GetCell (tableView, NSIndexPath.FromRowSection((int)(indexPath.Row - (int)(indexPath.Row / 6)),0));
}
return base.GetCell (tableView, indexPath);
}
First you need to know how many banners will fit into your source.
Say you have 14 rows in total in your source.
Every 6th row is supposed to be a banner.
number of banners == (int)Math.Floor(14f / 6) == 2
So we have one banner at row 6 (index 5) and one at 12 (index 11).
In your RowsInSection() method add 2 to the number of rows you have (for the banners).
Then in GetCell() check if it is time to inject a banner:
if(indexPath.Row % 6 == 0 && indexPath.Row > 0)
{
var bannerCell = tableView.DequeueReusableCell(SOME_SPECIAL_CELL_ID) as BannerCell;
if(bannerCell == null)
{
...
}
bannerCell.SetBannerView(SomeHelper.GetBannerView());
return bannerCell;
}
BannerCell would be a subclass of UITableViewCell you have to create that allows setting the banner. You can also use a normal cell and add the banner view to the ContentView of the cell. But don't forget to remove the subview first.
Related
I'm trying to make a PShape SVG multipy. I want a new shape created every time a variable (that I'm importing from a CSV file) changes. I tried using a for, but it doesn`t respect the variable range I'm giving it, it just creates as many SVGs as it wants. Basically what I'm trying to do is that if the variable indicates there are 21 data between an X rage, draw 21 copies of the SVG in a fixed distance between one and other.
Table table;
PShape tipi2;
PShape tipi3;
void setup() {
size (1875, 871);
table = loadTable("WHO.csv", "header");
tipi2 = loadShape("tipi-02.svg");
}
void draw() {
background(0);
for (TableRow row : table.rows()) {
int hale = row.getInt("Healthy life expectancy (HALE) at birth (years) both sexes");
}
tipi2.disableStyle();
noStroke();
for( int i = 0 ;i<=1800;i=i+33){
pushMatrix();
translate(0,89.5);
if(hale > 40 && hale < 60){
shape(tipi2,i,0);
popMatrix();
}
}
There are a couple of things that couple things that could be improved in your current code:
the hale variable's visibility (or scope) is only within this loop: for (TableRow row : table.rows()) {
the drawing styles (noStroke()/disableStyle(),etc.) don't change much therefore could e set once in setup() rather than multiple times a second in draw()
you could move the for loop from 0 to 1800 inside the for (TableRow row : table.rows()) { loop, but that might not be very efficient:
Here's what I mean:
Table table;
PShape tipi2;
PShape tipi3;
void setup() {
size (1875, 871);
table = loadTable("WHO.csv", "header");
tipi2 = loadShape("tipi-02.svg");
//this styles could be set once in setup, rather than multiple times in draw();
tipi2.disableStyle();
noStroke();
background(0);
for (TableRow row : table.rows()) {
int hale = row.getInt("Healthy life expectancy (HALE) at birth (years) both sexes");
for ( int i = 0; i<=1800; i=i+33) {
pushMatrix();
translate(0, 89.5);
//hale is visible within this scope, but not outside the for loop
if (hale > 40 && hale < 60) {
shape(tipi2, i, 0);
}
//popMatrix(); should be called the same amount of times as pushMatrix
popMatrix();
}
}
}
void draw() {
}
If I want to add a row of text fields programatically in JavaFx, i can simply use the gridpane add method
This adds a set of text fields to row 1.
for (int i = 0; i < Fields.size(); i++) {
gridpane.add(new TextField(), i, 1);
}
Similarly, How do I delete a row?. I dont find a suitable method to delete a row/column conveeniently in JavaFX.
There's no directly equivalent method. To remove nodes, just use
gridpane.getChildren().remove(...); or gridpane.getChildren().removeAll(...); and pass in the nodes you want to remove from the pane.
In Java 8+, you can use removeIf:
gridPane.getChildren().removeIf(node -> GridPane.getRowIndex(node) == rowNumber);
Caveat
If removing items from the 0th row, also check GridPane.getRowIndex(node) == null, i.e.,
node -> GridPane.getRowIndex(node) == null || GridPane.getRowIndex(node) == 0
(I think this is JavaFX leaving the row number as null when no row number is given in the corresponding element in FXML, even though giving no row number in FXML means the element is in the 0th row, since the default row is the 0th row.)
This works pretty well:
while(MainGridPane.getRowConstraints().size() > 0){
MainGridPane.getRowConstraints().remove(0);
}
while(MainGridPane.getColumnConstraints().size() > 0){
MainGridPane.getColumnConstraints().remove(0);
}
JavaFX APIs are pretty lacking (like easily removing rows from GridPane) and unintuitive (like returning null instead 0 for GridPane.getRowIndex). Here is solution I came up with:
Utils:
package io.github.againpsychox.javaspeedrunsapp.utils;
import javafx.scene.Node;
import javafx.scene.layout.GridPane;
public class GridPaneUtils {
/**
* Gets row index constrain for given node, forcefully as integer: 0 as null.
* #param node Node to look up the constraint for.
* #return The row index as primitive integer.
*/
public static int getRowIndexAsInteger(Node node) {
final var a = GridPane.getRowIndex(node);
if (a == null) {
return 0;
}
return a;
}
/**
* Removes row from grid pane by index.
* Note: Might not work correctly if row spans are used.
* #param grid Grid pane to be affected.
* #param targetRowIndexIntegerObject Target row index to be removed. Integer object type, because for some reason `getRowIndex` returns null for children at 0th row.
*/
public static void removeRow(GridPane grid, Integer targetRowIndexIntegerObject) {
final int targetRowIndex = targetRowIndexIntegerObject == null ? 0 : targetRowIndexIntegerObject;
// Remove children from row
grid.getChildren().removeIf(node -> getRowIndexAsInteger(node) == targetRowIndex);
// Update indexes for elements in further rows
grid.getChildren().forEach(node -> {
final int rowIndex = getRowIndexAsInteger(node);
if (targetRowIndex < rowIndex) {
GridPane.setRowIndex(node, rowIndex - 1);
}
});
// Remove row constraints
grid.getRowConstraints().remove(targetRowIndex);
}
}
Example usage:
GridPaneUtils.removeRow(this.grid, GridPane.getRowIndex(this.idTextField));
Posting my solution for further readers...
I have a gridview (Order) with three columns:
Price
Quantity
Total
I want to multiply Price with Quantity and show the result in Total column of dataGridview.
Remember: my dataGridview isn't bind with any table.
I am trying this code to achieve my goal but this isn't working means value isn't being returned:
private void totalcal()
{
// is the foreach condition true? Remember my gridview isn't bound to any tbl
foreach (DataGridViewRow row in gvSale.Rows)
{
int a = Convert.ToInt32(row.Cells[3].Value) * Convert.ToInt32(row.Cells[4].Value); // value is null why??
row.Cells[5].Value = a;
}
}
This is the method which I am calling on a button click. (It is not working reason define inside of my code above)
And plus I want to know which is the suitable Datagridview event for this calculation?? I don't want to calculate the total on button click
try
int.Parse(row.Cells[3].Value.toString()) * int.Parse(row.Cells[4].Value.toString())
insted of
Convert.ToInt32(row.Cells[3].Value) * Convert.ToInt32(row.Cells[4].Value)
And you know you can call this method anytime, if you dont want it to be with button click. Call it after gvSale's row populating operations finished.
EDIT
I guess you want the calculations to be done while the user is entering Price or Quanitity. For that you need to write a EditingControlShowing method for your datagridview. Here's a piece of code. I tested it actually and got it working.
Add this code in your main class definition after InitializeComponent(); line
gvSale.EditingControlShowing += new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(this.gvSale_EditingControlShowing);
And then add this methods :
TextBox tb = new TextBox(); // this is just a textbox to use in editing control
int Price_Index = 3; // set this to your Price Column Index
int Quantity_Index = 4; // set this to your Quantity Column Index
int Total_Index = 5; // set this to your Total Column Index
private void gvSale_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (gvSale.CurrentCell.ColumnIndex == Price_Index || gvSale.CurrentCell.ColumnIndex == Quantity_Index)
{
tb = e.Control as TextBox;
tb.KeyUp += new KeyEventHandler(Calculate_Total);
}
}
private void Calculate_Total(object sender, KeyEventArgs e)
{
int Price_Value = 0;
int Quantity_Value = 0;
int.TryParse(gvSale.CurrentCell.ColumnIndex != Price_Index ? gvSale.CurrentRow.Cells[Price_Index].Value.ToString() : tb.Text, out Price_Value);
int.TryParse(gvSale.CurrentCell.ColumnIndex != Quantity_Index ? gvSale.CurrentRow.Cells[Quantity_Index].Value.ToString() : tb.Text, out Quantity_Value);
gvSale.CurrentRow.Cells[Total_Index].Value = Price_Value * Quantity_Value;
}
I am trying to use the repaint method in the following code to update the screen after user input. The game is a card game where the user has to click on two cards to reveal their pictures. If the pictures match the cards remain visible however if the pictures don't match the cards flip over to hide the pictures once again.
The first card becomes visible after clicking it, however when the second card is selected either both cards become visible if a matching picture is selected or the first card just flips over without the second picture being revealed.
Thanks for your help.
addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
int row = e.getX() / (Card.SIZE*2);
int col = e.getY() / (Card.SIZE*3);
//OPEN means the picture is visible
if(cards[row][col].getState() == Card.CLOSED)
cards[row][col].setState(OPEN);
repaint();
compareCards(row,col);
}
});
}
public void compareCards(int row, int col){
if(clickNum == 1){
r1 = row;
c1 = col;
clickNum++;
}
else if(clickNum == 2){
r2 = row;
c2 = col;
//The OR accounts for clicking twice on the same tile
if(cards[r1][c1].getNum() != cards[r2][c2].getNum() || (r1 == r2 && c1 == c2)){
cards[r1][c1].setState(CLOSED);
cards[r2][c2].setState(CLOSED);
}
clickNum = 1;
}
}
Your compare cards function is setting the card states to CLOSED much too quickly, and so they are not displaying. Try using:
public void compareCards(int row, int col){
try
{
Thread.sleep(5000);//sleep for five seconds
}catch(Exception e){}
if(clickNum == 1){
r1 = row;
c1 = col;
clickNum++;
}
else if(clickNum == 2){
r2 = row;
c2 = col;
//The OR accounts for clicking twice on the same tile
if(cards[r1][c1].getNum() != cards[r2][c2].getNum() || (r1 == r2 && c1 == c2)){
cards[r1][c1].setState(CLOSED);
cards[r2][c2].setState(CLOSED);
}
clickNum = 1;
}
}
This should display both cards for about five seconds before turning them over. You'll also have to implement a method which handles flipping the cards back over if they are the same if you don't already have one. I only say this because I don't see one here.
How to autofit content in cell using jxl api?
I know this is an old question at this point, but I was looking for the solution to this and thought I would post it in case someone else needs it.
CellView Auto-Size
I'm not sure why the FAQ doesn't mention this, because it very clearly exists in the docs.
My code looked like the following:
for(int x=0;x<c;x++)
{
cell=sheet.getColumnView(x);
cell.setAutosize(true);
sheet.setColumnView(x, cell);
}
c stores the number of columns created
cell is just a temporary place holder for the returned CellView object
sheet is my WriteableSheet object
The Api warns that this is a processor intensive function, so it's probably not ideal for large files. But for a small file like mine (<100 rows) it took no noticeable time.
Hope this helps someone.
The method is self explanatory and commented:
private void sheetAutoFitColumns(WritableSheet sheet) {
for (int i = 0; i < sheet.getColumns(); i++) {
Cell[] cells = sheet.getColumn(i);
int longestStrLen = -1;
if (cells.length == 0)
continue;
/* Find the widest cell in the column. */
for (int j = 0; j < cells.length; j++) {
if ( cells[j].getContents().length() > longestStrLen ) {
String str = cells[j].getContents();
if (str == null || str.isEmpty())
continue;
longestStrLen = str.trim().length();
}
}
/* If not found, skip the column. */
if (longestStrLen == -1)
continue;
/* If wider than the max width, crop width */
if (longestStrLen > 255)
longestStrLen = 255;
CellView cv = sheet.getColumnView(i);
cv.setSize(longestStrLen * 256 + 100); /* Every character is 256 units wide, so scale it. */
sheet.setColumnView(i, cv);
}
}
for(int x=0;x<c;x++)
{
cell=sheet.getColumnView(x);
cell.setAutosize(true);
sheet.setColumnView(x, cell);
}
It is fine, instead of scanning all the columns. Pass the column as a parameter.
void display(column)
{
Cell = sheet.getColumnView(column);
cell.setAutosize(true);
sheet.setColumnView(column, cell);
}
So when you wiill be displaying your text you can set the particular length. Can be helpfull for huge excel files.
From the JExcelApi FAQ
How do I do the equivilent of Excel's "Format/Column/Auto Fit Selection"?
There is no API function to do this for you. You'll need to write code that scans the cells in each column, calculates the maximum length, and then calls setColumnView() accordingly. This will get you close to what Excel does but not exactly. Since most fonts have variable width characters, to get the exact same value, you would need to use FontMetrics to calculate the maximum width of each string in the column. No one has posted code on how to do this yet. Feel free to post code to the Yahoo! group or send it directly to the FAQ author's listed at the bottom of this page.
FontMetrics presumably refers to java.awt.FontMetrics. You should be able to work something out with the getLineMetrics(String, Graphics) method I would have though.
CellView's autosize method doesn't work for me all the time. My way of doing this is by programatically set the size(width) of the column based on the highest length of data in the column. Then perform some mathematical operations.
CellView cv = excelSheet.getColumnView(0);
cv.setSize((highest + ((highest/2) + (highest/4))) * 256);
where highest is an int that holds the longest length of data in the column.
setAutosize() method WILL NOT WORK if your cell has over 255 characters. This is related to the Excel 2003 max column width specification: http://office.microsoft.com/en-us/excel-help/excel-specifications-and-limits-HP005199291.aspx
You will need to write your own autosize method to handle this case.
Try this exemple:
expandColumns(sheet, 3);
workbook.write();
workbook.close();
private void expandColumn(WritableSheet sheet, int amountOfColumns){
int c = amountOfColumns;
for(int x=0;x<c;x++)
{
CellView cell = sheet.getColumnView(x);
cell.setAutosize(true);
sheet.setColumnView(x, cell);
}
}
Kotlin's implementation
private fun sheetAutoFitColumns(sheet: WritableSheet, columnsIndexesForFit: Array<Int>? = null, startFromRowWithIndex: Int = 0, excludeLastRows : Int = 0) {
for (columnIndex in columnsIndexesForFit?.iterator() ?: IntProgression.fromClosedRange(0, sheet.columns, 1).iterator()) {
val cells = sheet.getColumn(columnIndex)
var longestStrLen = -1
if (cells.isEmpty()) continue
for (j in startFromRowWithIndex until cells.size - excludeLastRows) {
if (cells[j].contents.length > longestStrLen) {
val str = cells[j].contents
if (str == null || str.isEmpty()) continue
longestStrLen = str.trim().length
}
}
if (longestStrLen == -1) continue
val newWidth = if (longestStrLen > 255) 255 else longestStrLen
sheet.setColumnView(columnIndex, newWidth)
}
}
example for use
sheetAutoFitColumns(sheet) // fit all columns by all rows
sheetAutoFitColumns(sheet, arrayOf(0, 3))// fit A and D columns by all rows
sheetAutoFitColumns(sheet, arrayOf(0, 3), 5)// fit A and D columns by rows after 5
sheetAutoFitColumns(sheet, arrayOf(0, 3), 5, 2)// fit A and D columns by rows after 5 and ignore two last rows