combine JSpinner with JFormattedTextField - java

I want to make a customized JSpinner for editing day hours. I want the format to be 1HH:mm:ss a1, I already get this part.
I also want to add in some functionalities of JFormattedTextField:
setplaceHolderCharacter('_')
For example the time is 09:23:45, when the user delete 09,
__:23:45 shows on screen.
input restriction
For example the time is 09:23:45, when the user delete 09,
and try to enter anything, he can only enter numbers, no letter is allowed.
Any help would be appreciated!

There may be a better solution with JFormattedTextField, but here is one with built-in java classes. Also this doesn't fit your requirement replacing the deleted numbers with '_'. But you can select the seconds and then spinn the seconds instead of the hours. Also there is only almost an input restriction. You may write letters, but no ChangeEvent will be fired. Additional bonus: You don't have to think about when to change to the next hour after 60 minutes or something and it works, of course, with everything a Date can have (so spinning months or years is possible, too)
public class HourSpinner implements ChangeListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new HourSpinner();
}
});
}
public HourSpinner() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100, 70);
frame.setLocationRelativeTo(null);
Container contentPane = frame.getContentPane();
JSpinner dateSpinner = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.HOUR_OF_DAY));
DateEditor editor = new JSpinner.DateEditor(dateSpinner, "HH:mm:ss");
dateSpinner.setEditor(editor);
dateSpinner.addChangeListener(this);
contentPane.add(dateSpinner);
frame.setVisible(true);
}
#Override
public void stateChanged(ChangeEvent e) {
JSpinner source = (JSpinner) e.getSource();
System.out.println(source.getValue());
}
}

Related

Extending variable scope from one frame to another frame

I have two JFrame based windows: SeatLayout and BillSummary. I need to get the seatnumber from the SeatLayout frame and display it in BillSummary but the variable scope is limited to the first frame.
How can I do this?
Using multiple JFrame is a bad practice and it should be avoided.
Reason being, it will add more problems in the future and it will be nightmare to maintain.
To answer your question , how to pass variable from your parent(JFrame) to a child(JDialog) .This can achive by using JDialog.
I am going to run through an example.
lets say, your BillSummary.java is ....
//BillSummary Class
public class billSummary {
JFrame frame;
billSummary(JFrame frame) {
this.frame = frame;
}
public void launchbillSummary(int seatNumber) {
// Create a dialog that suits your ui , you can use JPanel as your layout container
JDialog dialog = new JDialog(frame, "Bill Summary", true);
dialog.setLayout(new BorderLayout());
dialog.setSize(100, 100);
dialog.add(new JLabel(Integer.toString(seatNumber)), BorderLayout.CENTER);
dialog.setVisible(true);
}
}
Your seatLayout.java
public class seatLayout {
seatLayout(){
//Lets say you have seleted seat number 10
int defaultSeatNumber = 10;
//Lets say you have a button and when it is clicked , you pass the data to billsummary page
JButton enter = new JButton("Enter");
//Your seatLayout GUI
JFrame frame = new JFrame("seat layout");
frame.setSize(300,300);
frame.add(enter);
enter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//Do your passing of data/ price of calculation here
//You pass the data that to your custom dialog -> Bill summary
new billSummary(frame).launchbillSummary(defaultSeatNumber);
}
});
frame.setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new seatLayout();
}
});
}
}
I hope this help and answers your question. Good luck :)

Auto Prediction TextField

Okay, I've been searching how to do an auto prediction textfield for days now, and yes I found some solutions but they are completely hard to understand to be honest, and totally confusing since I'm new to Java/GUI. It would have been much easier if I had to click a button to do it, but I cant get how the program will perform such action whenever "a letter gets written". I've made a simple textfield and a button, whenever the button is clicked, the string in the textfield gets added in an arraylist, then prints the whole arraylist in another textfield(Just a simple example to test the auto prediction)
public class Phonebook {
public static ArrayList<String> names = new ArrayList<String>();
public static void main(String[] args) {
JFrame myForm = new JFrame("Phonebook");
myForm.setSize(555, 500);
myForm.setLocation(0, 0);
JButton button = new JButton("Add");
button.setSize(100, 50);
button.setLocation(450, 40);
myForm.add(button);
JTextField t = new JTextField();
t.setSize(200, 60);
t.setLocation(10, 40);
myForm.add(t);
JTextField ttt = new JTextField();
ttt.setSize(500, 300);
ttt.setLocation(10, 100);
ttt.setEditable(false);
myForm.add(ttt);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
names.add(t.getText());
String str = "";
for(int i=0; i<names.size(); i++)
str + =names.get(i) + "\n";
ttt.setText(str);
}
});
myForm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myForm.setLayout(null);
myForm.setVisible(true);
}
}
So I want the big textfield to auto complete the small textfield, so if I type "M", it shows only the names in the arraylist that start with an "M", the code for finding the names that start with an "M" would be easy, but making it "Automatic" sounds very difficult to me. If anyone could help me with my code instead of sending me a new whole confusing code, I would really appreciate that. Thank you.
Edit: Or I just want the code that somehow checks if a letter is written, so (if a letter gets written in the textfield), system.out.print("A");
You could try attaching a Document Listener to the text box:
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
// search the prediction data for the current contents
// of the text field
}
public void removeUpdate(DocumentEvent e) {
// do stuff
}
public void changedUpdate(DocumentEvent e) {
//Plain text components do not fire these events
}
});
You can then use either the insertUpdate or removeUpdate functions to get a hook into the point when text is changed, access the textFields values and put your auto-complete functionality in there.

