How does this JFormattedTextField work? - java

I have the sample code below, and I'm having problems understanding it. So I'd like two ask 2 questions:
Why does JFormattedTextField have a "value" (getValue(), setValue()) and a JTextField does not?
In the propertyChange() method, why is it sufficient to write:
amount = ((Number)amountField.getValue()).doubleValue();
to update the amount so that it is displayed the right way, but for the paymentField I have to call the setValue() method?
Sample:
/*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.text.*;
/**
* FormattedTextFieldDemo.java requires no other files.
*
* It implements a mortgage calculator that uses four
* JFormattedTextFields.
*/
public class FormattedTextFieldDemo extends JPanel
implements PropertyChangeListener {
//Values for the fields
private double amount = 100000;
private double rate = 7.5; //7.5%
private int numPeriods = 30;
//Labels to identify the fields
private JLabel amountLabel;
private JLabel rateLabel;
private JLabel numPeriodsLabel;
private JLabel paymentLabel;
//Strings for the labels
private static String amountString = "Loan Amount: ";
private static String rateString = "APR (%): ";
private static String numPeriodsString = "Years: ";
private static String paymentString = "Monthly Payment: ";
//Fields for data entry
private JFormattedTextField amountField;
private JFormattedTextField rateField;
private JFormattedTextField numPeriodsField;
private JFormattedTextField paymentField;
//Formats to format and parse numbers
private NumberFormat amountFormat;
private NumberFormat percentFormat;
private NumberFormat paymentFormat;
public FormattedTextFieldDemo() {
super(new BorderLayout());
setUpFormats();
double payment = computePayment(amount,
rate,
numPeriods);
//Create the labels.
amountLabel = new JLabel(amountString);
rateLabel = new JLabel(rateString);
numPeriodsLabel = new JLabel(numPeriodsString);
paymentLabel = new JLabel(paymentString);
//Create the text fields and set them up.
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);
rateField = new JFormattedTextField(percentFormat);
rateField.setValue(new Double(rate));
rateField.setColumns(10);
rateField.addPropertyChangeListener("value", this);
numPeriodsField = new JFormattedTextField();
numPeriodsField.setValue(new Integer(numPeriods));
numPeriodsField.setColumns(10);
numPeriodsField.addPropertyChangeListener("value", this);
paymentField = new JFormattedTextField(paymentFormat);
paymentField.setValue(new Double(payment));
paymentField.setColumns(10);
paymentField.setEditable(false);
paymentField.setForeground(Color.red);
//Tell accessibility tools about label/textfield pairs.
amountLabel.setLabelFor(amountField);
rateLabel.setLabelFor(rateField);
numPeriodsLabel.setLabelFor(numPeriodsField);
paymentLabel.setLabelFor(paymentField);
//Lay out the labels in a panel.
JPanel labelPane = new JPanel(new GridLayout(0,1));
labelPane.add(amountLabel);
labelPane.add(rateLabel);
labelPane.add(numPeriodsLabel);
labelPane.add(paymentLabel);
//Layout the text fields in a panel.
JPanel fieldPane = new JPanel(new GridLayout(0,1));
fieldPane.add(amountField);
fieldPane.add(rateField);
fieldPane.add(numPeriodsField);
fieldPane.add(paymentField);
//Put the panels in this panel, labels on left,
//text fields on right.
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
add(labelPane, BorderLayout.CENTER);
add(fieldPane, BorderLayout.LINE_END);
}
/** Called when a field's "value" property changes. */
public void propertyChange(PropertyChangeEvent e) {
Object source = e.getSource();
if (source == amountField) {
amount = ((Number)amountField.getValue()).doubleValue();
} else if (source == rateField) {
rate = ((Number)rateField.getValue()).doubleValue();
} else if (source == numPeriodsField) {
numPeriods = ((Number)numPeriodsField.getValue()).intValue();
}
double payment = computePayment(amount, rate, numPeriods);
paymentField.setValue(new Double(payment));
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("FormattedTextFieldDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new FormattedTextFieldDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
//Compute the monthly payment based on the loan amount,
//APR, and length of loan.
double computePayment(double loanAmt, double rate, int numPeriods) {
double I, partial1, denominator, answer;
numPeriods *= 12; //get number of months
if (rate > 0.01) {
I = rate / 100.0 / 12.0; //get monthly rate from annual
partial1 = Math.pow((1 + I), (0.0 - numPeriods));
denominator = (1 - partial1) / I;
} else { //rate ~= 0
denominator = numPeriods;
}
answer = (-1 * loanAmt) / denominator;
return answer;
}
//Create and set up number formats. These objects also
//parse numbers input by user.
private void setUpFormats() {
amountFormat = NumberFormat.getNumberInstance();
percentFormat = NumberFormat.getNumberInstance();
percentFormat.setMinimumFractionDigits(3);
paymentFormat = NumberFormat.getCurrencyInstance();
}
}

"Why has a JFormattedTextField an "value" (getValue(), setValue()) and a jTextField not?"
The text attributes of both JTextField and JFormattedTextField are the actual text you see displayed by each. But JFormattedTextField isn't just displaying some text that you give it. It, with the help of a Formatter that you provided, translates between some Object--in this case a Number--and the convenient human-readable text representation you see on the screen. The object whose value you're displaying is the "value" of the JFormattedTextField, how it looks on the screen is the "text". A regular JTextField, on the other hand, just shows whatever text you tell it to show and returns whatever the you type into it, so there's no need for a separate value attribute because it would always be identical to the "text".
"Why is it sufficient to write "amount = ((Number)amountField.getValue()).doubleValue();" to update the amount so that is is displayed the right way but for the paymentField i have to call the setValue-Methode?"
You're not writing
amount = ((Number)amountField.getValue()).doubleValue();
to update amountField, you're doing it to find out what to user typed into amountField. amountField is updating itself in response to user input because that's what JFormattedTextFields do.
Now, having learned what the user typed into amountField, you recalculate the payment amount and tell the paymentField to show the new payment by calling its setValue method.

Related

Can't get integer from JTextField

I'm trying to get an integer from a JTextField, but I keep getting a NumberFormatException. I used the code below:
JTextField price = new JTextField();
price.addActionListener(new ComboListener());
String inputText = price.getText();
int inputPrice = Integer.parseInt(inputText);
Every site says this is the proper way to do it, so I don't understand what I'm doing wrong.
edit: The full code is here:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class RatePanel extends JPanel {
private double[] rate; // exchange rates
private String[] currencyName;
private JLabel result;
public RatePanel() {
currencyName = new String[]{"Select the currency..",
"European Euro", "Canadian Dollar",
"Japanese Yen", "Australian Dollar",
"Indian Rupee", "Mexican Peso"};
rate = new double[]{0.0, 1.2103, 0.7351,
0.0091, 0.6969, 0.0222, 0.0880};
JLabel title = new JLabel("How much is that in dollars?");
title.setAlignmentX(Component.CENTER_ALIGNMENT);
title.setFont(new Font("Helvetica", Font.BOLD, 20));
add(title);
add(Box.createRigidArea(new Dimension(0, 100)));
JLabel enter = new JLabel("Enter cost of item");
enter.setAlignmentX(Component.LEFT_ALIGNMENT);
enter.setFont(new Font("Helvetica", Font.BOLD, 20));
add(enter);
JTextField price = new JTextField();
price.addActionListener(new BoxListener());
price.setAlignmentX(Component.RIGHT_ALIGNMENT);
add(price);
add(Box.createRigidArea(new Dimension(0, 100)));
JLabel select = new JLabel("Select a currency: ");
select.setAlignmentX(Component.LEFT_ALIGNMENT);
select.setFont(new Font("Helvetica", Font.BOLD, 20));
add(select);
JComboBox Cbox = new JComboBox(currencyName);
Cbox.addActionListener(new ComboListener());
Cbox.setAlignmentX(Component.RIGHT_ALIGNMENT);
add(Cbox);
String index = Cbox.getSelectedItem().toString();
}
public class BoxListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
String inputText = price.getText();
int inputPrice = Integer.parseInt(inputText);
}
}
public class ComboListener implements ActionListener {
public void actionPerformed(ActionEvent event, String index, double inputPrice, double[] rate) {
double finalPrice = 0;
switch (index) {
case "European Euro":
finalPrice = inputPrice * rate[1];
break;
case "Canadian Dollar":
finalPrice = inputPrice * rate[2];
break;
case "Japanese Yen":
finalPrice = inputPrice * rate[3];
break;
case "Australian Dollar":
finalPrice = inputPrice * rate[4];
break;
case "Indian Rupee":
finalPrice = inputPrice * rate[5];
break;
case "Mexican Peso":
finalPrice = inputPrice * rate[6];
break;
}
result = new JLabel(inputPrice + "USD equals " + finalPrice
+ index);
add(result);
}
#Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
I ran your code, it actually works fine (without giving me NumberFormatException).
You get NumberFormatException probably because you attempted the following:
Press Enter on the textfield when the field is empty
Press Enter on the textfield when the field contains non-numeric input
You could add validations to your input before attempting to parse the textfield's content into integer:
public class BoxListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
String s= price.getText();
if(s.matches("[0-9]+")) //Perform validation before parsing string
inputPrice = Integer.parseInt(s);
}
}
Also note that, instead of declaring inputPrice and your other components such as your textfields as local variables, I declared them as instance variables of RatePanel.
To declare your variables as instance variable instead of local variables:
class RatePanel extends JPanel{
private JTextfield txtPrice; // <--- declare here as instance variable
private int inputPrice; // <--- declare here as instance variable
public RatePanel(){
//If you declare in the constructor or other methods, they become local variables.
}
}
When I try to define it in the actionListener method, it tells me it
can't find the textbook
That is probably because you define 'price' as a local variable in the method that you create it. Your 'price' variable should be an instance variable that is visible to all methods in your class.
First of all, the code as written tries to access the text right after the text field is created, before the user has typed anything into it. The code accessing the text should be inside the action listener. If ComboListener is a class that you created, then the last two lines should be in its actionPerformed method; if you do it that way, make sure that the price variable is an instance variable or static variable (i.e., outside a method definition—whether to make it static and which class to put it in depends on how the rest of your code is structured).
An alternative way is to use an anonymous inner class, like this:
// the 'final' modifier is necessary for anonymous inner classes
// access local variables
final JTextField price = new JTextField();
price.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String inputText = price.getText();
// do the conversion and other processing here...
}
});
(I believe in newer versions of Java this can be abbreviated as
price.addActionListener((ActionEvent e) -> {
String inputText = price.getText();
// do the conversion and other processing here...
});
but I'm not 100% sure about that.)
Second, keep in mind that if you use parseInt, it'll only accept whole number values; things like 12.34 (with a decimal point) will cause an error. The simplest way to fix this is to use Double.parseDouble, although using doubles with prices can cause rounding errors, so it's not the best way to do it. Also, make sure you don't put a $ or £ or € or whatever in the box; that could also cause an error.
You are reading a JTextField immediately after creating it. At that point, it's empty empty string, which is not a valid number.
You should put that code in the listener where it will fire when the user presses Enter or something. And, additionaly, try to be nice to the user and show an error message instead of throwing an exception.

Can't expand JTree using the expandPath method

I've used an example by Ian F. Darwin on how to display a file system on a JTree, and although the code is clear to me, I can't figure out why I can't expand the tree on the valueChanged of the TreeSelectionListener. Here's the code:
package ericsonwrp.republica.vintage.caixa;
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.io.File;
import java.util.Collections;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
/**
* Display a file system in a JTree view
*
* #version $Id: FileTree.java,v 1.9 2004/02/23 03:39:22 ian Exp $
* #author Ian Darwin
*/
public class FileTree extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private JTree tree;
private JScrollPane scrollpane;
/** Construct a FileTree */
public FileTree(File dir) {
setLayout(new BorderLayout());
tree = new JTree(addNodes(null, dir));
tree.setRootVisible(false);
// Add a listener
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
.getPath().getLastPathComponent();
TreePath p = new TreePath(node.getPath());
tree.expandPath(p); // HERE <<<<<<<<<<<<<<
}
});
scrollpane = new JScrollPane();
scrollpane.getViewport().add(tree);
add(BorderLayout.CENTER, scrollpane);
}
/** Add nodes from under "dir" into curTop. Highly recursive. */
DefaultMutableTreeNode addNodes(DefaultMutableTreeNode curTop, File dir) {
String curPath = dir.getPath();
DefaultMutableTreeNode curDir = new DefaultMutableTreeNode(curPath);
if (curTop != null) { // should only be null at root
curTop.add(curDir);
}
Vector<String> ol = new Vector<String>();
String[] tmp = dir.list();
for (int i = 0; i < tmp.length; i++)
ol.addElement(tmp[i]);
Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
File f;
Vector<String> files = new Vector<String>();
// Make two passes, one for Dirs and one for Files. This is #1.
for (int i = 0; i < ol.size(); i++) {
String thisObject = (String) ol.elementAt(i);
String newPath;
if (curPath.equals("."))
newPath = thisObject;
else
newPath = curPath + File.separator + thisObject;
if ((f = new File(newPath)).isDirectory())
addNodes(curDir, f);
else
files.addElement(thisObject);
}
// Pass two: for files.
for (int fnum = 0; fnum < files.size(); fnum++)
curDir.add(new DefaultMutableTreeNode(files.elementAt(fnum)));
return curDir;
}
public Dimension getMinimumSize() {
return new Dimension(200, 400);
}
public Dimension getPreferredSize() {
return new Dimension(200, 400);
}
}
Here's a visual example of my "FileChooser" with this JTree:
As you can see, the node was supposed to expand on the valueChanged, and that does not happen ("Games" is a folder).
In your picture Games is not a folder. Look at the picture from your link. Something went wrong in addNodes(). You cant expand a leaf ;)
Try to call FileTree with new File("."). You should see your project folder. This worked for me. When I try to call new FileTree(new File("/")) to get all folders... here addNodes() fails.
Use this solution.
Maybe you have to make some changes:
... implements Comparable<File> {
and
public int compareTo(File object)...

creating a GUI in Java

I have worked a bit with creating basic GUI's in java. Very simply, what I am trying to achieve, is a title in a given font, and below that a JPanel containing 5 different buttons equally spaced and sized, with a modifier function that allows for the resolution to be changed by a scale factor of say 0.75, the JPanel would not touch the edge of the screen, but have a border of 20 pixels away. What I would love to achieve is a way of the user being able to enter whatever resolution they want and for it to still keep the same basic design therefore making it compatible with other devices.
.
The code I have been using thus far is:
package prototype1;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GUI {
public static void main(String[] args){
stateManager();
}
static public JFrame menu = new JFrame("Menu Screen");
static public double modifier = 1;
static public int width = 750;
static public int height = 1334;
static void stateManager(){
JFrame.setDefaultLookAndFeelDecorated(true);
AL demo = new AL();
menu.setContentPane(demo.contentPanel1());
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu.setSize((int) (width * modifier),(int) (height * modifier));
System.out.println((int)(width * modifier));
menu.setVisible(true);
}
static class AL implements ActionListener{
JLabel titleLabel;
JButton checkStar;
JPanel buttonScreenMenu;
public JPanel contentPanel1(){
JPanel totalGUI = new JPanel();
totalGUI.setLayout(null);
totalGUI.setBackground(Color.white);
int x = width;
int y = height;
titleLabel = new JLabel("Select what it is you would like to do!");
titleLabel.setFont(new Font("Castellar",Font.PLAIN, (int) (18 * modifier)));
titleLabel.setLocation(0,(int) (40 * modifier));
titleLabel.setSize((int) (x * modifier),(int) (30 * modifier));
titleLabel.setHorizontalAlignment(0);
totalGUI.add(titleLabel);
buttonScreenMenu = new JPanel();
buttonScreenMenu.setLocation((int) (20 * modifier) , (int) (100 * modifier));
buttonScreenMenu.setSize((int) ((x - 40) * modifier),(int) ((y - 120) * modifier));
buttonScreenMenu.setBorder(BorderFactory.createLineBorder(Color.black));
totalGUI.add(buttonScreenMenu);
checkStar = new JButton("Work out a Star");
checkStar.setLocation((int)(20 * modifier),(int)(20 * modifier));
checkStar.setSize(buttonScreenMenu.getWidth() - 40, (int) (buttonScreenMenu.getHeight() / 4) - 40);
checkStar.setBackground(Color.white);
buttonScreenMenu.add(checkStar);
return totalGUI;
}
#Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
}
However I stopped here as I was not getting anywhere near the results I wanted. The output of this code looks as follows:
How to fix the resolution problem?
Off of what cricket said, using absolute position will cause and give you many problems. I suggest you to look into using a layout manager such as box layout, which looks exactly same way you want to display your nodes. All you need to do is add spacing between the nodes. Which you can see how to do here.
Thus alternatively if you still want the users to enter in the dimensions of their frames. All you have to do is set the dimensions of your jframe and every thing will automatically adjust itself.

How to fix this Bad operand

I Need To convert years of days and this error stops me.
help please.. need to pass it now.
error: bad operand types for binary operator '*'
error: result = screen * 365;
^
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class DaysOfYears extends JFrame implements ActionListener
{
JTextField screen = new JTextField(30);
JButton conBtn = new JButton("Convert");
JLabel jb = new JLabel ("");
private double result;
public DaysOfYears(){
super("Convert Your Years in Days");
setSize(400, 200);
setLayout(new FlowLayout(FlowLayout.LEFT));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(screen);
add(conBtn);
add(jb);
conBtn.addActionListener(this);
}
public void actionPerformed(ActionEvent e){
result = screen * 365;
jb.setText(""+result);
}
public static void main (String[] args) {
DaysOfYears days = new DaysOfYears();
days.show(true);
}
}
I think you wanted to parse the text value of your JTextField and then perform your multiplication. Something like,
result = Integer.parseInt(screen.getText()) * 365;
Note that leap years have 366 days.
The JTextField holds its contents as String. You will need to convert it to integer unless of course you are supplying a string representation of a double data type within the JTextField.
Try something like:
result = Integer.valueOf(screen.getText()) * 365;
Here screen is a object of JTextFieldso multiply operation will not perform on the object of JTextField type you can grab the values of this object convert it into any Number type then try to multiplying. It will solve your problem .
Try this......
result = Integer.parseInt(screen.getText()) * 365;
// this will perform multiply actually. Thnak you

Need Help Animating Images in an HBox using JavaFX

I'm working on creating a simulation program for a game called Counter-Strike: Global Offensive, and I'm stuck on how I should animate certain images within an HBox. In the game, there are Weapon Cases containing various skins of different rarity. Upon clicking the 'Open' button, the possible items to win should start scrolling through the HBox. Think of it almost like Wheel of Fortune, where it begins fast and gradually slows down until it stops on 1 name, but in this case, instead of names there are items, and instead of a 'wheel', I have a horizontal HBox with images scrolling through. Here is a good example of what I'm trying to make: http://cases.goaggro.com/.
Currently, I have an instance of the ImageView class assigned to each individual weapon image that should be included in the total group of items to be rolled, and an array to hold all of these images. On the GUI, I have the HBox's max width and height set so that any 3 of these images placed inside the HBox from left to right fill its' volume perfectly. My first problem resides here. If I try to do something like
Hbox.getChildren().addAll(itemArray);
it will add the first 3 just fine, but will continue to add images beyond the boundaries of the HBox until reaching the main windows border. Is there any way to add more images into the HBox than the max displayed image count (being 3 due to the current HBox size I have set) while preventing them from exceeding the HBox boundaries and simply being hidden in the back?
The second question is, what would be the best way to go about animating each image inside of my HBox so that it scrolls towards the left but not beyond or outside of the HBox borders? I need the left-most image to slide left off the screen, while the middle image slides to the left position, and a new image slides in from the right to fill the right position, and repeat this at a speed that gradually slows to the point of landing on an item.
Currently, adding this code to the 'Open' button's event handler adds the images in item1, item2, and item3 correctly into the HBox. But if I exceed 3 images (like setting the HBox .addAll() to itemArray instead of the first 3 items individually, for example), it exceeds the HBox border and starts laying them on top of the scene until reaching the main windows border. NOTE: There are a total of 15 instances of the ImageView class (item1-item15) but I shortened the code to only 4, as well as the arrays contents to those 4, since the issue happens regardless when any more than 3 images are placed into the HBox.
public class Controller
{
#FXML
private HBox hBox;
public void openCaseAction(ActionEvent actionEvent)
{
final ImageView item1 = new ImageView(new Image(getClass().getResourceAsStream("../images/image1.png")));
final ImageView item2 = new ImageView(new Image(getClass().getResourceAsStream("../images/image2.png")));
final ImageView item3 = new ImageView(new Image(getClass().getResourceAsStream("../images/image3.png")));
final ImageView item4 = new ImageView(new Image(getClass().getResourceAsStream("../images/image4.png")));
final ImageView[] itemArray ={item1,item2,item3,item4};
hBox.getChildren().addAll(item1,item2,item3);
}
}
You probably want to use a custom layout for this rather than a HBox. Take a look at the Display Shelf example:
Download the Java 8 demos and samples from Oracle.
Extract the sample package.
Run the demo/javafx_samples/Ensemble8.jar program.
Type "Display Shelf" into the program's search bar.
View the Display Shelf example UI and source code.
Copy and modify as you see fit while respecting the original license terms.
It won't be exactly what you are looking for but it will be a much closer starting point than trying to animate items in a HBox.
Oracle DisplayShelf sample code:
/*
* Copyright (c) 2008, 2014, Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
* - Neither the name of Oracle Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package ensemble.samples.graphics2d.displayshelf;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.control.ScrollBar;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
/**
* Simple 7 segment LED style digit. It supports the numbers 0 through 9.
*/
/**
* A ui control which displays a browse-able display shelf of images
*/
public class DisplayShelf extends Region {
private final Duration DURATION = Duration.millis(500);
private final Interpolator INTERPOLATOR = Interpolator.EASE_BOTH;
private final double SPACING = 50;
private final double LEFT_OFFSET = -110;
private final double RIGHT_OFFSET = 110;
private final double SCALE_SMALL = 0.7;
private PerspectiveImage[] items;
private Group centered = new Group();
private Group left = new Group();
private Group center = new Group();
private Group right = new Group();
private int centerIndex = 0;
private Timeline timeline;
private ScrollBar scrollBar = new ScrollBar();
private boolean localChange = false;
private Rectangle clip = new Rectangle();
public DisplayShelf(Image[] images) {
// set clip
setClip(clip);
// set ids for styling via CSS
setId("displayshelf");
scrollBar.setId("display-scrollbar");
// create items
items = new PerspectiveImage[images.length];
for (int i = 0; i < images.length; i++) {
final PerspectiveImage item =
items[i] = new PerspectiveImage(images[i]);
final double index = i;
item.setOnMouseClicked((MouseEvent me) -> {
localChange = true;
scrollBar.setValue(index);
localChange = false;
shiftToCenter(item);
});
}
// setup scroll bar
scrollBar.setMax(items.length - 1);
scrollBar.setVisibleAmount(1);
scrollBar.setUnitIncrement(1);
scrollBar.setBlockIncrement(1);
scrollBar.valueProperty().addListener((Observable ov) -> {
if (!localChange) {
shiftToCenter(items[(int) Math.round(scrollBar.getValue())]);
}
});
// create content
centered.getChildren().addAll(left, right, center);
getChildren().addAll(centered, scrollBar);
// listen for keyboard events
setFocusTraversable(true);
setOnKeyPressed((KeyEvent ke) -> {
if (ke.getCode() == KeyCode.LEFT) {
shift(1);
localChange = true;
scrollBar.setValue(centerIndex);
localChange = false;
} else if (ke.getCode() == KeyCode.RIGHT) {
shift(-1);
localChange = true;
scrollBar.setValue(centerIndex);
localChange = false;
}
});
// update
update();
}
#Override
protected void layoutChildren() {
// update clip to our size
clip.setWidth(getWidth());
clip.setHeight(getHeight());
// keep centered centered
centered.setLayoutY((getHeight() - PerspectiveImage.HEIGHT) / 2);
centered.setLayoutX((getWidth() - PerspectiveImage.WIDTH) / 2);
// position scroll bar at bottom
scrollBar.setLayoutX(10);
scrollBar.setLayoutY(getHeight() - 25);
scrollBar.resize(getWidth() - 20, 15);
}
private void update() {
// move items to new homes in groups
left.getChildren().clear();
center.getChildren().clear();
right.getChildren().clear();
for (int i = 0; i < centerIndex; i++) {
left.getChildren().add(items[i]);
}
center.getChildren().add(items[centerIndex]);
for (int i = items.length - 1; i > centerIndex; i--) {
right.getChildren().add(items[i]);
}
// stop old timeline if there is one running
if (timeline != null) {
timeline.stop();
}
// create timeline to animate to new positions
timeline = new Timeline();
// add keyframes for left items
final ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
for (int i = 0; i < left.getChildren().size(); i++) {
final PerspectiveImage it = items[i];
double newX = -left.getChildren().size()
* SPACING + SPACING * i + LEFT_OFFSET;
keyFrames.add(new KeyFrame(DURATION,
new KeyValue(it.translateXProperty(), newX, INTERPOLATOR),
new KeyValue(it.scaleXProperty(), SCALE_SMALL, INTERPOLATOR),
new KeyValue(it.scaleYProperty(), SCALE_SMALL, INTERPOLATOR),
new KeyValue(it.angle, 45.0, INTERPOLATOR)));
}
// add keyframe for center item
final PerspectiveImage centerItem = items[centerIndex];
keyFrames.add(new KeyFrame(DURATION,
new KeyValue(centerItem.translateXProperty(), 0, INTERPOLATOR),
new KeyValue(centerItem.scaleXProperty(), 1.0, INTERPOLATOR),
new KeyValue(centerItem.scaleYProperty(), 1.0, INTERPOLATOR),
new KeyValue(centerItem.angle, 90.0, INTERPOLATOR)));
// add keyframes for right items
for (int i = 0; i < right.getChildren().size(); i++) {
final PerspectiveImage it = items[items.length - i - 1];
final double newX = right.getChildren().size()
* SPACING - SPACING * i + RIGHT_OFFSET;
keyFrames.add(new KeyFrame(DURATION,
new KeyValue(it.translateXProperty(), newX, INTERPOLATOR),
new KeyValue(it.scaleXProperty(), SCALE_SMALL, INTERPOLATOR),
new KeyValue(it.scaleYProperty(), SCALE_SMALL, INTERPOLATOR),
new KeyValue(it.angle, 135.0, INTERPOLATOR)));
}
// play animation
timeline.play();
}
private void shiftToCenter(PerspectiveImage item) {
for (int i = 0; i < left.getChildren().size(); i++) {
if (left.getChildren().get(i) == item) {
int shiftAmount = left.getChildren().size() - i;
shift(shiftAmount);
return;
}
}
if (center.getChildren().get(0) == item) {
return;
}
for (int i = 0; i < right.getChildren().size(); i++) {
if (right.getChildren().get(i) == item) {
int shiftAmount = -(right.getChildren().size() - i);
shift(shiftAmount);
return;
}
}
}
public void shift(int shiftAmount) {
if (centerIndex <= 0 && shiftAmount > 0) {
return;
}
if (centerIndex >= items.length - 1 && shiftAmount < 0) {
return;
}
centerIndex -= shiftAmount;
update();
}
}
/*
* Copyright (c) 2008, 2014, Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
* - Neither the name of Oracle Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package ensemble.samples.graphics2d.displayshelf;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Parent;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.effect.Reflection;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
/**
* A Node that displays a image with some 2.5D perspective rotation around the Y
* axis.
*/
public class PerspectiveImage extends Parent {
private static final double REFLECTION_SIZE = 0.25;
public static final double WIDTH = 200;
public static final double HEIGHT = WIDTH + (WIDTH * REFLECTION_SIZE);
private static final double RADIUS_H = WIDTH / 2;
private static final double BACK = WIDTH / 10;
private PerspectiveTransform transform = new PerspectiveTransform();
/**
* Angle Property
*/
public final DoubleProperty angle = new SimpleDoubleProperty(45) {
#Override
protected void invalidated() {
// when angle changes calculate new transform
double lx = (RADIUS_H - Math.sin(Math.toRadians(angle.get())) * RADIUS_H - 1);
double rx = (RADIUS_H + Math.sin(Math.toRadians(angle.get())) * RADIUS_H + 1);
double uly = (-Math.cos(Math.toRadians(angle.get())) * BACK);
double ury = -uly;
transform.setUlx(lx);
transform.setUly(uly);
transform.setUrx(rx);
transform.setUry(ury);
transform.setLrx(rx);
transform.setLry(HEIGHT + uly);
transform.setLlx(lx);
transform.setLly(HEIGHT + ury);
}
};
public final double getAngle() {
return angle.getValue();
}
public final void setAngle(double value) {
angle.setValue(value);
}
public final DoubleProperty angleModel() {
return angle;
}
public PerspectiveImage(Image image) {
ImageView imageView = new ImageView(image);
Reflection reflection = new Reflection();
reflection.setFraction(REFLECTION_SIZE);
imageView.setEffect(reflection);
setEffect(transform);
getChildren().addAll(imageView);
}
}

Categories

Resources