Iconified JFrame showing behind modal JDialog on win 7 taskbar click - java

I originally developed the following code on Win XP. When you click the program icon in the XP taskbar, the parent frame remains iconified and the JDialog returns to focus, which is the behavior I want. However, when clicking the program's taskbar icon on Win 7, the parent JFrame changes its state back to Normal and shows behind the app-modal JDialog. I've tried overriding the JFrame's setExtendedState() method to intercept the frame's state change with no luck.
Is there a workaround for this, or is there a flaw my logic I need to address?
import java.awt.*;
import javax.swing.JDialog;
import javax.swing.JFrame;
public class TestLogin extends JFrame {
public TestLogin() {
this.setSize(300, 300);
iconify(this);
setLocationRelativeTo(null);
this.setTitle("I'm a Frame!");
this.setVisible(true);
LoginScreen login = new LoginScreen(this);
}
public static void main(String [] args) {
TestLogin frame = new TestLogin();
}
public static void iconify(Frame frame) {
int state = frame.getExtendedState();
// Set the iconified bit
state |= Frame.ICONIFIED;
// Iconify the frame
frame.setExtendedState(state);
}
public static void deiconify(Frame frame) {
int state = frame.getExtendedState();
// Clear the iconified bit
state &= ~Frame.ICONIFIED;
// Deiconify the frame
frame.setExtendedState(state);
}
public class LoginScreen extends JDialog {
private JFrame root;
public LoginScreen(JFrame root) {
super(root);
this.root = root;
setLocationRelativeTo(null);
this.setTitle("I'm a Dialog!");
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
this.setSize(200, 200);
setVisible(true);
}
}
}

It looks like a bug in the java paradigm of "write once, run anywhere". If that is to include windows 7, then you might contact oracle and fill a bug report.
Regards,
Stéphane

Related

Change AWT Frame's maximize behaviour to fullscreen on MacOS

When creating an AWT Frame in a Java program running on MacOS, the maximize button in the frame's title bar maximises the window:
public static void main(String args[]) {
new Frame();
}
When I create a Swing JFrame instance instead, the same button toggles the window into fullscreen mode, which is the standard behaviour on MacOS. The button even looks different visually when I hover over it:
public static void main(String args[]) {
new JFrame();
}
Is there any way how I can replicate JFrame's "maximize to fullscreen" behaviour with AWT's Frame? I scanned the code of the entire JFrame class and wasn't able to identify any logic that would toggle the Frame's behaviour in such a way.
Try this code :
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
public class MyFrame extends Frame {
MyFrame() {
for (Window w : Window.getWindows()) {
GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice().setFullScreenWindow(w);
}
}
public static void main(String args[]) {
MyFrame f = new MyFrame();
f.setVisible(true);
}
}

Issue with Dialog Modality in Swing in java 1.6

I have 3 dialog that gets displayed together in my project.
First dialog is modeless with setVisibleOnTop(false).
Second dialog is modeless with setVisibleOnTop(true).
Third dialog is Application Modal with setVisibleOnTop(true).
Now the issue is :
Ideally when there is a dialog "third" opened with APPLICATION_MODAL property then no other JComponent should accept the click. This works fine with java 1.7.
With java 1.6 is I click on dialog "one" then dialog "second" goes at the back of dialog "one". Whereas dialog "third" is still opened.
Now the question is:
Why dialog "one" comes in front when there is an APPLICATION_MODAL dialog (third) opened?
Why second dialog with property setAlwaysOnTop(true) goes at back?
I believe this is a issue with java 1.6. Does anyone know about this?
Is this bug documented somewhere?
Sample Code:
import java.awt.Frame;
import javax.swing.JDialog;
class MyDialog1 extends JDialog {
MyDialog1 ()
{
super();
super.setVisible(false);
setTitle("one");
}
}
class MyDialog2 extends JDialog {
MyDialog2 ()
{
super(null,ModalityType.MODELESS);
setAlwaysOnTop(true);
setTitle("second");
}
}
class MyDialog3 extends JDialog {
MyDialog3 ()
{
super(new Frame(),ModalityType.APPLICATION_MODAL);
setTitle("third");
setAlwaysOnTop(true);
super.setVisible(false);
}
}
public class ModalityIssue {
public static void main(String args[])
{
MyDialog1 d1=new MyDialog1();
d1.setSize(600, 600);
MyDialog2 d2=new MyDialog2();
d2.setSize(500, 500);
MyDialog3 d3=new MyDialog3();
d3.setSize(400, 400);
d1.setVisible(true);
d2.setLocationRelativeTo(d1);
d2.setVisible(true);
d3.setLocationRelativeTo(d2);
d3.setVisible(true);
}
}
dont to use awt components
JFrame ignores alwaysOnTop and modality,
use Initial Thread,
important is code ordering too
you can to use aplication modality (seems like as better, but nobody knows if meets with your requirement/s)
MyDialog1 always flashing (MyDialog2 is painted before MyDialog1, then jumps behing MyDialog2, standard users can't catch that), maybe there aren't any JComponents added to any of Top-Level Containers in the current JVM
for example (Java 1.6.21 / 025 / 031, the same corerctly works in 1.7.04 and 1.8.60 / 66 / win10)
import java.awt.Dialog.ModalityType;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
class MyDialog1 extends JDialog {
public MyDialog1() {
super(null, ModalityType.MODELESS);
setAlwaysOnTop(true);
setTitle("fist");
}
}
class MyDialog2 extends JDialog {
public MyDialog2() {
super(null, ModalityType.MODELESS);
setAlwaysOnTop(true);
setTitle("second");
}
}
public class ModalityIssue {
private JFrame frame = new JFrame();
private MyDialog1 d1 = new MyDialog1();
private MyDialog2 d2 = new MyDialog2();
public ModalityIssue() {
frame.setTitle("third");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocation(100, 100);
frame.setVisible(true);
d1.setSize(400, 300);
d1.setLocation(200, 200);
d1.setVisible(true);
d2.setSize(400, 300);
d2.setLocation(300, 300);
d2.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ModalityIssue();
}
});
}
}

