import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
class Demo implements ActionListener
{
JFrame f;
JButton b;
DisplayDialog dialog;
public Demo()
{
f = new JFrame();
f.setSize(200,200);
b = new JButton("Click me");
f.add(b);
dialog = new DisplayDialog();
b.addActionListener(this);
f.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
Object o = e.getSource();
if(o==b)
{
dialog.display("Hello");
dialog.display("Hello");
dialog.display("Hello");
dialog.display("Hello");
dialog.display("Hello");
}
}
public static void main(String args[])
{
Demo d = new Demo();
}
class DisplayDialog implements ActionListener
{
JDialog dg;
JLabel l;
JButton b;
Font myfont;
public DisplayDialog()
{
dg = new JDialog(f,"Alert!",true);
dg.setSize(300,150);
l = new JLabel("Message");
b = new JButton("OK");
myfont = new Font("Serif",Font.BOLD,12);
l.setFont(myfont);
dg.add(l);
dg.add(b,"South");
dg.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
Object o = e.getSource();
if(o==b)
{
dg.setVisible(false);
}
}
public void display(String str)
{
if(dg.isVisible())
dg.setVisible(false);
l.setText(str);
dg.setVisible(true);
}
}
}
When the button is clicked, 5 Dialog box appears. Now I want to make such a change in the DisplayDialog class so that every time display method is called,the previously opened dialogs are closed and the latest one is the only one that is visible.
I tried doing this :
public void display(String str)
{
if(dg.isVisible())
dg.setVisible(false);
l.setText(str);
dg.setVisible(true);
}
but it didn't do anything.
Also,I am very surprised that multiple dialog boxes are appearing even though there is only one instance of the object. From my understanding, setVisible(true) should not do anything if the dialog is already visible.
This whole situation is very confusing to me.
The thing is that you cannot do this in single thread (like you are preseting it in your demo) - setVisible will always block (wait till dialog closes) and another display call will not be invoked till then.
Try to run it in multi frame env (like you have stated that your app is) but change display to
public void display(String str){
l.setText(str);
if(dg.isVisible()){
dg.setVisible(true);
}
}
This way dialog will not be displayed if it is already visible, but text will be changed. The condition for it to work is that is is not consecutinve calls to display like in demo, but from different threads. There is no other way around. setVisible will alwys block.
Related
Hello I have a class that opens a JFrame and takes in a text. But when I try getting the text it says its null.
Everytime I click the button I want the System.out to print the text I entered in the textArea.
This is my first class :
public class FileReader {
FileBrowser x = new FileBrowser();
private String filePath = x.filePath;
public String getFilePath(){
return this.filePath;
}
public static void main(String[] args) {
FileReader x = new FileReader();
if(x.getFilePath() == null){
System.out.println("String is null.");
}
else
{
System.out.println(x.getFilePath());
}
}
}
This is a JFrame that takes in the input and stores it in a static String.
/*
* This class is used to read the location
* of the file that the user.
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.event.*;
import javax.swing.*;
public class FileBrowser extends JFrame{
private JTextArea textArea;
private JButton button;
public static String filePath;
public FileBrowser(){
super("Enter file path to add");
setLayout(new BorderLayout());
this.textArea = new JTextArea();
this.button = new JButton("Add file");
add(this.textArea, BorderLayout.CENTER);
add(this.button, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
setVisible(true);
this.button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
filePath = new String(textArea.getText());
System.exit(0);
}
});
}
}
But everytime I run these programs I get
String is null.
You are mistaken by the way how JFrames work. A JFrame does not stall the execution of the code until it is closed. So, basically, your code creates a JFrame and then grabs the filePath variable in that object, before the user could have possibly specified a file.
So, to solve this, move the code that outputs the filepath to stdout to the ActionListener you have. Get rid of the System.exit() call, and use dispose() instead.
Update: You should have this code for the ActionListener:
this.button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
filePath = new String(textArea.getText());
if(filePath == null){
System.out.println("String is null.");
}
else
{
System.out.println(filePath);
}
dispose();
}
});
And as main method:
public static void main(String[] args)
{
FileBrowser x = new FileBrowser();
}
Your main does not wait until the user has specified a text in the textArea. You could prevent this behaviour by looping until the text in the textArea is set or you could place the logic of the main function into the ActionListener to handle the event.
Following the second way the main function only creates a new FileBrowser object.
sorry to bother everyone.
Overall problem: I'm trying to open a dialogue box let the user enter something then close it
Issue: - A function is not being called (i think)
- The main problem is when i use debug it works fine so Its difficult for me to track down the problem
I'm having trouble with JButtons,
it works in debug but not in normal run. this was probably because i was using an infinite loop. someone online suggested i used SwingUtilities but that didn't work (at least i don't think.
/**
*
* #author Deep_Net_Backup
*/
public class butonTest extends JFrame {
String name;
boolean hasValue;
//name things
private JLabel m_nameLabel;
private JTextField m_name;
//panel
private JPanel pane;
//button
private JButton m_submit;
//action listener for the button submit
class submitListen implements ActionListener {
public void actionPerformed(ActionEvent e) {
submit();
System.out.println("Test");
}
}
//constructor
public butonTest(){
//normal values
name = null;
hasValue = false;
//create the defauts
m_nameLabel = new JLabel("Name:");
m_name = new JTextField(25);
pane = new JPanel();
m_submit = new JButton("Submit");
m_submit.addActionListener(new submitListen());
//
setTitle("Create Cat");
setSize(300,200);
setResizable(false);
//add components
pane.add(m_nameLabel);
pane.add(m_name);
pane.add(m_submit);
add(pane);
//last things
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
//submit
private void submit()
{
System.out.println("submit");
name = m_name.getText();
hasValue = true;
}
//hasValue
public boolean hasValue()
{
return(hasValue);
}
//get the text name
public String getName()
{
return(name);
}
public void close()
{
setVisible(false);
dispose();
}
public static void main(String[] args)
{
/* Test 1
boolean run = true;
String ret = new String();
butonTest lol = new butonTest();
while(run)
{
if(lol.hasValue())
{
System.out.println("Done");
run = false;
ret = new String(lol.getName());
lol.close();
}
}
System.out.println(ret);*/
//Tset 2
/*
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
butonTest lol = new butonTest();
if(lol.hasValue())
{
System.out.println(lol.getName());
}
}
});*/
}
}
Edit:
How its not working: When i run Test the program will print test and submit then it should change the hasValue to true. this will (hopefully) allow the if statement to run to print done. This does not happen.
Edit 2:
I have just added a few more lines for further testing 2 prints and this seems to have solved the issue (but this is bad)
System.out.println("hasValue " + hasValue); -> to the hasValue() function
System.out.println("set to true"); -> submit() function
You are doing something far too complicated than is necessary. Instead of having the listener as a seperate class, you could have it as an anonymous class. That way you can get a handle on the outer class (butonTest.this), and call any method you want on it.
m_submit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
submit();
System.out.println("Test");
butonTest.this.close();
}
});
I'm not sure what you are trying to do with the infinite loop. It would have run to completion before you show the dialog anyway.
It would help to read up a bit on how Event-Handling works in Swing :)
I am afraid your constructor butonTest() and submit() method are out of your
class (public class butonTest extends JFrame).
you need to get them inside your class:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class JDorm implements ItemListener{
public static void main(String[] args){
JCheckBox privateroom = new JCheckBox("Private Room",false);
JCheckBox interweb = new JCheckBox("Internet Connection",false);
JCheckBox cable = new JCheckBox("Cable TV connection",false);
JCheckBox fridg = new JCheckBox("Refridgerator",false);
JCheckBox microwave = new JCheckBox("Microwave",false);
JCheckBox soon = new JCheckBox(",and so on",false);
JLabel greet = new JLabel("Please choose ammenities");
String sel = "Your selected options";
JTextArea textBox = new JTextArea(sel,0,1);
cable.addItemListener();
JFrame dormFrame = new JFrame("Dorm Options");// creates frame with title
final int WIDTH = 250;
final int HEIGHT = 500;
dormFrame.setSize(WIDTH, HEIGHT);// sets the size of frame in pixels
dormFrame.setVisible(true);// note: default visibility is false
dormFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dormFrame.setLayout(new FlowLayout());
dormFrame.add(greet);
dormFrame.add(microwave);
dormFrame.add(fridg);
dormFrame.add(cable);
dormFrame.add(interweb);
dormFrame.add(privateroom);
dormFrame.add(soon);
dormFrame.add(textBox);
}
public void itemStateChanged(ItemEvent event){
Object source = event.getSource();
int select = event.getStateChange();
}
}
This is what I have so far, I know I need listeners, and a message to appear in the box when selection is checked and unchecked.
Do I need if statements for the changes?
Create a generic listener that can be added to all the check boxes. Something like:
ItemListener listener = new ItemListener()
{
public void itemStateChanged(ItemEvent event)
{
JCheckBox checkBox = (JCheckBox)event.getSource();
textBox.setText( checkBox.getText() );
}
};
Then you add the listener to each check box:
privateRoom.addItemListener( listener );
interweb.addItemListener( listener );
I have tried for one Checkbox and you can do others similarly
final JCheckBox privateroom = new JCheckBox("Private Room",false);
Now add item listener to checkbox privateroom and also the actions which you would like to happen i.e.
privateroom.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent event)
{
if (event.getItemSelectable() == privateroom)
textBox.setText("Private Room");
}
});
The reason i have declared Checkbox privaterroom as final is because privaterroom is local and is being accessed from an inner class.
One more thing I don't know the way you have written your program is good or bad because I am also learning swing and am a newbie. But the way i write my program has the following structure
class MyClass extends JFrame implements LISTENER_NAME
{
// Components declared here
// constructor starts
public MyClass()
{
//Componenets instantiated
// add listeners to appropriate components
// setVisible(), setDefaultCloseOperation(),setSize() etc called
}
// listener interface methods here like
public void itemStateChanged(ItemEvent ie)
{
................
}
// main method
public static void main(String[] args)
{
new MyClass();
}
} // class over
This way I have never encountered the final keyword etc problems. I hope some expert will guide us.
I want to make an event which will be triggered after i make the selection to the JComboBox.
the problem I'm now facing is that when i added an ActionListener, it was triggered when the user clicked on the box but BEFORE he actually chose the new item, thus the action listener was activated all the time on the previous value which was selected in the box. what i want to do is simply changing the title of an JTextArea according to the selection.
I tried doing something like this:
jBox.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String alt = GetAlgoAreaTitleByChoice();
panel.remove(jArea);
currentBest = setArea("",alt);
currentBest.setBounds(50, 350, 1000, 290);
panel.add(jArea);
}
});
and the method inside:
private String GetArgsAreaTitleByChoice(){
String chi = jBox.getSelectedItem().toString();
if(chi.equals(generalChoice)){
return "Hello";
}
else if(chi.equals(algoChoice)){
return "World";
}
else if(chi.equals(argsChoice)){
return "Hello";
}
return null;
}
I've tried using the SELECTED events now like this:
public void itemStateChanged(ItemEvent e) {
JComboBox cb = (JComboBox)e.getSource();
// Get the affected item
String item = cb.getSelectedItem().toString();
if (e.getStateChange() == ItemEvent.SELECTED) {
panel.remove(jBox);
textArea = setArea("", item);
panel.add(jBox);
}
but it seems to remove the area from the panel without adding it back... why is this happening?
Here is a simple demonstration with a sample code :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Tester {
public Tester(){
JComboBox box = new JComboBox();
box.addItem("One");
box.addItem("Two");
box.addItem("Three");
box.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange()==ItemEvent.SELECTED){
e.getItem(); //Do what ever you want :))
}
}
});
JFrame frame = new JFrame();
frame.getContentPane().add(box);
frame.pack();
frame.setVisible(true);
}
public static void main(String [] args) {
Tester tester = new Tester();
}
}
For listening of events from JComboBox is better implements ItemListener, returns two events SELECTED/DESELECTED
EDIT
if you remove/add JComponent(s) on Runtime and in already visible container, then you have to call (as least code lines)
revalidate();
repaint();
I am working on an assignment, and I need to enter an SQL Query in a textfield. The user can either press the custom 'execute query' button, or they can press the enter key. When either of these are used, it is to trigger an ActionListener (no other listener is allowed). Is it as simple as writing:
if (e.getSource()=='querybutton' || e.getSource=='enter')
Or is there more to it than this?
As I said, it is a simple question (I know).
edit:
I would write this bit in my ActionPerformed as:
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==gui.executeQueryButton || e.getSource()==gui.enter)
{
String query = gui.queryText.getText();
//more code to follow
}
}
e.getSource() actually returns the object responsible for firing the event (not the name of the variable you used when creating the control). In this case, your button. You could in principle compare e.getSource() with the actual button instances. However, are you actually adding this action listener to buttons other than those two? Presumably you'd only have to add this listener to the two buttons for which you want this behavior -- in which case you wouldn't have to have this if check.
" Is it as simple as writing:
if (e.getSource()=='querybutton' || e.getSource=='enter')"
It's not simple to write this, but rather it is wrong to write it.
For one you don't want to compare Strings with ==, for another, you don't declare Strings with single quotes, and for a third, the enter key is not obtained in this way, but rather by adding the appropriate ActionListener object to the JTextField itself, and finally there should be in a single ActionListener class that handles this action, so the if block is completely unnecessary. This can probably be best done with a small inner private ActionListener class. You'd then create one object of this class and add it as an ActionListener for the querybutton and for the JTextField.
edit 1:
A more complete example of what I mean is shown below, a demo class that has a private inner handler class:
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerEg extends JPanel {
private JButton queryButton = new JButton("Query");
private JTextField textField = new JTextField("hello", 20);
public ActionListenerEg() {
QueryListener qListener = new QueryListener();
queryButton.addActionListener(qListener);
textField.addActionListener(qListener);
add(queryButton);
add(textField);
}
private class QueryListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
String textInField = textField.getText();
System.out.println("Use text in field, \"" + textInField + "\" to call SQL query in a background SwingWorker thread.");
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("ActionListenerEg");
frame.getContentPane().add(new ActionListenerEg());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
The ActionListener is fired either by pressing the button or by pressing enter from within the JTextField. I'd then have in my control class, code that is called inside of the actinoPerformed method.
edit 2: Having most handler or "control" code in its own Handler or Control class can be a good idea, but it doesn't have to implement ActionListener interface itself, but rather just have the code that will be called from within the ActionListener codes. For example, here I try to put all the handler code in its own class. It will have different methods that are called for various situations. e.g.,
import java.awt.Component;
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerEg extends JPanel {
private ActionListenerHandler handler;
private JButton queryButton = new JButton("Query");
private JButton displayButton = new JButton("Display");
private JTextField textField = new JTextField("hello", 20);
// pass in handler or handler
public ActionListenerEg(final ActionListenerHandler handler) {
this.handler = handler;
QueryListener qListener = new QueryListener();
queryButton.addActionListener(qListener);
textField.addActionListener(qListener);
displayButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (handler != null) {
handler.displayActionPerformed(e);
}
}
});
add(queryButton);
add(textField);
add(displayButton);
}
private class QueryListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (handler != null) {
String textInField = textField.getText();
handler.doQueryAction(e, textInField);
}
}
}
private static void createAndShowUI() {
ActionListenerHandler handler = new ActionListenerHandler();
JFrame frame = new JFrame("ActionListenerEg");
frame.getContentPane().add(new ActionListenerEg(handler));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class ActionListenerHandler {
public void displayActionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog((Component) e.getSource(), "Display things!");
}
public void doQueryAction(ActionEvent e, String textInField) {
String text = "We will use \"" + textInField + "\" to help create and run the SQL Query";
JOptionPane.showMessageDialog((Component) e.getSource(), text);
}
}
Please ask questions if it's clear as mudd, or if anything is wrong.