The default JavaFX tableview example does not go very far with regards to showing you how to format cells that contain Integers (you typically want them to align right) or Decimal values (aligned right and formatted properly).
I'm posting this here as a reminder to myself, as well as to anyone that might have come across the same issue. This is just a code posting, explanations on how to use JavaFX and the rest of the code can be found in the JavaFX sample code provided by Oracle.
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.beans.property.StringProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;
public class TableSample extends Application {
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setScene(new Scene(root));
final ObservableList<Person> data = FXCollections.observableArrayList();
data.add(new Person("Jacobz", "Smithy", "jacobz.smith@example.com", 78, 19.99));
data.add(new Person("Jacob", "Smith", "jacob.smith@example.com", 23, 116.0));
data.add(new Person("Isabella", "Johnson", "isabella.johnson@example.com", 101, 20.1));
data.add(new Person("Ethan", "Williams", "ethan.williams@example.com", 43, 18.0));
data.add(new Person("Emma", "Jones", "emma.jones@example.com", 44, 23.88));
data.add(new Person("Michael", "Brown", "michael.brown@example.com", 56, 19.5));
TableColumn firstNameCol = new TableColumn();
firstNameCol.setText("First");
firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
TableColumn lastNameCol = new TableColumn();
lastNameCol.setText("Last");
lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
TableColumn emailCol = new TableColumn();
emailCol.setText("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(new PropertyValueFactory("email"));
TableColumn ageCol = new TableColumn();
ageCol.setText("Age");
ageCol.setMinWidth(100);
ageCol.setCellValueFactory(new PropertyValueFactory("age"));
TableColumn pricePaidCol = new TableColumn();
pricePaidCol.setText("PricePaid");
pricePaidCol.setMinWidth(100);
pricePaidCol.setCellValueFactory(new PropertyValueFactory("pricePaid"));
//Formatting decimal columns
pricePaidCol.setCellFactory(new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<Person, Double>() {
@Override
public void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}
private String getString() {
String ret = "";
if (getItem() != null) {
String gi = getItem().toString();
NumberFormat df = DecimalFormat.getInstance();
df.setMinimumFractionDigits(2);
df.setRoundingMode(RoundingMode.DOWN);
ret = df.format(Double.parseDouble(gi));
} else {
ret = "0.00";
}
return ret;
}
};
cell.setStyle("-fx-alignment: top-right;");
return cell;
}
});
//Formatting decimal columns end
//Formatting integer columns
ageCol.setCellFactory(new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<Person, Integer>() {
@Override
public void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}
private String getString() {
String ret = "";
if (getItem() != null) {
ret = getItem().toString();
} else {
ret = "0";
}
return ret;
}
};
cell.setStyle("-fx-alignment: top-right;");
return cell;
}
});
//Formatting integer columns end
TableView tableView = new TableView();
tableView.setItems(data);
tableView.getColumns().addAll(firstNameCol, lastNameCol, emailCol, ageCol, pricePaidCol);
root.getChildren().add(tableView);
}
public static class Person {
private StringProperty firstName;
private StringProperty lastName;
private StringProperty email;
private IntegerProperty age;
private DoubleProperty pricePaid;
private Person(String fName, String lName, String email, int age, Double pPaid) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
this.age = new SimpleIntegerProperty(age);
this.pricePaid = new SimpleDoubleProperty(pPaid);
}
public StringProperty firstNameProperty() {
return firstName;
}
public StringProperty lastNameProperty() {
return lastName;
}
public StringProperty emailProperty() {
return email;
}
public IntegerProperty ageProperty() {
return age;
}
public DoubleProperty pricePaidProperty() {
return pricePaid;
}
}
@Override
public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Monday, July 8, 2013
Saturday, June 1, 2013
Quick CRUD Application on Netbeans 7.3
I often find the need for a quick CRUD application to Create, Read, Update & Write to a local or remote database, and previous versions of Netbeans made this very easy to do with the Swing Desktop Database Application feature.
This should be easy to follow for anyone, even if you've never even worked with Netbeans. The only thing you might need to take a look at first, is connecting to a database.
Since the JSR-296 (Swing Application Framework) has been deprecated, you might think that it's no longer possible to quickly throw together a CRUD app, but you'd be wrong :-)
If you want to follow along, fire up Netbeans 7.3 and follow along, this will be a mostly visual how-to. I'm running on Ubuntu, but you should get very similar visuals with a Mac or PC.
Start up a new project - as shown, go for Java->Java Application
So let's solve this problem, first select the two date fields as shown below and make them smaller.
So that's it! You now have a truly fully functional CRUD application with no real coding required. There is one thing that's still bugging me, I don't like the Nimbus look that much. Let's change that, it's pretty easy to do. Locate the piece of code as shown below.
Type in the bit of code as shown below. Take care where you enter the code by looking at the highlighted starting and ending curly brackets.
Add the javax.swing.UIManager.
Add a reference to the setLookAndFeel in the main section.
Launch the application again & now you should have the same look as your OS. In my case that's Ubuntu & now everything works exactly as expected.
There's still some functionality we can add easily, that's to make it possible to sort any of the fields. Look at the three lines below and add them to your NewMasterDetailForm.
Right-click on the top table grid and then check the box that says 'autoCreateRowSorter' - and that's it!
Let's take it one step further, by adding an icon for the application. Type up the line below.
We'll change it in the next step or two though, I've just copied and pasted the line from code that I had already. There's a really easy way to cheat and get the image we want imported into our project. Just drop a label anywhere on an open space, we'll delete it again later, this is just to get things going.
Right-click on the label & click on the ellipsis button of the 'icon' element. Then click on 'Import to Project' and select an image that's about 36x36 pixels.
Change the reference to the icon in your code as shown below.
In Ubuntu you don't see any app icons in the top bar, but this is what it looks like in Windows, which also shows that the app works in both Linux and Windows.
The last missing piece is a title for the form in Windows, to do that, you just add frame.setTitle("CRUDDemo");
as shown below, and you're done.
That concludes this little demo, hopefully it helps you to quickly build a CRUD application.
Here's the look-and-feel piece of code, be aware that you should still have one last closing curly bracket at the end.
Happy coding!
This should be easy to follow for anyone, even if you've never even worked with Netbeans. The only thing you might need to take a look at first, is connecting to a database.
Since the JSR-296 (Swing Application Framework) has been deprecated, you might think that it's no longer possible to quickly throw together a CRUD app, but you'd be wrong :-)
If you want to follow along, fire up Netbeans 7.3 and follow along, this will be a mostly visual how-to. I'm running on Ubuntu, but you should get very similar visuals with a Mac or PC.
Start up a new project - as shown, go for Java->Java Application
Okay, so now add a new form, right-click on your project name, you should see something like this. You will see that once you've done this once, the 'Master/Detail Sample Form' should become one of your top selections when you right-click and then select 'New'.
And look at that! We have a form that allows you to select a database connection, table & fields to use. Not bad at all!
I've just selected the local Derby database, but as long as you know the connection details for you database, you could connect to any other database you like. I'm not going to go into details here, there's lots of information on that if you browse the interwebs a bit. In particular, connecting to a MySQL table is just as easy as connecting to this sample Derby database.
You will see that in the first selection, it shows the 'Customer' database, and this is the one that is used in a lot of demos. There is a particular problem with this though, the fields are very straight-forward, so I will be using the 'Purchase_Order' database, since it has a date field.
If you click next, you will be able to select fields to use and move them up & down.
Click 'Next' and you will get a form with the master-detail components you would expect.
I've just click-dragged it to enlarge the form.
In the next step we'll do something you might find a bit odd, but it's the easiest in this case. Just go ahead and delete the 'CRUDDemo' form. If you try to run the project now, you will get this notification, just click 'OK' and it will become the new main class.
Once you've done that, you should be able to launch the application. Look at that! A fully functional CRUD application in no time & no coding at all.
Go ahead and click on one of the top rows & you should see the detail part filling up. There is one problem though, take a look at the 'Sales Date' and 'Shipping Date' fields, they're empty. That's the little secret that the other more simplistic demos do not show you how to resolve.
If you take a look at the output window at the bottom, you will see the error that's being thrown - 'Cannot cast java.util.Date to java.lang.String'.
Find the 'FormattedField' component and drop them next to the date fields.
It should look something like this now.
Take note of the variable name by right-clicking on the original 'Sales Date' item and clicking on 'Change Variable Name'. We're not going to change the name, but you can copy the name to use it in the next step.
Right-click on the 'Formatted Field' and select 'Bind->Value', then pick the 'Binding Source' and 'Binding Expression' as below. Once you've done that, you can delete the original 'Sales Date' field.
Now rename the new Formatted Field to 'salesDateField'.
Do the same for the other date field & hook it up to the 'Shipping Date'. Once you've done that, you should no longer get the error and the date fields should show properly.
You might notice that our new fields do not behave quite the same as the original ones. The original fields are disabled, until you select a row. To make the new fields behave in the same way, click on one of the original fields and copy the text as shown below.
Now just click on one of the new fields & just paste it in.
So that's it! You now have a truly fully functional CRUD application with no real coding required. There is one thing that's still bugging me, I don't like the Nimbus look that much. Let's change that, it's pretty easy to do. Locate the piece of code as shown below.
Type in the bit of code as shown below. Take care where you enter the code by looking at the highlighted starting and ending curly brackets.
Add the javax.swing.UIManager.
Add a reference to the setLookAndFeel in the main section.
Launch the application again & now you should have the same look as your OS. In my case that's Ubuntu & now everything works exactly as expected.
There's still some functionality we can add easily, that's to make it possible to sort any of the fields. Look at the three lines below and add them to your NewMasterDetailForm.
Right-click on the top table grid and then check the box that says 'autoCreateRowSorter' - and that's it!
Let's take it one step further, by adding an icon for the application. Type up the line below.
We'll change it in the next step or two though, I've just copied and pasted the line from code that I had already. There's a really easy way to cheat and get the image we want imported into our project. Just drop a label anywhere on an open space, we'll delete it again later, this is just to get things going.
Right-click on the label & click on the ellipsis button of the 'icon' element. Then click on 'Import to Project' and select an image that's about 36x36 pixels.
The last missing piece is a title for the form in Windows, to do that, you just add frame.setTitle("CRUDDemo");
as shown below, and you're done.
Here's the look-and-feel piece of code, be aware that you should still have one last closing curly bracket at the end.
public static void main(String[] args) {
setLookAndFeel();
/* Create and display the form */
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setContentPane(new NewMasterDetailForm());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setIconImage(new ImageIcon(getClass().getResource("checkout.png")).getImage());
frame.setTitle("CRUDDemo");
frame.pack();
frame.setVisible(true);
}
});
}
public static void setLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.out.println("Error setting native LAF: " + e);
}
}
Happy coding!
Monday, April 29, 2013
Change Netbeans Java Swing Applications Interface Look-and-Feel to System Native Look
For some or other reason people at Oracle/Netbeans want us to use the horrendous (IMHO) Nimbus theme.
You can change that quite easily, this is one of the first things I do.
Alter your main class (don't put an interface on it), so look like the snippet below, which also shows you how to add an icon to your application.
Put the icon.png file in the same folder as the source, this Init class will call the MainForm (or whatever) and show it with the specified icon:
This does not however make the icon show on Windows, so add this: Right-click Form, Properties, set 'iconImages' to 'none', click 'iconImage'->'Value from existing component', click 'Property' then '...' then 'iconImage'
Now your Java application should look pretty much like other applications that run on the same OS, and yes, I WANT it to look like the other applications. :-)
You can change that quite easily, this is one of the first things I do.
Alter your main class (don't put an interface on it), so look like the snippet below, which also shows you how to add an icon to your application.
Put the icon.png file in the same folder as the source, this Init class will call the MainForm (or whatever) and show it with the specified icon:
public class Init {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
setLookAndFeel();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
MainForm m = new MainForm();
m.setTitle("EncodingConverter");
m.setIconImage(new ImageIcon(getClass().getResource("icon.png")).getImage());
m.setVisible(true);
}
});
}
public static void setLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.out.println("Error setting native LAF: " + e);
}
}
}
This does not however make the icon show on Windows, so add this: Right-click Form, Properties, set 'iconImages' to 'none', click 'iconImage'->'Value from existing component', click 'Property' then '...' then 'iconImage'
Now your Java application should look pretty much like other applications that run on the same OS, and yes, I WANT it to look like the other applications. :-)
Sunday, April 28, 2013
iPad & iPhone Viewport Rotate Screw-up
If you've designed a mobile site before (or if you're about to...) you would have seen or used this before:
You can disable scalability with javascript until gesturestart with this script:
<meta name="viewport" content="width=device-width, initial-scale=1">That's all fine & dandy, until someone rotates their screen and then flips it back again. This is one way to solve that little irritating issue:
You can disable scalability with javascript until gesturestart with this script:
if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
var viewportmeta = document.querySelector('meta[name="viewport"]');
if (viewportmeta) {
viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
document.body.addEventListener('gesturestart', function () {
viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
}, false);
}
}
Saturday, April 27, 2013
Prevent Pinch-zoom on a Div or Whole Body
Sometimes you just don't want people to go pinch-zoom your site into oblivion, luckily, there is a way to do that :-)
$("body").bind('touchstart', function preventZoom(e) {
var t2 = e.timeStamp
, t1 = $(this).data('lastTouch') || t2
, dt = t2 - t1
, fingers = e.originalEvent.touches.length;
$(this).data('lastTouch', t2);
if (!dt || dt > 500 || fingers > 1) return; // not double-tap
e.preventDefault(); // double tap - prevent the zoom
// also synthesize click events we just swallowed up
$(this).trigger('click').trigger('click');
});
Mobile Device Detection & Touch Screen Desktops
Not too long ago, I thought that this type of script was a pretty solid way of making sure that you redirect your traffic to a mobile site:
I originally got it from here: http://roughlybrilliant.com/jquery_mobile_best_practices#9
The question I've been asking myself lately is, with touch interfaces coming to desktop screens, this type of code that detects a touch interface will no longer just apply to mobile screens.
Due to this & the fact that mobile browsing growing exponentially, the best approach I believe is to just go for Responsive Design & one of the easier ways to do that is to use something like Twitter Bootstrap - http://twitter.github.io/bootstrap/scaffolding.html#responsive
Happy Coding!
if( ('querySelector' in document && 'localStorage' in window && 'addEventListener' in window && ('ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch) ) || navigator.userAgent.indexOf('IEMobile') > 0){
location.replace('YOUR MOBILE SITE'); }
I originally got it from here: http://roughlybrilliant.com/jquery_mobile_best_practices#9
The question I've been asking myself lately is, with touch interfaces coming to desktop screens, this type of code that detects a touch interface will no longer just apply to mobile screens.
Due to this & the fact that mobile browsing growing exponentially, the best approach I believe is to just go for Responsive Design & one of the easier ways to do that is to use something like Twitter Bootstrap - http://twitter.github.io/bootstrap/scaffolding.html#responsive
Happy Coding!
Subscribe to:
Posts (Atom)