How to create a modal JDialog on top of another modal JDialog

I have a modal settings dialog which is a JDialog. In this settings window I placed some components including a button to yet another modal settings dialog which is also a JDialog. I made them JDialogs because that is the only way I know of to make a modal dialog.
The problem is this: when I create the main settings dialog I have to construct the JDialog either without a parent Frame or with a parent Frame. Since my main window is a JFrame, I can just pass that to the main settings dialog constructor. But when I want to create the second modal settings dialog which should have the main settings dialog as a parent, I can't find a way to get the (J)Frame of the JDialog. I do want to pass that main settings dialog as a parent so that the second settings dialog centers on it when it is shown. Let's assume the second settings dialog has no constructor for passing a location, just the constructors of the JDialog.
Is there a way to get the (J)Frame of a JDialog?
Is there a design flaw in my setup and should I have used something else for these settings dialogs? (And if so, how should I make these alternative settings dialogs modal?)
Thank you for your help,
Erik
UPDATE:
Thank you all for your answers. They led me to understand that apparently it's not absolutely necessary to have an owner for a JDialog. I thought this was needed for the dialog to be able to disable the owner until the dialog is closed, but apparently the modality is independent of the owner. I also noticed that even with an owner the dialog still doesn't center on the owner, so now my code is like:
public class CustomDialog extends JDialog {
public CustomDialog(String title) {
setModal(true);
setResizable(false);
setTitle(title);
buildGUI();
}
public Result showDialog(Window parent) {
setLocationRelativeTo(parent);
setVisible(true);
return getResult();
}
}
This also allows for modal dialogs in modal dialogs.
Thanks for all your help!
Not sure what exactly you have as a problem, but here is an example on how you can have multiple modal dialogs:
import java.awt.BorderLayout;
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.JPanel;
import javax.swing.SwingUtilities;
public class TestDialog {
protected static void initUI() {
JPanel pane = newPane("Label in frame");
JFrame frame = new JFrame("Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
frame.setVisible(true);
}
public static JPanel newPane(String labelText) {
JPanel pane = new JPanel(new BorderLayout());
pane.add(newLabel(labelText));
pane.add(newButton("Open dialog"), BorderLayout.SOUTH);
return pane;
}
private static JButton newButton(String label) {
final JButton button = new JButton(label);
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(newPane("Label in dialog"));
dialog.pack();
dialog.setVisible(true);
}
});
return button;
}
private static JLabel newLabel(String label) {
JLabel l = new JLabel(label);
l.setFont(l.getFont().deriveFont(24.0f));
return l;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
}
1.please read The New Modality API in Java SE 6
2.Is there a way to get the (J)Frame of a JDialog?
Window ancestor = SwingUtilities.getWindowAncestor(this);
or
Window ancestor = (Window) this.getTopLevelAncestor();
It is now 2021 and so about 8.5 years after the question was posted, but back in 2012 and still in these days by far and away the easiest solution is to simply create the JDialog with a Dialog as owner. Java has 5 constructors with a Dialog owner to offer, next to 5 similar ones with a Frame owner and 5 with a Window owner.
The issue that the OP was probably faced with was the default template for a JDialog in Netbeans or some other IDE. Netbeans (12.2) offers this as a template for a new JDialog Form...:
public class NewJDialog extends javax.swing.JDialog {
/**
* Creates new form NewJDialog
*/
public NewJDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
}
You can simply change the signature of the constructor to use a Dialog as owner instead of the default option of a Frame:
public class NewJDialog extends javax.swing.JDialog {
/**
* Creates new form NewJDialog
*/
public NewJDialog(java.awt.Dialog parent, boolean modal) {
super(parent, modal);
initComponents();
}
And away you go.

How I can selected by default an InternalFrame on a JDesktopPane?

I have a JFrame with the JDesktopPane and inside the JDesktopPane, I launch with the constructor a JInternalFrame.
(Its a app like the authentification users, with the textbox user and textbox pass)
I lauch the internal like this:
MyInternalFrame internalF = new MyInternalFrame();
desktopPane.add(internalF);
I try with:
internalF.setVisible(true);
internalF.setSelected(true);
desktopPane.getDesktopManager().activateFrame(internal);
desktopPane.setSelectedFrame(internal);
How I can lauch the JInternalFrame and Its selected by default?
When I run the aplication, internalframe is like in background, Its not selected, Its not focused.
Have a look at the How To Use Internal Frames java tutorial. It gives a nice example and uses the following;
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
desktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {}
}
You can make the internal frame visible AFTER the desktop is created and the main frame is visible. In that case the frame will be selected by default.
So, one example of what you can do:
Create main frame
Create desktop
Create internal frame but don't make it visible
Start thread that sets visible to true on the internal frame, but the thread can wait until the desktop is shown
Make the main frame visible
In the thread call internalFrame.setVisible(true) and exit from the thread.
In such case the internal frame will appear on the desktop and it will be selected as you want it.
You might think of other solution without using threads, but writing handlers to the main frame's events. In any case, to make the internal frame visible after it shows, you have to show it AFTER desktop with main frame is displayed.
Here is the example, that you can use:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.HeadlessException;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private Internal internalFrame;
public Main() throws HeadlessException {
super("Internal Frame Test");
setBounds(10, 10, 600, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
add(createDesktop(), BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowOpened(WindowEvent e) {
internalFrame.setVisible(true);
}
});
setVisible(true);
}
private Component createDesktop() {
JDesktopPane d = new JDesktopPane();
internalFrame = new Internal("first");
d.add(internalFrame);
return d;
}
public static class Internal extends JInternalFrame {
private static final long serialVersionUID = 1L;
public Internal(String title) {
super(title);
setBounds(10, 10, 300, 100);
}
}
public static void main(String[] a) {
new Main();
}
}

