Activate JTextArea on program launch? - java

Is it possible to make a JTextArea in a way that when the user starts to type when the program is launched it's it automatically starts to type in that JTextArea. Normally the the user first has to click on the JTextArea to start to type in it?
Can I make it that the user does not have to click a JTextArea to start typing it?
EDIT: I've tried using:
textField.requestFocusInWindow();
inside my frame class but that doesn't work.

This called to gain focus and is configurable with your code. There are some samples which use Listeners to change JTextArea at the proper time.
Method .requestFocusInWindow(); might fix your problem in the code bellow:
tabbedPane.addChangeListener(e -> {
Component comp = tabbedPane.getSelectedComponent();
if (comp.equals(pnlFoo)) {
txtFoo.requestFocusInWindow();
} else if (comp.equals(pnlBar)) {
txtBar.requestFocusInWindow();
}
});
Similar issue : Java - how do I gain focus on JTextArea when selecting a new JTabbedPane
This could help for your first run :
frame.addWindowFocusListener(new WindowAdapter() {
public void windowGainedFocus(WindowEvent e) {
textArea_1.requestFocusInWindow();

Related

Java: How to wait for the listener to execute the next line?

I have a problem because I have the next code in my main class:
SelectCalculatorWindow selectCalculatorWindow = new SelectCalculatorWindow();
CalcWindow calcWindow;
if (selectCalculatorWindow.getOption() == SelectCalculatorWindow.BASIC_OPTION) {
calcWindow = new CalcWindow(0);
} else if (selectCalculatorWindow.getOption() == SelectCalculatorWindow.PSEUDOSCIENTIFIC_OPTION) {
calcWindow = new CalcWindow(1);
}
And, in other class (SelectCalculatorWindow), I have this:
public SelectCalculatorWindow() {
initComponents();
instantiateListener();
}
private void instantiateListener() {
acceptBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(basicCalculatorRbtn.isSelected()) {
setOption(BASIC_OPTION);
} else if (pseudoscientificCalculatorRbtn.isSelected()) {
setOption(PSEUDOSCIENTIFIC_OPTION);
}
setVisible(false);
}
});
}
So, I want that condition sentences that I wrote in the main class execute only if user click the button, and I don't know how to do it
You haven't posted a valid minimal reproducible example program yet, and so I can only guess, but having said that, my guess is that SelectCalculatorWindow creates and displays a JFrame which is a non-modal application window, which is not what you want. Instead you will want to display a modal child-window, or dialog, such as a modal JDialog. When you use this, it pauses application code flow in the calling code until the dialog has been dealt with, and so allows your program to pause waiting for the user to make their selection, and then resume the code once the selection has been made.
A JOptionPane is an example of a type of modal dialog, but using a JDialog, you can create windows as varied and flexible as a JFrame, but with the advantages noted above.

Not sure where to put logic loop [java]