Honestly confused on how to apply Swing Timers to my program, can someone take a look?

I was reading about Swing Timers and the example really looks nothing like I was trying to do so I found it logically confusing to apply it to my program. I'm starting to think I don't even need a timer for this.
Here is what I am trying to do:
I am making a JFrame program that has the user enter a credit card number into a JTextField. Before they do this there is a JLabel that says "Please enter your number into the text field", then once they enter this into the field and hit enter, depending on whether my code determines that the card number is valid or not valid, the JLabel will change to "Invalid" or "Thank you, processing."
However, I have unsuccessfully found a way to make it change text based, it just seems to stay with whatever text I initially give it.
So could someone please look at my code and change it to do what I am asking? That would be excellent. You guys have been helpful in the past.
public class CreditGraphics {
public String cardNum;
public JFrame frame;
public JPanel panel;
public JLabel label;
public JTextField text;
public Timer timer;
public CreditGraphics() {
frame = new JFrame("HI");
panel = new JPanel();
label = new JLabel();
text = new JTextField(16);
panel.add(label);
panel.add(text);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
label.setText("Hi");
label.setText("Hello");
text.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardNum = text.getText();
timer = new Timer(2000,this);
timer.setInitialDelay(1000);
timer.start();
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new CreditGraphics();
}
});
}
public void checkCard(){
}
}
You have some major problems with your Timer's ActionListener as it is adding the anonymous inner ActionListener object, the this in the Timer's constructor, to itself. So it will call the very same actionPerformed inside the Timer that is called by the JButton that starts the Timer -- quite confusing. If your program were to need a Timer, you would do well to make sure to give it its own ActionListener, and not the same ActionListener that you add to your JButton as you're doing now.
Most importantly, do you even need a Swing Timer? I don't think so since you don't appear to be wanting an action repeatedly happening every xxx milliseconds, or an action that occurs once after xxx milliseconds, and since all you want to do is change the text. I suggest that instead you simply change your JLabel's text in the anonymous inner ActionListener class, and just leave it at that. If your requirements are different, then you will want to clarify and expand on your question.
So in semi-pseudocode, something like:
public void actionPerformed(ActionEvent e) {
String userText = text.getText();
if (testIfTextValid(userText)) { // some method to test if input OK
label.setText(INPUT_VALID); // String constant for JLabel to display
// here pass the userText to other parts of your code that needs to use it
} else {
label.setText(INPUT_INVALID);
}
}

Java - How to update a panel every second

