I have developed Swing application in which I have used JDialog to show popup.
But the problem is when I press alt+tab it shows only the dialog not the application. I also tried the modal for dialog.
My requirement is when the dialog opened on application and I press the alt+tab key it switch to another X application and again when I press alt+tab key it display dialog opened on my application. Currently it shows dialog opened but alone not with application.
How I can meet this requirement using JDialog?
Here is sample code
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*$Id$
*/
public class Main
{
public static void main(final String[] args)
{
final JFrame jFrame = new JFrame();
jFrame.setSize(300, 200);
final JPanel panel = new JPanel();
final JButton button = new JButton("click here to open dialog");
final ProductDialog dialog = new ProductDialog();
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent e)
{
dialog.setVisible(true);
}
});
panel.add(button);
jFrame.add(panel);
jFrame.setVisible(true);
}
}
And The dialog is as under
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ProductDialog extends JDialog
{
private static final long serialVersionUID = 1L;
public ProductDialog()
{
this.add(new JPanel().add(new JLabel("Test")));
this.setSize(150, 100);
this.setModal(true);
this.setLocationRelativeTo(null);
}
}
Here is an image of the visual effect of a small app. that is currently displaying a security dialog in alt+tab on Windows 7. The app. itself is already visible on-screen, though the security dialog (upper left) is all that is shown in the smaller icons.
You need to set the parent window of the dialog to the Frame of your application.
Small example:
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TestDialog {
protected void initUI() {
JFrame frame = new JFrame(TestDialog.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton button = new JButton("Click me to open dialog");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window parentWindow = SwingUtilities.windowForComponent(button);
JDialog dialog = new JDialog(parentWindow);
dialog.setLocationRelativeTo(button);
dialog.setModal(true);
dialog.add(new JLabel("A dialog"));
dialog.pack();
dialog.setVisible(true);
}
});
frame.add(button);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestDialog().initUI();
}
});
}
}
I have pass the parent Frame to the Dialog as under.
final ProductDialog dialog = new ProductDialog(jFrame);
And set it as under
Call the constructor of super class with parent window as argument and set the modality type of dialog and it's work for me.
import java.awt.Dialog;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ProductDialog extends JDialog
{
private static final long serialVersionUID = 1L;
public ProductDialog(final JFrame jFrame)
{
super(jFrame);
this.add(new JPanel().add(new JLabel("Test")));
this.setSize(150, 100);
this.setModal(true);
this.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
}
}
This is just sample example that I have created for testing.
Related
I have discovered class javax.swing.Popup. I wrote code to test its behavior. Code is shown below. When I run the code, after the JFrame is displayed, I click the SHOW button and the Popup is displayed. After that I click the HIDE button and the Popup disappears. But then if I click the SHOW button again, nothing happens. The Popup only appears after clicking the SHOW button for the first time. Also, if I click the HIDE button first, before clicking the SHOW button, then when I click the SHOW button, the Popup does not appear.
Am I missing something?
Am I doing something wrong?
I admit I haven't investigated this behavior. I haven't searched the Internet and I haven't looked at the code for class Popup nor PopupFactory, simply due to laziness and in the hope that someone can explain it to me.
Here is my MCVE.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
public class PopupTest implements ActionListener, Runnable {
private static final String HIDE = "HIDE";
private static final String SHOW = "SHOW";
private Popup popup;
public void actionPerformed(ActionEvent actionEvent) {
String actionCommand = actionEvent.getActionCommand();
switch (actionCommand) {
case HIDE:
popup.hide();
break;
case SHOW:
popup.show();
break;
}
}
public void run() {
showGui();
}
private void showGui() {
JFrame frame = new JFrame("Popup");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel centerLabel = new JLabel("CENTER LABEL", SwingConstants.CENTER);
frame.add(centerLabel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel();
JButton showButton = new JButton(SHOW);
showButton.addActionListener(this);
buttonsPanel.add(showButton);
JButton hideButton = new JButton(HIDE);
hideButton.addActionListener(this);
buttonsPanel.add(hideButton);
frame.add(buttonsPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
JLabel popupLabel = new JLabel("Popup_Label");
PopupFactory factory = PopupFactory.getSharedInstance();
Point pt = centerLabel.getLocationOnScreen();
int x = pt.x + 10;
int y = pt.y - 10;
popup = factory.getPopup(centerLabel, popupLabel, x, y);
}
public static void main(String[] args) {
PopupTest instance = new PopupTest();
EventQueue.invokeLater(instance);
}
}
https://docs.oracle.com/javase/7/docs/api/javax/swing/Popup.html#hide()
The documentation that you have chosen not to read is very clear that hide() disposes of the Popup and any further method calls on that Popup will result in indeterminate behaviour.
You must create a new Popup instance each time.
From the docs for hide():
"Hides and disposes of the Popup. Once a Popup has been disposed you
should no longer invoke methods on it. A disposed Popup may be
reclaimed and later used based on the PopupFactory."
As such, here is a quick and dirty modified version that works.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
public class PopupTest implements ActionListener, Runnable {
private static final String HIDE = "HIDE";
private static final String SHOW = "SHOW";
private Popup popup;
private JLabel centerLabel;
private JLabel popupLabel = new JLabel("Popup_Label");
private PopupFactory factory = PopupFactory.getSharedInstance();
public void actionPerformed(ActionEvent actionEvent) {
String actionCommand = actionEvent.getActionCommand();
switch (actionCommand) {
case HIDE:
if (popup == null) {
return;
}
popup.hide();
popup = null; // necessary to avoid using the disposed popup
break;
case SHOW:
if (popup != null) { // it's already showing
return;
}
Point pt = centerLabel.getLocationOnScreen();
int x = pt.x + 10;
int y = pt.y - 10;
popup = factory.getPopup(centerLabel, popupLabel, x, y);
popup.show();
break;
}
}
public void run() {
showGui();
}
private void showGui() {
JFrame frame = new JFrame("Popup");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
centerLabel = new JLabel("CENTER LABEL", SwingConstants.CENTER);
frame.add(centerLabel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel();
JButton showButton = new JButton(SHOW);
showButton.addActionListener(this);
buttonsPanel.add(showButton);
JButton hideButton = new JButton(HIDE);
hideButton.addActionListener(this);
buttonsPanel.add(hideButton);
frame.add(buttonsPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
PopupTest instance = new PopupTest();
EventQueue.invokeLater(instance);
}
}
I have a window, which is the main window in my app and it contains buttons. On clicking on one of them, a child JFrame appears and if I click again another frame appears and this can be continuous depending on how many clicks are made. What I want, is when I click on the JButton once only one frame should open and since this frame is open no other similar frames can be opened upon clicking on the button for the second time until the first child frame is closed.
This can be done by opening a Modal dialog box instead of a jFrame. See How to Use Modality in Dialogs for more information.
Here is a simple example from A Simple Modal Dialog:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AboutDialog extends JDialog implements ActionListener {
public AboutDialog(JFrame parent, String title, String message) {
super(parent, title, true);
if (parent != null) {
Dimension parentSize = parent.getSize();
Point p = parent.getLocation();
setLocation(p.x + parentSize.width / 4, p.y + parentSize.height / 4);
}
JPanel messagePane = new JPanel();
messagePane.add(new JLabel(message));
getContentPane().add(messagePane);
JPanel buttonPane = new JPanel();
JButton button = new JButton("OK");
buttonPane.add(button);
button.addActionListener(this);
getContentPane().add(buttonPane, BorderLayout.SOUTH);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
setVisible(false);
dispose();
}
public static void main(String[] a) {
AboutDialog dlg = new AboutDialog(new JFrame(), "title", "message");
}
}
i want to open new JDialog box inside JDialog box. so i have used that code to prevent to come on ancestor JFrame but i am facing the problem to open new JDialog box in previous JDialog box. please give me the solution to get rid of this problem.
Here is the code :-
TestbedWorkflow tbwf = new TestbedWorkflow();
JDialog dialog = new JDialog();
Dimension s = SOAStreamer.getSOAStreamerObj().getContentPanel().getSize();
dialog.setSize(s);
dialog.setTitle("TestBed Workflow Design");
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
tbwf.setSize(s);
dialog.add(tbwf);
tbwf.updateUI();
dialog.setVisible(true);
TestbedWorkflow is JFrame which i have added in to JDialog box.now i want to open new JDialog box.
thanks in advance
The example below opens an arbitrary number of dialogs in an APPLICATION_MODAL hierarchy; only the most recent is operable. As an alternative, consider a modeless dialog, illustrated here.
Update: The revised example below shows the hierarchy depth in the dialog title and eliminates a spurious subclass.
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
/**
* #see https://stackoverflow.com/a/12301243/230513
*/
public class DialogTest {
private static int index;
static class OpenAction extends AbstractAction {
public OpenAction() {
super("Open");
}
#Override
public void actionPerformed(ActionEvent e) {
JDialog jd = new JDialog();
jd.setTitle("D" + String.valueOf(++index));
jd.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
jd.add(new JButton(new OpenAction()));
jd.pack();
jd.setLocationRelativeTo(null);
jd.setVisible(true);
}
}
private void display() {
JFrame f = new JFrame("DialogTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JButton(new OpenAction()));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new DialogTest().display();
}
});
}
}
I have 2 problems with java on Ubuntu:
JTextField gets inaccessible and you cant type anything in it. To reproduce you have to click on label ('Click this label') it will open my extended JDialog. After closing it with Cancel button JTextField gets inaccessible. The problem is that it doesen't happen all the time. I think around 1 on 10 tries. When it happens you have to click somewhere else on browser window or open dialog one more time.
Second problem is that when ubuntu opens JDialog it creates other process which is shown on left side app bar. You can than click somewhere on the applet under the dialog and this dialog will go under the browser even thought it is modal and should be on top.
Did anyone get similar errors with ubuntu and know how to fix it. On windows everything works fine. We use ubuntu-12.04-desktop and java 1.6.0_34-b04. It was tested in firefox 11.0 and Google chrome (newest I think)
Here is my code TestApplet.java class:
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JApplet;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import client.utilities.GUIUtilities;
#SuppressWarnings("serial")
public class TestApplet extends JApplet {
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
JApplet applet = TestApplet.this;
applet.setLayout(new FlowLayout());
JTextField ts = new JTextField("Test text");
ts.setColumns(10);
applet.add(ts);
applet.add(getCallCalendarButton(ts));
}
});
} catch (Exception e) {
System.err.println(e.getCause());
}
}
private JLabel callCalendarButton;
private MyDialog aDialog;
protected JLabel getCallCalendarButton(final JComponent cmp) {
if (callCalendarButton == null) {
callCalendarButton = new JLabel("Click this label!!");
callCalendarButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (callCalendarButton.isEnabled()) {
Frame parentFrame = null;
if (parentFrame == null)
parentFrame = GUIUtilities.getParentFrame(cmp);
System.out.println(parentFrame);
aDialog = new MyDialog(parentFrame, cmp);
aDialog.setVisible(true);
System.out.println("qwewqe");
cmp.requestFocusInWindow();
}
}
});
}
return callCalendarButton;
}
}
And here is extended JDialog class (MyDialog.java):
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class MyDialog extends JDialog {
private JButton okButton;
private JButton cancelButton;
private JComponent owner;
private int WIDTH = 230;
private int HEIGHT = 230;
Frame parent;
public MyDialog(Frame parent, JComponent owner) {
super(parent);
this.parent = parent;
this.owner = owner;
okButton = new JButton("OK");
okButton.setMnemonic('O');
okButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
MyDialog.this.setVisible(false);
MyDialog.this.dispose();
}
});
cancelButton = new JButton("Cancel");
cancelButton.setMnemonic('C');
cancelButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
MyDialog.this.setVisible(false);
}
});
this.setLayout(new BorderLayout());
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
bottomPanel.add(okButton);
bottomPanel.add(cancelButton);
this.add(bottomPanel, BorderLayout.SOUTH);
this.setModal(true);
this.setBounds(100, 100, WIDTH, HEIGHT);
//
this.addComponentListener(new ComponentAdapter(){
#Override
public void componentHidden(ComponentEvent e){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
MyDialog.this.owner.requestFocusInWindow();
//MyDialog.this.parent.toFront();
//MyDialog.this.parent.requestFocusInWindow();
}
});
}
});
}
}
To use this html to run applet:
<html>
<body>
<Applet Code="TestApplet.class" width="200" height="100" >
</Applet>
</body>
</html>
I have a main application frame (MainFrame class). On actionperformed event of a JButton, a JPanel (MyJPanel class) is opened by placing it in JDialog. I am not extending JDialog to create MyJPanel class because I might need MyJPanel at other purposes too.
My Problem is I cannot programmatically close the MyJPanel which is displayed in JDialog. Is there anything that I missing? Could you please figure it out?
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class MainFrame extends JPanel {
public MainFrame() {
JButton btnOpenJdialog = new JButton("Open JDialog");
add(btnOpenJdialog);
btnOpenJdialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog jd = new JDialog();
MyJPanel mjp = new MyJPanel(true);//showing in JDialog
jd.setTitle("JDialog");
jd.add(mjp);
jd.pack();
jd.setVisible(true);
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("Test-JFrame");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainFrame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
MyJPanel Class :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JButton;
public class MyJPanel extends JPanel {
private boolean isShownInJDialog = false;
public MyJPanel() {
JButton btnCloseMe = new JButton("Finish Action");
add(btnCloseMe);
btnCloseMe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isShownInJDialog) {
MyJPanel.this.setVisible(false);
//how to close the JDialog too.
}
else {
//just hide the content,
MyJPanel.this.setVisible(false);
}
}
});
}
public MyJPanel(boolean isShownInJDialog) {
this();
this.isShownInJDialog = isShownInJDialog;
}
}
UPDATE
I was able to solve this using Howard's answer as :
...
if (isShownInJDialog) {
Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
w.setVisible(false);
}
...
If I understand your question correctly, you want to close the JDialog which your MyJPanel is contained in but do not have a reference to it?
You may either provide such a reference using the constructor of MyJPanel or change the code inside your ActionListener to
Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
w.setVisible(false);
which looks up the parent window of your panel without direct reference.