I'm currently trying to build a small program for school. If you click on a checkbox it should show other elements. I learned in python that you need a while loop because the program needs to go over the same lines again where you check if the box is checked but if i put a loop the whole program won't start. I don't understand why.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test extends JFrame {
private JCheckBox moredetailscheck;
private JTextField inputfielduser;
public static void main(String[] args) {
test venster = new test();
venster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
venster.setSize(800, 600);
venster.setVisible(true);
venster.setTitle("true");
venster.setResizable(false);
}
public test() {
setLayout(new FlowLayout());
moredetailscheck = new JCheckBox("checkbox", false);
add(moredetailscheck);
inputfielduser = new JTextField(15);
while(true) { // you want to let the program keep going over these lines
if(moredetailscheck.isSelected()) {
add(inputfielduser);
}
}
}
If you click on a checkbox it should show other elements.
So, you would attach a listener to the JCheckBox, here an ItemListener, that responds when the state of the JCheckBox changes.
I learned in python that you need a while loop because the program needs to go over the same lines again where you check if the box is checked
This is called "polling" and is needed for linear console programs where you need to continually obtain input from the user, again in a "linear" fashion. In these types of programs, you the programmer are in complete control over program code flow, but that's not what you want here.
but if i put a loop the whole program won't start. I don't understand why.
That's because you're now using an event-driven GUI library, there the Swing library, and by calling a while (true) loop on the event thread, you completely block it, rendering your GUI useless. Your program is starting, but it can't construct the GUI, draw itself or listen for events.
Solution:
Get rid of the while (true) loop. Again, it is useful for simple console programs but not in this situation.
Add an ItemListener to your JCheckBox. You can find out how to do that in the check box tutorial
Don't keep adding items to your GUI. Use a CardLayout to swap views. The tutorial can be found here: CardLayout tutorial.
Or even better, have all the GUI items on the GUI at startup, but use the JCheckBox state to enable/disable an item.
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
For example:
import java.awt.event.ItemEvent;
import javax.swing.*;
public class TestCheckBox extends JPanel {
private static final long serialVersionUID = 1L;
private JCheckBox moreDetailsCheck = new JCheckBox("More Details", false);
private JTextField inputFieldUser = new JTextField(15);
public TestCheckBox() {
inputFieldUser.setEnabled(false);
add(moreDetailsCheck);
add(inputFieldUser);
// add a listener to the JCheckBox
moreDetailsCheck.addItemListener(e -> {
// if checkbox selected, enable the text field. else disable it
inputFieldUser.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
});
}
private static void createAndShowGui() {
TestCheckBox mainPanel = new TestCheckBox();
JFrame frame = new JFrame("Test CheckBox");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
In Java, the AWT starts a thread to handle events automatically; you just let main finish and the program keeps running anyway until you call System.exit. You do need event handlers, though, for which any number of tutorials exist.
(Incidentally, your infinite loop comes before even showing your JFrame.)

Prevent breaking of JTextField / JDialog with repeated transferFocus()

I have a very strange scenario which unfortunately I cannot prevent from occurring in my Swing application. When it occurs however, it has major consequences for me. Perhaps somebody could help!
The basic setup is as follows:
Linux environment.
Multiple JTextFields in a JFrame.
JTextFields push through transferFocus() when the Enter key is pressed.
A JDialog pops up on leaving one of the fields which requires the Enter key to be pressed to remove it.
The situation that causes the issue is as follows:
The Enter key is held down for a few seconds.
When the enter key is held down, the focus obviously flies through the different text fields. When the dialog box is shown, the enter key closes it causing the focus to then continue to fly through the text fields. Eventually, within a couple of seconds, Java breaks. The textboxes immediately stop responding to key strokes - you cannot type anything in them at all. Other than that, everything seems normal - you can click around and focus on different textboxes, close the application etc.
I have created a simple test case you can use to recreate the situation.
The JFrame:
public class TestSwing extends JFrame {
JTextField jtfText1, jtfText2, jtfText3;
TextHandler handler = null;
public TestSwing() {
super("TextField Test Demo");
Container container = getContentPane();
container.setLayout(new FlowLayout());
jtfText1 = new MyJTextField(10);
jtfText2 = new MyJTextField(10);
jtfText3 = new MyJTextField(10);
container.add(jtfText1);
container.add(jtfText2);
container.add(jtfText3);
handler = new TextHandler();
jtfText3.addActionListener(handler);
setSize(325, 100);
setVisible(true);
}
private class TextHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(null, "wait!");
}
}
public static void main(String args[]) {
TestSwing test = new TestSwing();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
The custom JTextField:
public class MyJTextField extends JTextField {
public MyJTextField(int len) {
super(len);
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
int key = evt.getKeyCode();
if (key == KeyEvent.VK_ENTER)
transferFocus();
}
});
}
}
To answer any potential questions up front:
The Enter key must be used to transfer the focus.
The spamming of the Enter key comes from the user leaving something on the keyboard (this is in the retail environment so this happens often).
Simply closing and restarting the application is not really an option as there is no mouse plugged into the computer. The application is booted up automatically on start-up making this scenario devastating as the only way to fix the problem is to restart the machine.
The machines aren't very powerful (processing & memory) which somehow causes the issue to happen a lot quicker than when it's recreated on a development machine.
Is this a bug in Java? Can anyone think of a way to prevent this from happening?
The closest I can get to preventing this from happening is to put a sleep(500) call in the JDialog (mine is extended) before it closes but that's not really a great fix...
I have tested this in JDK 1.6, 1.7 and 1.8. While it takes a bit longer in the later versions for the textboxes to become unresponsive, it still happens eventually.
Thanks in advance!
Xandel
Don't use KeyEvents. KeyEvents are generally used in AWT. Swing has newer and better API's to use (in most cases). In this case a JTextField was designed to respond to an ActionEvent when the Enter key is pressed.
You could try to keep track of the last time Enter was pressed and ignore events that seem to be invoked within the repeat rate of the OS. My repeat rate appears to be around 35ms:
import java.awt.event.*;
import javax.swing.*;
public class MyJTextField extends JTextField
{
private static long lastTime = System.currentTimeMillis();
public MyJTextField(int len)
{
super(len);
addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
long diff = evt.getWhen() - lastTime;
System.out.println(diff);
if (diff > 50)
{
transferFocus();
}
lastTime = evt.getWhen();
}
});
}
}

return a variable value to main on button click

