I have a simple login screen. I want UserName and Password to show up in the first and second text fields until they are clicked on. This functionality is working. However the first text field is always focused when the app launches and therefore shows up as "" until it loses focus. I tried to set a default button and request focus to no avail. It looks like the button is defaulting correctly, but it is not receiving focus for some reason. Anyone know how to fix this?
public class Basics implements ActionListener{
private JFrame frmBasics;
private JTextField userNameFeild;
private JTextField passwordFeild;
private JButton btnSignIn;
private JButton btnSignUp;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Basics window = new Basics();
window.frmBasics.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}//end main
/**
* Create the application.
*/
public Basics() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmBasics = new JFrame();
frmBasics.setTitle("Welcome to the POOPalace!!!");
frmBasics.setBounds(100, 100, 511, 344);
frmBasics.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmBasics.getContentPane().setLayout(null);
userNameFeild = new JTextField("UserName");
userNameFeild.setBounds(148, 79, 214, 20);
userNameFeild.addFocusListener(new FocusedClass());
frmBasics.getContentPane().add(userNameFeild);
userNameFeild.setColumns(10);
passwordFeild = new JTextField("Password");
passwordFeild.setBounds(148, 126, 214, 20);
passwordFeild.addFocusListener(new FocusedClass());
frmBasics.getContentPane().add(passwordFeild);
passwordFeild.setColumns(10);
btnSignIn = new JButton("Sign In");
btnSignIn.setBounds(148, 182, 89, 23);
btnSignIn.addActionListener(this);
frmBasics.getContentPane().add(btnSignIn);
btnSignUp = new JButton("Sign Up");
btnSignUp.setBounds(273, 182, 89, 23);
btnSignUp.addActionListener(this);
frmBasics.getContentPane().add(btnSignUp);
//from what I've been reading these 2 lines should be the solution
//but the request focus seems to not be working
frmBasics.getRootPane().setDefaultButton(btnSignIn);;
btnSignIn.requestFocus();
}
#Override
public void actionPerformed(ActionEvent e) {
//frmBasics.getContentPane().removeAll();
//frmBasics.repaint();
System.out.println(userNameFeild.getText());
System.out.println(passwordFeild.getText());
}//actionPerformed
private class FocusedClass implements FocusListener {
#Override
public void focusGained(FocusEvent arg0) {
if(arg0.getSource().equals(userNameFeild) && userNameFeild.getText().compareTo("UserName") == 0){
userNameFeild.setText("");
}
if(arg0.getSource().equals(passwordFeild) && passwordFeild.getText().compareTo("Password") == 0){
passwordFeild.setText("");
}
}
#Override
public void focusLost(FocusEvent arg0) {
if(userNameFeild.getText().compareTo("") == 0){
userNameFeild.setText("UserName");
}
if(passwordFeild.getText().compareTo("") == 0){
passwordFeild.setText("Password");
}
frmBasics.getContentPane().repaint();
}
}
}//class
Requesting focus works only after the layout of the window is complete.
We need to call the requestFocusInWindow() in one of the three specific situations:
In the windowOpened() method.
In the EventQueue's invokeLater(), which will run after all pending events are processed.
In the overriden JFrame's setVisible() method.
The first option:
//btnSignIn.requestFocusInWindow();
frmBasics.addWindowListener(new WindowAdapter() {
#Override
public void windowOpened(WindowEvent e) {
btnSignIn.requestFocusInWindow();
}
});
Also note that requestFocusInWindow() is more portable than
requestFocus().
Related
this is my first question on this website.
I have this problem, in this class I have two buttons with two different functions, one to exit and another to put the first and last name in a text field.
I can't get the second ActionEvent to work, please help me, thanks.
import javax.swing.*;
import java.awt.event.*;
public class Prueba1 extends JFrame implements ActionListener{
private JLabel nombre, apellidos,respondo;
private JTextField textfield, textfield1;
private JButton boton,botonoff;
public Prueba1() {
setLayout(null);
nombre = new JLabel("Nombre:");
nombre.setBounds(10, 10, 300, 30);
add(nombre);
apellidos = new JLabel("Apellidos");
apellidos.setBounds(10, 40, 300, 30);
add(apellidos);
textfield = new JTextField();
textfield.setBounds(100,10,150,20);
add(textfield);
textfield1 = new JTextField();
textfield1.setBounds(100,40,150,20);
add(textfield1);
boton = new JButton("¿Que saldrá?");
boton.setBounds(10,80,120,30);
boton.addActionListener(this);
add(boton);
botonoff = new JButton("Salir");
botonoff.setBounds(10,120,120,30);
botonoff.addActionListener(this);
add(botonoff);
respondo = new JLabel("UwU");
respondo.setBounds(160,80,300,30);
add(respondo);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == boton) {
String nombreyapellidos, nombre1, apellidos1;
nombre1 = textfield.getText();
apellidos1 = textfield1.getText();
nombreyapellidos = nombre1 + apellidos1;
respondo.setText(nombreyapellidos);
}
}
public void actionPerformed1(ActionEvent e) {
if(e.getSource() == botonoff) {
System.exit(0);
}
}
public static void main(String args[]) {
Prueba1 clase = new Prueba1();
clase.setVisible(true);
clase.setBounds(0, 0, 500, 500);
clase.setResizable(true);
clase.setLocationRelativeTo(null);
}
}
Remove public void actionPerformed1(ActionEvent e) method and add the body of that method in the else branch in the body of public void actionPerformed(ActionEvent e).
public void actionPerformed(ActionEvent e) {
if (e.getSource() == boton) {
String nombreyapellidos, nombre1, apellidos1;
nombre1 = textfield.getText();
apellidos1 = textfield1.getText();
nombreyapellidos = nombre1 + apellidos1;
respondo.setText(nombreyapellidos);
} else if (e.getSource() == botonoff) {
System.exit(0);
}
}
When you provide an ActionListener object to a buttons button.addActionListener(listener)
You have several ways to accomplish this.
button.addActionListener(this);
Is only one way. This way says the the class implements ActionListener.
In effect it implements the
public void actionPerformed(ActionEvent e)
method.
Your
public void actionPerformed1(ActionEvent e)
can't be used by the button at all.
Fortunately there are many other ways to describe the code that should be executed when an action event is produced.
An inner class, static or not. Other class/object.
A lambda expression.
You can find how to express a lambda here.
I am learning about multithreading right now.
I have a "main" class in which I build a JFrame with a Textfield and a Start and a Stop Button in it.
I also have another class/Thread from which I want to print the current time into my Textfield when I click the Start Button of my Frame. Everything works but the text doesn't change in my Textfield as I start the Thread even though Eclipse says my code is alright.
What am I doing wrong?
Class 1:
public class Uhr extends JFrame {
private JPanel contentPane;
public JTextPane tpZeit;
Thread t;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Uhr frame = new Uhr();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Uhr() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
tpZeit = new JTextPane();
tpZeit.setText("test");
tpZeit.setBounds(43, 50, 212, 43);
contentPane.add(tpZeit);
JButton btnstart = new JButton("GO");
btnstart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tpZeit.setText("started");
if (t == null) {
t = new Thread(new Uhrsteuerung());
}
if(!t.isAlive()) {
t = new Thread(new Uhrsteuerung());
t.start();
}
}
});
btnstart.setBounds(10, 227, 89, 23);
contentPane.add(btnstart);
JButton btnstop = new JButton("Stop");
btnstop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t.interrupt();
}
});
btnstop.setBounds(248, 227, 89, 23);
contentPane.add(btnstop);
}
}
Class with additional Thread:
public class Uhrsteuerung extends Uhr implements Runnable {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String time;
boolean x ;
#Override
public synchronized void run() {
// TODO Auto-generated method stub
x = true;
while (x) {
try {
time = sdf.format(System.currentTimeMillis());
System.out.println(time);
tpZeit.setText(time);
repaint();
Thread.sleep(1000);
} catch (InterruptedException ex) {
x = false;
}
}
}
}
All code for Java's Swing classes must be executed on the Event Dispatch Thread (EDT). Swing provides some special classes for helping you do this.
To execute code off the EDT, use a SwingWorker class. SwingWorker will execute a task in the background (not using the EDT) and then return a result properly synchronized that executes on the EDT. https://docs.oracle.com/en/java/javase/16/docs/api/java.desktop/javax/swing/SwingWorker.html
Its application is pretty simple. Define your own class that extends SwingWorker.
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
// ...
If you need to update a component, it's good to pass in the component so that you can refer to it later.
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
private JTextArea textArea;
public PrimeNumbersTask( JTextArea textArea ) {
this.textArea = textArea;
}
// ...
Do your work in the method doInBackground() by overriding it. Don't touch the Swing classes in this method. Use the publish() method to send smaller chunks of data to the EDT if you want to provide progressive results instead of waiting for the whole task to complete.
#Override
public List<Integer> doInBackground() {
while (!done && ! isCancelled()) {
// do stuff
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
}
return numbers;
}
Finally override the method process() to update your Swing classes.
#Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
From the EDT, you can call execute() to start your background task.
JTextArea textArea = new JTextArea();
// manipulate and set up GUI...
PrimeNumbersTask task = new PrimeNumbersTask(textArea);
task.execute();
There's a lot more docs on SwingWorker if you Google for it, that's the basics of how to use it.
I am trying to get the input from a JTextField and output it on the console using getText(). And it seems to be working except it doesn't print out the last character. If I typed Hello the output would be Hell, If I typed Hello there the output would be Hell ther .... missing the last character.
public class Generator {
private JFrame frame;
private JTextField textRoomName;
private String roomName;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Generator window = new Generator();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Generator() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.getContentPane().setBackground(Color.GRAY);
frame.setForeground(Color.BLACK);
frame.setBackground(Color.BLACK);
frame.setBounds(100, 100, 450, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
textRoomName = new JTextField();
textRoomName.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
roomName = textRoomName.getText();
}
});
textRoomName.setBounds(140, 52, 212, 20);
frame.getContentPane().add(textRoomName);
textRoomName.setColumns(10);
JButton btnGenerate = new JButton("Generate");
btnGenerate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(roomName);
}
});
btnGenerate.setBounds(324, 427, 89, 23);
frame.getContentPane().add(btnGenerate);
}
}
textRoomName.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
roomName = textRoomName.getText();
}
});
Don't use a KeyListener. The Document hasn't been updated with the text yet when the keyPressed event is generated.
Instead the better API to use is a DocumentListener.
Read the sections from the Swing tutorial on:
Listening For Changes on a Document and
How to Write a DocumentListener
for more information and examples.
I have an application I'm making for a game to automatically update a game client.
Once you press Launch, it will open up my DownloadFrame (extends JDialog), and will look like this:
If you click the icon for the application in the taskbar, (maybe Windows 8 is the problem?) it will minimize the application like usual. However when you go to maximise the application again, the JDialog will be hidden, I'm assuming, behind the parent. It looks like this:
Here's my code for my extension of JDialog. Apologies in advance for it being messy.
public class DownloadFrame extends JDialog implements Runnable {
private static final long serialVersionUID = -8764984599528942303L;
private Background frame;
private ImageIcon[] gifs;
private JLabel spinner;
public DownloadFrame() {
super(Loader.application, false);
setLayout(null);
setUndecorated(true);
setAutoRequestFocus(true);
new Thread(this).start();
generateBackground();
generateButton();
generateGif();
}
private void generateBackground() {
frame = new Background("sub_background.png");
setSize(frame.getWidth(), frame.getHeight());
setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));
setLocationRelativeTo(null);
setLocation(this.getX(), this.getY() + 5);
setLayout(null);
setContentPane(frame);
}
private void generateGif() {
gifs = Utils.generateGifImages();
spinner = new JLabel(gifs[0]);
spinner.setBounds(70, 30, gifs[0].getIconWidth(), gifs[0].getIconHeight());
add(spinner);
}
private HoverableButton cancel;
public HoverableButton getCancelButton() {
return cancel;
}
private void generateButton() {
cancel = new HoverableButton(Settings.CANCEL_BUTTON, 75, 145);
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
/*
* TODO -
* stop the download in progress
*/
for (HoverableButton button : Loader.application.getPrimaryButtons()) {
button.setActive(true);
button.setVisible(true);
}
dispose();
}
});
add(cancel);
}
private int cycleCount;
private void cycleGif() {
if (spinner == null) {
return;
}
cycleCount++;
if (cycleCount > 7) {
cycleCount = 0;
}
spinner.setIcon(gifs[cycleCount]);
}
#Override
public void run() {
while (true) {
cycleGif();
try {
Thread.sleep(100L);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
In case it's needed, here's my usage of it. Most of the stuff can be ignored I'm sure, it's simply there to hide the four buttons while the download is in progress.
((HoverableButton) components[2]).addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
HoverableButton source = (HoverableButton) components[2];
if (source.isActive()) {
try {
Thread.sleep(500L);
} catch (Exception ex) {
ex.printStackTrace();
}
if (panel == null) {
panel = new DownloadFrame();
panel.setVisible(true);
} else {
panel.setVisible(true);
panel.getCancelButton().removeHighlight();
}
for (HoverableButton button : getPrimaryButtons()) {
button.setActive(false);
button.setVisible(false);
button.removeHighlight();
}
/*
* TODO -
* handle checking for updates / downloading updates
*/
}
}
});
However when you go to maximise the application again, the JDialog will be hidden, I'm assuming, behind the parent
Yes. When you create the JDialog, you need to specify the "owner" JFrame of the dialog in the constructor.
So you must create and make the JFrame and make the frame visible before you create the dialog.
This might be a very simple thing that I'm overlooking, but I just can't seem to figure it out.
I have the following method that updates a JTable:
class TableModel extends AbstractTableModel {
public void updateTable() {
try {
// update table here
...
} catch (NullPointerException npe) {
isOpenDialog = true;
JOptionPane.showMessageDialog(null, "No active shares found on this IP!");
isOpenDialog = false;
}
}
}
However, I don't want isOpenDialog boolean to be set to false until the OK button on the message dialog is pressed, because if a user presses enter it will activate a KeyListener event on a textfield and it triggers that entire block of code again if it's set to false.
Part of the KeyListener code is shown below:
public class KeyReleased implements KeyListener {
...
#Override
public void keyReleased(KeyEvent ke) {
if(txtIPField.getText().matches(IPADDRESS_PATTERN)) {
validIP = true;
} else {
validIP = false;
}
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
if (validIP && !isOpenDialog) {
updateTable();
}
}
}
}
Does JOptionPane.showMessageDialog() have some sort of mechanism that prevents executing the next line until the OK button is pressed? Thank you.
The JOptionPane creates a modal dialog and so the line beyond it will by design not be called until the dialog has been dealt with (either one of the buttons have been pushed or the close menu button has been pressed).
More important, you shouldn't be using a KeyListener for this sort of thing. If you want to have a JTextField listen for press of the enter key, add an ActionListener to it.
An easy work around to suite your needs is the use of showConfirmDialog(...), over showMessageDialog(), this lets you take the input from the user and then proceed likewise. Do have a look at this example program, for clarification :-)
import javax.swing.*;
public class JOptionExample
{
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
int selection = JOptionPane.showConfirmDialog(
null
, "No active shares found on this IP!"
, "Selection : "
, JOptionPane.OK_CANCEL_OPTION
, JOptionPane.INFORMATION_MESSAGE);
System.out.println("I be written" +
" after you close, the JOptionPane");
if (selection == JOptionPane.OK_OPTION)
{
// Code to use when OK is PRESSED.
System.out.println("Selected Option is OK : " + selection);
}
else if (selection == JOptionPane.CANCEL_OPTION)
{
// Code to use when CANCEL is PRESSED.
System.out.println("Selected Option Is CANCEL : " + selection);
}
}
});
}
}
You can get acces to the OK button if you create optionpanel and custom dialog. Here's an example of this kind of implementation:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author OZBORN
*/
public class TestyDialog {
static JFrame okno;
static JPanel panel;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
zrobOkno();
JButton przycisk =new JButton("Dialog");
przycisk.setSize(200,200);
panel.add(przycisk,BorderLayout.CENTER);
panel.setCursor(null);
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
przycisk.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(
cursorImg, new Point(0, 0), "blank cursor"));
final JOptionPane optionPane = new JOptionPane(
"U can close this dialog\n"
+ "by pressing ok button, close frame button or by clicking outside of the dialog box.\n"
+"Every time there will be action defined in the windowLostFocus function"
+ "Do you understand?",
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION);
System.out.println(optionPane.getComponentCount());
przycisk.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
final JFrame aa=new JFrame();
final JDialog dialog = new JDialog(aa,"Click a button",false);
((JButton)((JPanel)optionPane.getComponents()[1]).getComponent(0)).addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
aa.dispose();
}
});
dialog.setContentPane(optionPane);
dialog.pack();
dialog.addWindowFocusListener(new WindowFocusListener() {
#Override
public void windowLostFocus(WindowEvent e) {
System.out.println("Zamykam");
aa.dispose();
}
#Override public void windowGainedFocus(WindowEvent e) {}
});
dialog.setVisible(true);
}
});
}
public static void zrobOkno(){
okno=new JFrame("Testy okno");
okno.setLocationRelativeTo(null);
okno.setSize(200,200);
okno.setPreferredSize(new Dimension(200,200));
okno.setVisible(true);
okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel=new JPanel();
panel.setPreferredSize(new Dimension(200,200));
panel.setLayout(new BorderLayout());
okno.add(panel);
}
}
Try this,
catch(NullPointerException ex){
Thread t = new Thread(new Runnable(){
public void run(){
isOpenDialog = true;
JOptionPane.setMessageDialog(Title,Content);
}
});
t.start();
t.join(); // Join will make the thread wait for t to finish its run method, before
executing the below lines
isOpenDialog = false;
}