I am currently studying Java to improve myself. I have a program which has a main window, menu and submenus.
I have other windows on when I click on my submenus.
One of them is setRates which is
public SetMyRates(){
JPanel dataPanel = new JPanel(new GridLayout(2, 2, 12, 6));
dataPanel.add(setTLLabel);
dataPanel.add(setDollarsLabel);
dataPanel.add(setTLField);
dataPanel.add(setDollarsField);
JPanel buttonPanel = new JPanel();
buttonPanel.add(closeButton);
buttonPanel.add(setTLButton);
buttonPanel.add(setDollarsButton);
Container container = this.getContentPane();
container.add(dataPanel, BorderLayout.CENTER);
container.add(buttonPanel, BorderLayout.SOUTH);
setTLButton.addActionListener(new SetTL());
setDollarsButton.addActionListener(new SetDollars());
closeButton.addActionListener(new closeFrame());
dataPanel.setVisible(true);
pack();
}
and I want that window to close when I click on my closeButton.
I made a class for closeButton, actionListener which is:
private class closeFrame implements ActionListener{
public void actionPerformed(ActionEvent e){
try{
dispose();
}
catch(Exception ex){
JOptionPane.showMessageDialog(null, "Please enter correct Rate.");
}
}
}
But when I click that button, it closes my main window instead of my submenus window. What should I exactly do to fix the problem?
You need to get a reference to the Window that you want to close and call dispose() directly on that reference. How you do this will depend on the details of your program -- information that we're currently not privy to.
Edit: one way to get that reference is via SwingUtilities.getWindowAncestor(...). Pass in the JButton reference returned from your ActionEvent object and call dispose on it. Something like...
public void actionPerformed(ActionEvent e) {
Object o = e.getSource();
if (o instanceof JComponent) {
JComponent component = (JComponent)o;
Window win = SwingUtilities.getWindowAncestor(component);
win.dispose();
}
}
caveat: code neither compiled nor run nor tested in any way.
Also note that for this to work, the component that holds and activates the ActionListener has to reside on the Window that you wish to close, else this won't work.
From what I think you could easily when opening an another window just store a reference to it and use it inside the action listener. Something along these lines:
JFrame openedWindow;
//inside the listener
if(openedWindow)
openedWindow.dispose();
else dispose();
Related
Good afternoon!
I have this code:
private static class ClickListener implements ActionListener {
public ClickListener() {
}
#Override
public void actionPerformed(ActionEvent e) {
JFrame frame = new JFrame();
JLabel label = new JLabel("Opção Indisponivel");
JPanel panel = new JPanel();
frame.add(label, BorderLayout.CENTER);
frame.setSize(300, 400);
JButton button = new JButton("Voltar");
button.addActionListener(new CloseWindowListener());
panel.add(button);
frame.add(panel, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
private static class CloseWindowListener implements ActionListener {
public CloseWindowListener() {
}
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
}
What I want to do is when i click on the button "voltar" (which is in another window, not on the "main" one as you can see) it closes the windows but not the app itselft. The setVisible line gives me an error about that it cannot be referenced by a static context which I understand because I need the reference of the frame. How do I solve this?
EDIT: Changed JFrame to JDialog but still no sucess. Both windows are shutdown.
Thanks in advance,
Diogo Santos
The setVisible line gives me an error about that it cannot be referenced by a static context which I understand because I need the reference of the frame. How do I solve this?
You can access the component that generated the event. Then you can find the window the component belongs to. This will give you generic code to hide any window:
//setVisible(false);
JButton button = (JButton)e.getSource();
Window window = SwingUtilities.windowForComponent(button);
window.setVisible(false);
You can also check out Closing an Application. The ExitAction can be added to your button. Now when you click the button it will be like clicking the "x" (close) button of the window. That is whatever default close operation your specify for the window will be invoked.
This question already has answers here:
The Use of Multiple JFrames: Good or Bad Practice? [closed]
(9 answers)
Closed 7 years ago.
My aim is for an action listener to close a specific JFrame when the user hits the JButton to quit.
Overall, when the program starts a large JFrame opens then a small one in front....in my code the user enters some details in this small one and hits submit(for the sake of simplicity, ive omitted this code here and replaced submit with quit)
So when this quit buttons pressed. I expect this small JFrame to close. I can't seem to figure this out. The action listeners in a different class and ive tried making instances and had no luck. I've commented out the code I've tried below when attempting to solve this issue.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test
{
public static void main(String Args[])
{
makeGUI m = new makeGUI();
}
}
class makeGUI
{
JButton close = new JButton("CLOSE ME");
makeGUI()
{
frame f1 = new frame();
JFrame smallframe = new JFrame(); //want to close this one
JPanel jp = new JPanel(new FlowLayout());
smallframe.setSize(300,300);
smallframe.setLocationRelativeTo(null);
smallframe.setDefaultCloseOperation(smallframe.DISPOSE_ON_CLOSE);
close.addActionListener(new action());
jp.add(close);
smallframe.add(jp);
smallframe.setVisible(true);
}
class action implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//makeGUI s1 = new makeGUI();
if (e.getSource () == close)
{
//s1.smallframe.dispose();
System.out.println("gotcha");
}
}
}
}
class frame extends JFrame
{
frame ()
{
setExtendedState(JFrame.MAXIMIZED_BOTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("big one");
setVisible(true);
}
}
First, it's not a good practice to name classes with a lowercase, so try renaming to something like MakeGUI instead of makeGUI.
The problem with your commented code is that it creates a new instance of makeGUI every time the button is clicked and the action listener is invoked. The result is that when you click on the close button, a new frame is created, then an inner one and this inner one gets immediately closed. The only thing you'd be doing is creating more and more frames. You should keep the instance as a state, for instance as a class member:
class MakeGUI {
JFrame smallframe;
JButton close = new JButton("CLOSE ME");
MakeGUI() {
frame f1 = new frame();
smallframe = new JFrame(); //want to close this one
JPanel jp = new JPanel(new FlowLayout());
smallframe.setSize(300, 300);
smallframe.setLocationRelativeTo(null);
smallframe.setDefaultCloseOperation(smallframe.DISPOSE_ON_CLOSE);
close.addActionListener(new action());
jp.add(close);
smallframe.add(jp);
smallframe.setVisible(true);
}
class action implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == close) {
// use this instead of dispose
smallframe.dispatchEvent(new WindowEvent(smallframe, WindowEvent.WINDOW_CLOSING));
System.out.println("gotcha");
}
}
}
}
If you want to simulate someone pressing the [X] button then you can use this code to programmatically trigger this event:
smallFrame.dispatchEvent(new WindowEvent(smallFrame, WindowEvent.WINDOW_CLOSING));
Aside from that, your code is not working because you are not closing your instance of the small window, instead you are creating another instance and disposing of it. Inside your close event you should be closing the smallFrame instance.
You can do this by either passing your JFrame to the constructor of your ActionListener or making smallFrame a class variable.
It appears you are using the small JFrame as a pop up to get information or display information. If so, you may want to look into the JOptionPane class which is made for "Dialogue Boxes".
Documentation:
http://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html
I have two Jframes where frame1 has some text fields and when a button on frame1 is clicked, I open another JFrame which contains a search box and a JTable containing search results.
When I click on a result row on JTable, I want that particular values to be reflected in the frame1 text fields.
I tried passing the JFrame1's object as a parameter but I have no clear idea on how to achieve this.
Any help would be highly appreciated.
Thanks
First of all, your program design seems a bit off, as if you are using a JFrame for one of your windows where you should in fact be using a JDialog since it sounds as if one window should be dependent upon the other.
But regardless, you pass references of GUI objects the same as you would standard non-GUI Java code. If one window opens the other (the second often being the dialog), then the first window usually already holds a reference to the second window and can call methods off of it. The key often is when to have the first window call the second's methods to get its state. If the second is a modal dialog, then the when is easy -- immediately after the dialog returns which will be in the code immediately after you set the second dialog visible. If it is not a modal dialog, then you probably want to use a listener of some sort to know when to extract the information.
Having said this, the details will all depend on your program structure, and you'll need to tell us more about this if you want more specific help.
For a simple example that has one window open another, allows the user to enter text into the dialog windows JTextField, and then places the text in the first window's JTextField, please have a look at this:
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class WindowCommunication {
private static void createAndShowUI() {
JFrame frame = new JFrame("WindowCommunication");
frame.getContentPane().add(new MyFramePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
// let's be sure to start Swing on the Swing event thread
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class MyFramePanel extends JPanel {
private JTextField field = new JTextField(10);
private JButton openDialogeBtn = new JButton("Open Dialog");
// here my main gui has a reference to the JDialog and to the
// MyDialogPanel which is displayed in the JDialog
private MyDialogPanel dialogPanel = new MyDialogPanel();
private JDialog dialog;
public MyFramePanel() {
openDialogeBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openTableAction();
}
});
field.setEditable(false);
field.setFocusable(false);
add(field);
add(openDialogeBtn);
}
private void openTableAction() {
// lazy creation of the JDialog
if (dialog == null) {
Window win = SwingUtilities.getWindowAncestor(this);
if (win != null) {
dialog = new JDialog(win, "My Dialog",
ModalityType.APPLICATION_MODAL);
dialog.getContentPane().add(dialogPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
}
dialog.setVisible(true); // here the modal dialog takes over
// this line starts *after* the modal dialog has been disposed
// **** here's the key where I get the String from JTextField in the GUI held
// by the JDialog and put it into this GUI's JTextField.
field.setText(dialogPanel.getFieldText());
}
}
class MyDialogPanel extends JPanel {
private JTextField field = new JTextField(10);
private JButton okButton = new JButton("OK");
public MyDialogPanel() {
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
okButtonAction();
}
});
add(field);
add(okButton);
}
// to allow outside classes to get the text held by the JTextField
public String getFieldText() {
return field.getText();
}
// This button's action is simply to dispose of the JDialog.
private void okButtonAction() {
// win is here the JDialog that holds this JPanel, but it could be a JFrame or
// any other top-level container that is holding this JPanel
Window win = SwingUtilities.getWindowAncestor(this);
if (win != null) {
win.dispose();
}
}
}
You'd do a very similar technique to get information out of a JTable.
And again, if this information doesn't help you, then please tell us more about your program including showing us some of your code. The best code to show is a small compilable example, an SSCCE similar to what I've posted above.
In my program I have a main JFrame that holds a button. When this button is clicked a new JFrame appears in which I can change some information. Whenever I finish editing I press a save button on the new JFrame which saves the changes and disposes the JFrame. Now when this is done, I'd like to perform an action in the main JFrame as well, but only if something changed. If I open the new JFrame and just close it again without using the save button, I don't want to do anything in the main frame.
I've tried searching the web for a solution, but just don't seem to be anything useful out there..
An example of the code I've got so far:
Main Frame...
public class MainFrame extends JFrame
{
public MainFrame()
{
super("Main Frame");
JButton details = new JButton("Add Detail");
add(details);
details.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
new DetailFrame().setVisible(true);
}
});
}
}
Detail Frame...
public class DetailFrame extends JFrame
{
public DetailFrame()
{
super("Detail Frame");
JButton save = new JButton("Save");
add(save);
save.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
// Save whatever content
dispose();
}
});
}
}
So when I click the "Save" button on the Detail Frame, I want to do something in the Main Frame, whereas when the "x" is clicked on the Detail Frame, I don't want to do anything..
Hope someone is able to help me, and sorry for my english..
You can pass a MainFrame handle to the DetailFrame constructor. Then, on clicking the Save button, the DetailFrame would call a function in MainFrame and pass the changes to it.
Another way is to create a public boolean variable in DetailFrame and set it to true when the Save button is clicked. This way MainFrame will know whether the DetailFrame was closed or Save'd.
EDIT: Some more ideas:
Use JDialog instead of JFrame. JDialog.setVisible is modal, i.e. it will block the calling function until the dialog is closed; this way you can process the results of the dialog in the same "Details" button listener.
To access the dialog after it is called, store the dialog in a separate variable. First construct the dialog, then show it, and then process the result by analyzing its variables.
Store the results of editing in other public variables of DetailFrame (or let's call it DetailDialog). This should happen only when the "Save" button is clicked. This may even allow to go without the boolean variable (depends on the types of values you are editing).
DetailDialog dlg = new DetailDialog();
dlg.setVisible(true);
if(dlg.approvedResult != null) {
// process the result...
}
EDIT: Sorry, JDialog is not modal by default. Need to call a special super constructor to make it modal.
Also, here you will have to pass the reference to MainFrame to the dialog constructor, but you still can declare it as a simple JFrame and avoid unnecessary dependencies.
To get the reference to the enclosing MainFrame from within the anonymous ActionListener, use MainFrame.this.
To be able to change the button text after it was created, you will have to store the button in a member variable.
Main Frame...
public class MainFrame extends JFrame
{
private JButton details = new JButton("Add Detail");
public MainFrame()
{
super("Main Frame");
getContentPane().add(details);
details.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
DetailDialog dlg = new DetailDialog(MainFrame.this);
dlg.setVisible(true);
if(dlg.approved){
details.setText("Edit Detail");
}
}
});
}
}
Detail Dialog... (not Frame)
public class DetailDialog extends JDialog
{
public boolean approved = false;
public DetailDialog(JFrame parent)
{
super(parent,"Detail Dialog",true); // modal dialog parented to the calling frame
JButton save = new JButton("Save");
getContentPane().add(save);
save.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
// Save whatever content
approved = true;
dispose();
}
});
}
}
Create the detail frame in the main frame, and add a windowlistener to it, using the windowadapter class. Implement the windowclosing event by checking for changes, handle those, and then dispose the detail frame. This is all done in the mainframe.
The detail frame should have do nothing on close set to prevent the detail frame being disposed before you recorded the changes.
You may wish to implement checking for changes in the detailframe as a method returning a class holding the interesting data. That way your windowlistener can be small an to the point.
Forget the 2nd JFrame. use a modal dialog instead. It will block input until dismissed. Once dismissed, the only thing to do is decide whether to update the original data. JOptionPane has some inbuilt functionality that makes that easy. If the user presses Cancel or the esc key, the showInputDialog() method will return null as the result.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class EditInfo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
final JFrame f = new JFrame("Uneditable");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new BorderLayout(10,10));
final JTextField tf = new JTextField("Hello World!", 20);
tf.setEnabled(false);
p.add(tf, BorderLayout.CENTER);
JButton edit = new JButton("Edit");
edit.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
String result = JOptionPane.showInputDialog(
f,
"Edit text",
tf.getText());
if (result!=null) {
tf.setText(result);
}
}
} );
p.add(edit, BorderLayout.EAST);
p.setBorder(new EmptyBorder(10,10,10,10));
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
If it is necessary to edit a number of fields all at once in the JOptionPane, use a JPanel to contain them all, and put them in a showMessageDialog() call. Check the integer based return result to determine if the user OK'd the changes.
I have created a modal JDialog box with a custom drawing on it and a JButton. When I click the JButton, the JDialog box should close and a value should be returned.
I have created a function in the parent JFrame called setModalPiece, which receives a value and sets it to a local JFrame variable.
The problem is that this function is not visible from the JDialog box (even though the JDialog box has a reference to the parent JFrame).
Two questions:
1) Is there a better way to return a value from a JDialog box to its parent JFrame?
2) Why can't the reference to the JFrame passed to the JDialog be used to access my JFrame function setModalPiece?
I generally do it like this:
Dialog dlg = new Dialog(this, ...);
Value result = dlg.showDialog();
The Dialog.showDialog() function looks like this:
ReturnValue showDialog() {
setVisible(true);
return result;
}
Since setting visibility to true on a JDialog is a modal operation, the OK button can set an instance variable (result) to the chosen result of the dialog (or null if canceled). After processing in the OK/Cancel button method, do this:
setVisible(false);
dispose();
to return control to the showDialog() function.
You should do the opposite by adding a custom method getValue() to your custom JDialog.
In this way you can ask the value of the dialog from the JFrame instead that setting it by invoking something on the JFrame itself.
If you take a look at Oracle tutorial about dialogs here it states
If you're designing a custom dialog, you need to design your dialog's API so that you can query the dialog about what the user chose. For example, CustomDialog has a getValidatedText method that returns the text the user entered.
(you can find source of CustomDialog to see how they suppose that you will design your custom dialog)
I don't know if I can explain my method in a cool way...
Let's say I need productPrice and amount from a JDialog whos going to get that info from user, I need to call that from the JFrame.
declare productPrice and ammount as public non-static global variables inside the JDialog.
public float productPrice;
public int amount;
* this goes inside the dialog's class global scope.
add these lines in the JDialog constructor to ensure modality
super((java.awt.Frame) null, true);
setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
* this goes within the dialog's class constructor
let's say your JDialog's class name is 'MyJDialog' when calling do something like this
MyJDialog question = new MyJDialog();
MyJDialog.setVisible(true);
// Application thread will stop here until MyJDialog calls dispose();
// this is an effect of modality
//
// When question calls for dispose(), it will leave the screen,
// but its global values will still be accessible.
float myTotalCostVar = question.productPrice * question.ammount;
// this is acceptable.
// You can also create public getter function inside the JDialog class,
// its safer and its a good practice.
* this goes in any function within your JFrame and will call JDialog to get infos.
When you pass any value to JFrame to JDialog then create parametrized constructor of jdialog and in jframe whenever you want to call.
e.g. The parametrized constructor like :
public EditProduct(java.awt.Frame parent, boolean modal, int no) {
//int no is number of product want to edit.
//Now we can use this pid in JDialog and perform whatever you want.
}
When you want to pass values from JDialog to JFrame create a bean class with set and get method the the values using vector and get these values in jframe.
More info
Here is how I usually do it. I wasn't sure, that's why I've created that post:
Returning value from JDialog; dispose(), setVisible(false) - example
Add an interface to your constructor?
public class UploadConfimation extends JDialog {
private final JPanel contentPanel = new JPanel();
public interface GetDialogResponse{
void GetResponse(boolean response);
}
/**
* Create the dialog.
*/
public UploadConfimation(String title, String message, GetDialogResponse result) {
setBounds(100, 100, 450, 300);
setTitle(title);
getContentPane().setLayout(new BorderLayout());
contentPanel.setLayout(new FlowLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
{
JLabel lblMessage = new JLabel(message);
contentPanel.add(lblMessage);
}
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("YES");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
result.GetResponse(true);
dispose();
}
});
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("NO");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
result.GetResponse(false);
dispose();
}
});
buttonPane.add(cancelButton);
}
}
}
}