Making a Java panel fullscreen

How would you make a JComponent (panel, frame, window, etc.) fullscreen, so that it also overlaps everything on the screen including the windows start bar?
I don't want to change the resolution or anything with the graphics device like bitdepth etc, I just want to overlap everything else.
Check out this tutorial describing Java's Full-Screen mode API.
Example code (taken from the tutorial). Note that the code operates on a Window so you would need to embed your JPanel with a Window (e.g. JFrame) in order to do this.
GraphicsDevice myDevice;
Window myWindow;
try {
myDevice.setFullScreenWindow(myWindow);
...
} finally {
myDevice.setFullScreenWindow(null);
}
You can try some of the codes in this page, allowing a container to fill the screen (so it is not a solution for an individual component, but for a set of components within a container like a JFrame)
public class MainWindow extends JFrame
{
public MainWindow()
{
super("Fullscreen");
getContentPane().setPreferredSize( Toolkit.getDefaultToolkit().getScreenSize());
pack();
setResizable(false);
show();
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
Point p = new Point(0, 0);
SwingUtilities.convertPointToScreen(p, getContentPane());
Point l = getLocation();
l.x -= p.x;
l.y -= p.y;
setLocation(l);
}
});
}
...
}
You need to use the following API: http://java.sun.com/docs/books/tutorial/extra/fullscreen/index.html
Going full screen isn't as simple as making a large panel, you need to look into the underlying OS graphics. But your JPanel code should translate just fine.
I needed to search a lot, to do the same. Here is completely a working version of it by steps, so that i can find it later also, and use it.
Step 1: create a file called fullscreen.java
Step 2: copy this code and paste it as it is:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class fullscreen extends Window
{
private Button button;
public fullscreen()
{
super(new Frame());
button = new Button("Close");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
setLayout(new FlowLayout());
add(button);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(0,0,screenSize.width, screenSize.height);
}
public static void main(String[] args)
{
// This will take over your whole screen tested and works in my:
// Fedora 12/13/14
// CentOS 5.0
// if this works for you, in other platforms, please leave a comments which OS it worked.
// happy coding!
new fullscreen().setVisible(true);
}
}
Step 3: compile the code and run
Done.
If I were you I would try to make Java not draw the border of the Jframe, then make it take all the screen.
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import javax.swing.JFrame;
public class FenNoBorder extends JFrame {
public FenNoBorder () {
setUndecorated(true);
setVisible(true);
GraphicsEnvironment graphicsEnvironment=GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle maximumWindowBounds=graphicsEnvironment.getMaximumWindowBounds();
setBounds(maximumWindowBounds);
}
}

Categories

Resources