I'm trying to create a Java GUI which displays the current time. Currently, I can make it display the current time, but only on startup. It then simply remains on that time forever. The reason is that I cannot figure out how to make it automatically load in the new current time every second. Here is my relevant code thus far:
// Getting the current time...
long epoch = System.currentTimeMillis() / 1000;
String date = new java.text.SimpleDateFormat("HH:mm:ss").format(new java.util.Date(epoch * 1000));
// Creating the panel...
JLabel lblThetime = new JLabel(date);
sl_panel.putConstraint(SpringLayout.NORTH, lblThetime, 55, SpringLayout.SOUTH, lblIBeA);
sl_panel.putConstraint(SpringLayout.WEST, lblThetime, 139, SpringLayout.WEST, panel);
lblThetime.setFont(new Font("Avenir Next", Font.PLAIN, 40));
// Adding the time to the panel
panel.add(lblThetime);
// My refresher which doesn't work
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
removeAll();
validate();
repaint();
}
}, 1000, 1000);
I attempted to make a refresher using information from this thread, but to no avail, the window (when run) is just blank. I then tried making a different refresher using information from this thread, and created this:
// My refresher which doesn't work
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
contentPane.remove(lblThetime);
contentPane.add(lblThetime);
}
}, 1000, 1000);
With contentPane having been defined as private JPanel contentPane;
Which also didn't work, however only the time itself is blank, the rest of the content in the window (One other JLabel (just some text)) remains as normal.
Without any refresher it behaves as described above, whereby it just displays the time when it started and remains on that time forever.
I'm using Eclipse with WindowBuilder. (And I'm (probably evidently) a complete noob to Java GUI stuff xD)
I discovered the solution!
I tried all the solutions given as answers here, and none which gave code fully worked, however all answers pointed me in the right direction. I found the solution to the problem on a website which I have forgotten the name of, but I used its suggestion and came up with this final solution which worked:
// New timer which works!
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
String date = new java.text.SimpleDateFormat("HH:mm:ss").format(new java.util.Date(System.currentTimeMillis()));
lblThetime.setText(date);
}
};
new Timer(delay, taskPerformer).start();
Thank you to all who answered as without said answers I probably would not have been able to find this solution :D
First of all you are using java.util.Timer instead of javax.swing.Timer. You need use this second class when working with Swing components to ensure GUI updates are made on the Event Dispatch Thread. Also take a look to Concurrency in Swing tutorial.
As suggested in other answers, there is no need to remove/add JLabel each time you want to update its text. Just call JLabel.setText() method.
If you still want remove/add the JLabel each time, then be aware of this:
From Container.add() javadoc:
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Then you'll need to call Component.revalidate() method. Like this:
contentPane.remove(lblThetime);
contentPane.add(lblThetime);
contentPane.revalidate();
Instead of removing and adding the label to the panel you should change the string of the label every second.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
String date = new java.text.SimpleDateFormat("HH:mm:ss").format(new java.util.Date() );
lblThetime.setText(date);
}
}, 1000, 1000);
// Creating the panel...
JLabel lblThetime = new JLabel(date);
You can try to use Swing Timer for that task, for example:
private static JLabel l;
public static void main(String[] args) {
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
l.setText(new Date().toString());
}
});
timer.start();
JFrame f = new JFrame();
l=new JLabel(new Date().toString());
f.getContentPane().add(l);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
That example update JLabel with new date every second
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
label.setText(new Date().toString());
}
}, 1000, 1000);
Isn't it simpler?
Clue 1: really search for Timer classes in Java. Did you pick the correct one?
Clue 2: update the label text instead.

Text in Label not displaying correctly with setText method

I'm trying to set the text in a label dynamically by calling the setText method whenever a button is clicked. Here is my code:
import java.awt.*;
import java.awt.event.*;
class Date {
public static void main(String[] args) {
new MainWindow();
}
}
class MainWindow {
static Label month = new Label();
static Label day = new Label();
static Button submit = new Button("Submit");
MainWindow() {
Frame myFrame = new Frame("Date Window");
myFrame.setLayout(new FlowLayout());
myFrame.add(month);
myFrame.add(day);
myFrame.add(submit);
submit.addActionListener(new ButtonListener());
myFrame.addWindowListener(new WindowListener());
myFrame.setSize(200, 200);
myFrame.setVisible(true);
}
}
class WindowListener extends WindowAdapter {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if (event.getSource() == MainWindow.submit) {
MainWindow.month.setText("12");
MainWindow.day.setText("31");
}
}
}
When I initialize the two Label objects without any arguments, the strings "12" and "31" that are passed to the setText method aren't visible on the screen when the submit button is clicked until I click on the window and drag to resize it. I've noticed this on a Mac only. On a PC, the strings are are visible but obscured until I resize the window. However, if I initialize the labels like this:
static Label month = new Label("0");
static Label day = new Label("0");
On the Mac, the strings appear as intended, however, they're obscured until the window is resized. What am I missing?
Calling validate() on the Frame as mentioned here solved the problem.
Try repainting the frame or/and set enough space(setPreferredSize, setMininumSize)
Well, most of your posting are over a year old so I'll give you the benefit of the doubt. I never use AWT so I don't know what the problem is, but I'll suggest:
1) Name you classes properly. "Date" is already a class in the JDK. Choose a better name.
2) Try using Swing components instead of AWT.
3) Get rid of static variables from your class.
4) Get rid of the WindowListener to close the frame.
The code example you posted here is 10-15 years old. Try something newer. Start with the Swing tutorial for more recent examples.

Categories