I am designing a project in NetBeans. For that I need to display a jdialog as a login window at first. But if I run the project both jframe and jdialog will appear. How can I hide jframe and how to set jdialog as a starting one in my project?
I wrote
LoginDlg.setVisible(true);
this.setVisible(false);
In construcor.
Start by taking a look at How to Make Dialogs
You want to make the JDialog a modal dialog, so that it will stop the execution of additional code.
In your program launch code, you want to show the dialog first, then, based on what the user does, show the main frame.
Alternatively, you could use a CardLayout, see How to Use CardLayout for more details, which will allow you to switch the active view based on your needs
In your main method, show only the dialog. Then add a button or something(e.g timer) that hides the dialog, and add a listener to that dialog so when the dialog disposes the main frame is shown.
public class JavaApplication3{
private static JFrame f = new JFrame("alabala");
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
final JDialog d = new JDialog();
d.add(new JLabel("pla"));
d.setVisible(true);
Timer t1 = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
d.dispose();
}
});
t1.setRepeats(false);
t1.start();
d.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
f.pack();
f.setVisible(true);
}
});
}
}
Related
I have a program with a GUI that needs to open a separate window and wait for the user to select and option, then continue. I figure I should be doing this with the wait() and notify() methods, but I'm still trying to figure out exactly how to use those. A complicating factor is that things seem to work differently when the second window is created in an actionPerformed() method, which it needs to be.
Here's how I think it should be done here, apparently it is not quite right...
This should create a window with a button, when the button is pressed, another window with a button should be created, and when that button is pressed, the program should print "End".
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class WtfExample {
public static void main(String[] args) {
JFrame jf = new JFrame();
JButton butt = new JButton("Button");
butt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
WtfExample we = new WtfExample();
we.display();
}
});
jf.getContentPane().add(butt);
jf.setSize(new Dimension(1000, 500));
jf.setVisible(true);
System.out.println("End");
}
public synchronized void display() {
JFrame jf = new JFrame();
JButton butt = new JButton("Button");
butt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
synchronized(WtfExample.this) {
WtfExample.this.notifyAll();
}
}
});
jf.getContentPane().add(butt);
jf.setSize(new Dimension(1000, 500));
jf.setVisible(true);
while(true) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
edit- I wasn't clear enough in one thing- the second window that's opened is blank, like its components were never added to it. That's the case whether it's a frame or dialog, but that only happens if the window is created from the actionPerformed method.
No, you should just be using a JDialog.
You need a modal dialog window. Here's a tutorial on dialogs. It is easier to use JOptionPane for the simple cases.
A Dialog can be modal. When a modal Dialog is visible, it blocks user input to all other windows in the program.
As the other two answers suggest you need a modal JDialog. You do not need to deal with any Thread classes. The JDialog window will deal with the giving you control back once the user input is handled. There are a few ways you can set the dialog box modal. Here are two examples.
new JDialog(Dialog owner, boolean modal)
or
new JDialog(Dialog owner, String title, boolean modal)
You could also do something like this:
JDialog dialog = new JDialog(owner);
dialog.setModal(true);
I think this is a pretty good article about modality in JAVA.
I'm curious how can I use a dialog designer that is built into IntelliJ IDEA since I find it an option with big potential but I don't really know how to use it.
Let's consider a desktop program with two classes created using designer: MainWindow and MainDialog. Let's assume that MainWindow class already has all fields, components etc. required for a simple form to be displayed. Then in the MainWindow class we have:
JLabel label = new JLabel("This is default text");
JButton showDialog = new JButton("Show dialog");
showDialog.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
MainDialog dialog = new MainDialog ();
dialog.pack();
dialog.setVisible(true);
}
});
which makes the dialog visible. The MainDialog class designed by default by designer looks like this:
public class MainDialog extends JDialog {
private JPanel contentPane;
private JButton buttonOK;
private JButton buttonCancel;
public MainDialog() {
setContentPane(contentPane);
setModal(true);
getRootPane().setDefaultButton(buttonOK);
buttonOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onOK();
}
});
buttonCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
});
// call onCancel() when cross is clicked
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
});
// call onCancel() on ESCAPE
contentPane.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
private void onOK() {
// add your code here
dispose();
}
private void onCancel() {
// add your code here if necessary
dispose();
}
}
Now let's also assume that in the dialog class I have a text field:
JTextField textField = new JTextField();
that I am getting a text to be displayed by label in the MainWindow class from.
Since I have an onOK() function created by default I'd like it to update a label in MainWindow class with text typed in text field in MainDialog class.
The problem is: how can I perform an action on another class's field using this pattern without writing in MainDialog a line MainWindow window = new MainWindow or making label static? Is it possible? I know that this can be done much simpler but this is also an easy example and I'd like to perform much more complex operations using this structure.
Yes, it's possible.
First option: since the dialog is modal, the code opening the modal in the main window will be blocked until the dialog is closed. So you could just do something like this in the modal:
public String getEnteredText() {
return textField.getText();
}
and in the main window:
dialog.setVisible(true);
myLabel.setText(dialog.getEnteredText());
Or (but I would use the first option), you can pass the main window, or any other callback, to the dialog. For example:
MainDialog dialog = new MainDialog(this);
And in the dialog:
private void onOK() {
mainWindow.setLabelText(textField.getText());
dispose();
}
My recommendation is to avoid UI designers. Especially if you're not able yet to write the code that they generate by yourself, and you don't have a deep understanding of how Swing works.
I'm working on a program which has multiple JFrame and JDialog windows.
I have a JFrame which contains a button, when I click on this button a JDialog window opens up. In this JDialog windows there is another button, which when is clicked it opens up a second JDialog window. In the second JDialog window I have a last button.
What I want to do is to close both JDialog windows and JFrame window when this last button is clicked.
This is how the opening order is:
JFrame Frame1;
JButton Button1;
JDialog Dialog1;
JButton Button2;
JDialog Dialog2;
JButton Button3;
Button1ActionPerformed(ActionEvent e){
new Dialog(Frame1Frame);
}
Button2ActionPerformed(ActionEvent e){
new Dialog2(Dialog1Frame)
}
Button3ActionPerformed(ActionEvent e){
//Here I wnat to add the code that closes JDialog2 JDialog1 and JFrame1 windows.
}
I have tried super.dispose(); but it doesn't work. Any ideas?
As shown here using Action, your actionPerformed() implementation can dispatch the WINDOW_CLOSING event to the desired Window instances.
#Override
public void actionPerformed(ActionEvent e) {
d1.dispatchEvent(new WindowEvent(d1, WindowEvent.WINDOW_CLOSING));
d2.dispatchEvent(new WindowEvent(d2, WindowEvent.WINDOW_CLOSING));
f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
}
There may be better ways of doing this, but here is one general approach that might help.
In your code you create the windows but you do not store the reference to the windows you created into a variable. For example, you have:
JDialog Dialog1;
Then later, when you create the instance of Dialog1, you have this code:
Button1ActionPerformed(ActionEvent e){
new Dialog(Frame1Frame);
}
This means you have created the Dialog, but you have not retained a reference to the Dialog for later manipulation by your code. If you assign this value here, you should be able to manipulate it later.
If you change your implementation to:
Button1ActionPerformed(ActionEvent e){
Dialog1 = new Dialog(Frame1Frame);
}
Then later in your code you will have a reference to the Dialog in order to manipulate it,
Button3ActionPerformed(ActionEvent e){
Dialog1.dispose();
// you can manipulate the variables of the class from here and close other windows etc.
}
If you have the objects reference, you can do:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
public class Main
{
private static JFrame frame;
private static JButton buttonFrame;
private static JDialog dialog1;
private static JButton buttonDialog1;
private static JDialog dialog2;
private static JButton buttonDialog2;
public static void main(String[] args) {
/* frame */
frame = new JFrame("Main Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
buttonFrame = new JButton("open dialog 1");
buttonFrame.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
dialog1.setVisible(true);
}
});
frame.add(buttonFrame);
/* dialog 1 */
dialog1 = new JDialog(frame, "Dialog 1");
dialog1.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog1.setSize(300, 300);
dialog1.setLocationRelativeTo(null);
buttonDialog1 = new JButton("open dialog 2");
buttonDialog1.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
dialog2.setVisible(true);
}
});
dialog1.add(buttonDialog1);
/* dialog 2 */
dialog2 = new JDialog(dialog1, "Dialog 2");
dialog2.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog2.setSize(200, 200);
dialog2.setLocationRelativeTo(null);
buttonDialog2 = new JButton("close all");
buttonDialog2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
dialog2.dispose();
dialog1.dispose();
frame.dispose();
}
});
dialog2.add(buttonDialog2);
/* show frame */
frame.setVisible(true);
}
}
Otherwise you can use System.exit(0);:
buttonDialog2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
Closing multiple JFrame by another JFrame-
It is possible to close multiple windows, even non-static Java swing windows. Type below small code, step by step.
The below code is mainly for closing the First frame through the second open frame which has been opened by the same First frame.
*Make a **second class global variable** in the first-class & a **button global variable in first-class*
Class2 NiceApp1 = new Class2();
JToggleButton Nice=new JToggleButton("Nice One");
// *After the Class1 above code, you will need a close method. I use a jar of NiceApplication1 with class New Close you can use the same jar or very below close method and can call the close method. You will need to type the method in Class1, just type your **close method in the method**.*
public void method (){
NewClose NiceO = new NewClose();
NiceO.Close(this);
//or
Close();
}
*// Now make a **Button Global variable in Class2**.*
javax.swing.JToggleButton Zero = new javax.swing.JToggleButton();
*// Type in Class2 the below **method**.*
public void methodclass2(JToggleButton Nice){
Zero = Nice;
}
*//Now you will need to type the below code, type the below code in the **Class1 button action** by which you will open the Class2.*
Nice.addActionListener((ActionEvent e) -> {
method();
});
NiceApp1.methodclass2(Nice);
NiceApp1.setVisible(true);
*//Now just type a **single line code** in the second class, type anywhere from which you want to close Class1.*
Zero.doClick();
*//Now the **close method** if you don't have a close method.*
public void Close() {
WindowEvent winclosing = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(winclosing);
}
**You have done now if you did the above process.
If you only want to close which opens secondly so by the only close method change the this into your frame variables.
You can also visit NiceApplication1.BlogSpot.Com.
You can use the above code. From Class2 after the button's click, you will see your previous Class1 window will close.**
My application offers the ability to launch a long-running task. When this occurs a modeless JDialog is spawned showing the progress of the task. I specifically make the dialog modeless to allow the user to interact with the rest of the GUI whilst the task runs.
The problem I'm facing is that if the dialog becomes hidden behind other windows on the desktop it becomes difficult to locate: There is no corresponding item on the task bar (on Windows 7), nor is there an icon visible under the Alt+Tab menu.
Is there an idiomatic way to solve this problem? I had considered adding a WindowListener to the application's JFrame and use this to bring the JDialog to the foreground. However, this is likely to become frustrating (as presumably it will mean the JFrame then loses focus).
You can create a non-modal dialog and give it a parent frame/dialog. When you bring up the parent frame/dialog, it also brings the non-modal dialog.
Something like this illustrates this:
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame();
frame.setTitle("frame");
JDialog dialog = new JDialog(frame, false);
dialog.setTitle("dialog");
final JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(button, "Hello");
}
});
final JButton button2 = new JButton("Click me too");
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(button2, "Hello dialog");
}
});
frame.add(button);
dialog.add(button2);
frame.pack();
dialog.pack();
frame.setVisible(true);
dialog.setVisible(true);
}
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.