I want that main should print hello (in a pop up dialogue box) everytime the button is clicked. So I designed the following program but it doesn't seem to work. The program compiles and executes just fine but when I click the button, I don't see the any dialogue box popping up. I have put in place the getter and setter of the boolean variable (button_clicked) whose value is being tested in the main() block.
Please help if you know..
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class abc extends JFrame implements ActionListener{
boolean button_clicked = false;
JButton b1;
abc(){
this.setSize (400, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.createUI();
}
void createUI(){
this.setLayout(null);
b1 = new JButton("x");
b1.setSize(110,30);
b1.setLocation(10,210);
this.add(b1);
b1.addActionListener(this);
}
public boolean isButton_clicked() {
return button_clicked;
}
public void setButton_clicked(boolean button_clicked) {
this.button_clicked = button_clicked;
}
public void actionPerformed(ActionEvent arg0) {
button_clicked = true;
//I don't want to print the dialogue box from here..
//I want to keep everything under main()'s control.
}
}
public class tempMain extends JFrame {
public static void main(String[] args) {
abc temp = new abc();
temp.setVisible(true);
while(true){
if(temp.isButton_clicked())
JOptionPane.showMessageDialog(null, "Hello");
}
}
}
Move the JOptionPane.showMessageDialog() call under the actionPerformed() method and delete the while() thing under the main method.
As has already been pointed out by a number of people, you approach and design are flawed. I won't go into further as it has already been dealt with, but as a suggestion you could try...
abc temp = new abc();
temp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
JOptionPane.showMessageDialog(null, "Look Ma, I'm in Main...");
}
});
temp.setVisible(true);
And in your abc class...
class abc JFrame implements {
// build your class as normal
public void addActionListener(ActionListener listener) {
b1.addActionListener(listener);
}
}
You might want to read about "How to Write an Action Listener" to help you implement an ActionListner in your code.
The basic idea for your code would be to:
Declare an event handler class
Register an instance of the event handler class as a listener with your JButton
Include code that implements the methods in listener interface. In your case, you would over-ride actionPerformed() and write your logic over there to show a dialog box. "How to Make Dialogs" would be another useful tutorial for you.
As #Quinman pointed out, your code design is really flawed. I understand that you do not want to put the JOptionPane under the actionperformed method for some personal reason which I don't understand. Based on that premise, I think that the best solution would be to create a callback, that is, make your JFrame know the main class and call it when the button is clicked.
It is possible to make this mechanism independent of the main class. Please check the Observer design pattern in order to understand how to do that.
Your code also has another flaw - when the button is clicked I get infinite Hello messages. In order to avoid that, you should set the button_clicked variable to false. I only mention that as a general tip, for in truth you really should get rid of the busy wait that your while is causing.
You may be looking for a modeless dialog. In this example, the main panel, named Observer, listens to an ObservedPanel in a dialog. By using a PropertyChangeListener, any changes made to the dialog are immediately reflected in the main panel.
Judging from the comments you provided, you want to reuse your abc class (which has a very poor name and does not comply to the Java naming standards) for several different purposes, so you do not want to include the code which is executed when you press the button in the abc class.
There are multiple solutions for this (where the first is my preferred one)
Pass an Action in the constructor of your abc class and couple that Action to the JButton. This way the class which constructs the abc instance is responsible for the behavior when the button is pressed
make abc abstract and let your ActionListener call that abstract method. You can then make concrete implementations of this class each time you want different behavior.
Further notes on your code:
get rid of that while( true ) loop
get rid of the null layout and use a LayoutManager instead
Swing components should be created and accessed on the Event Dispatch Thread. Consult the Concurrency in Swing tutorial for more information

Attach to Window events from JPanel

I'm trying to listen for a window close event on the parent JFrame of a JPanel. In the WindowClosing event I'd like to de-register a listener to a different component.
Unfortunately the only code I can gaurantee to have run is the constructor for the panel. What this means is that the panel itself doesn't have an ancestor window yet, so simply calling SwingUtilities.getWindowAncestor doesn't work. So what I do is register a hierarchy listener, and in the hierarchyChanged event look for SHOWING_CHANGED event. When that even fires, now I can look for the window ancestor of the panel.
So basically I have the following:
class ShapeControlPanel extends JPanel{
public ShapeControlPanel(){
final ShapeControlPanel me = this;
me.addHierarchyListener(new HierarchyListener() {
#Override
public void hierarchyChanged(HierarchyEvent e) {
if((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) == HierarchyEvent.SHOWING_CHANGED){
SwingUtilities.getWindowAncestor(me).addWindowListener(new WindowListener() {
/* Snipped some empty handlers */
#Override
public void windowClosing(WindowEvent e) {
/* Finally get to remove the handler. */
me.getApparent().removeLocationSelectionListener(me.GUID(), me);
}
});
}
}
});
}
}
Is this sane? Is there a more reasonable way of getting a handle on the frame closing event?
It's not the ugliest thing I've seen (I wouldn't even say it's all that bad), but you have to ask yourself: why does your panel really need to know when the window is closed? It seems to be an odd coupling that would best be removed.
I don't know enough about your context and what you are truly trying to accomplish to suggest an alternative right now. But if a panel needs to know about the container in which it resides, there is probably some bad design with harmful coupling.

Categories