Desktop application - how do I dynamically create and destroy forms - java

I'm creating a small crypto app for the desktop using java.
I'm using JFrames (import javax.swing.JFrame) with Oracle
JDeveloper 11g under Linux.
I want to have a "welcome" form/frame where users can choose
their encryption method, and then on choosing the method,
I want to dynamically create the appropriate form for the
chosen encryption method and also destroy/free/dispose() of
the welcome form. When the user has finished their encrypting,
they should close the frame/form (either by clicking on the
x at the top right - or using the Exit button or by any
method) and the welcome frame should be dynamically recreated
and appear.
I've tried various things - btnEncode_actionPerformed(ActionEvent e)
then this.dispose() - and I've fiddled with this_windowClosed(WindowEvent e)
and dispose(), but nothing seems to work.
Even a workaround using setVisibl(true/false) would be acceptable at
this stage - this has been wrecking my head all day. It's very
easy to do in Delphi!
TIA and rgs,
Paul...

something like this usually does the trick: (Note I haven't tested this)
public class WelcomeMsg extends JFrame
.
.
.
public void btnContinue_actionPerformed(ActionEvent e)
{
this.dispose();
SwingUtilities.invokeLater(new Runnable(){ new JFrameAppropriateWindow(args) });
}
where btnContinue is the Continue button on your welcome form and JFrameAppropriateWindow is the next frame you would like to show depending on the user's choice. Args are any arguments you need to pass.
When you are ready, you can simply dispose the current frame and relaunch an instance of WelcomeMsg

I put together this simple example for creating and displaying a panel depending on a user choice.
public class Window extends JFrame {
public Window() {
this.setLayout(new BorderLayout());
JComboBox encryptionCombobox = new JComboBox();
encryptionCombobox.addItem("foo");
encryptionCombobox.addItem("bar");
//...
encryptionCombobox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// find choices and the correct panel
JPanel formPanel = new JPanel();
formPanel.setOpaque(true);
formPanel.setBackground(Color.RED);
//...
Window.this.add(formPanel, BorderLayout.CENTER);
Window.this.validate();
Window.this.repaint();
}
});
add(encryptionCombobox, BorderLayout.NORTH);
}
public static void main(String[] args) {
new Window().setVisible(true);
}
}
When I come to think about it, you should probably use a CardLayout instead, which allows you to switch between different panels (cards).

Related

Closing a JFrame Opened in Another JFrame

I am building an application which I need to open a JFrame in another JFrame while the first JFrame is disabled.
The problem is when I want to close the second JFrame I need to enable the first JFrame.
I have tried in several ways, but it is not working properly and I was not able to reach one goal in each of them. I need to reach both goals:
Disabling the first Frame when the second Frame is opened
Enabling it when the second Frame is closed.
Here is part of my code:
private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
PaymentJFrame pjf = new PaymentJFrame();
//setEnableValue(false);
//enableFrame();
this.setEnabled(false);
pjf.setVisible(true);
if (!pjf.isActive()){
this.setEnabled(true);
}
}
This code dose not enable the First Frame at all.
I have tried to use it in another way by adding an enable when the second Frame is closed but it is not working:
//Class in first Frame
private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
PaymentJFrame pjf = new PaymentJFrame();
//setEnableValue(false);
//enableFrame();
this.setEnabled(false);
pjf.setVisible(true);
}
//Class in second Frame
private void formWindowClosed(java.awt.event.WindowEvent evt) {
// TODO add your handling code here:
FinancialDocumentsJFrame.setEnableValue(true);
}
Dose any one know how can I reach these goals?
The first Frame is the main frame and the second frame is a class that I make the frame object from it in order to show and get more information from users.
I ma using netBeans IDE designer.
First of all, a Swing application should only have one JFrame, other windows can be JDialog or somethign else. As for your question, use this code as an example. It uses a listener to detect the closing event of the second window. The following code should be in the (first) JFrame (it looks like you have a button there)
private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {
JDialog paymentDialog = new JDialog();
MyFirstFrame.this.setEnabled(false);
paymentDialog.setVisible(true);
paymentDialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
MyFirstFrame.this.setEnabled(true);
}
});
}
You can create your own dialog by extending JDialog as you did with the frames, and use the custom dialog in this code. Also instead of setting the JFrame enabled or disabled, you could consider using a modal JDialog that blocks actions to the JFrame while the dialog is active.
And further still, there is the setAlwaysOnTop(boolean) for Swing windows.
use this.dispose()method JFrame has dispose() method for JFrame Close
I decided to use jDialog as it was recommended by many people on the net.
I used a jDialog and copied all the objects I had used in the second jFrame.
It worked the way I wanted it to do.
My only problem is that why java hasn't prepared a different way to answer this need.
I'm using an action listener in the first jFrame to open the second Frame which I have used jDialog for it.
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
ActivityJDialog ajdf = new ActivityJDialog(this,true);
ajdf.setVisible(true);
}
And I have copied everything I wanted to have into this jDialog.
public class ActivityJDialog extends java.awt.Dialog {
//Document Attributes
int documentStatus = -1;
int documentType = -1;
/**
* Creates new form AcrivityJDialog
* #param parent
* #param modal
*/
public ActivityJDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
/*if(false) // Full screen mode
{
// Disables decorations for this frame.
//this.setUndecorated(true);
// Puts the frame to full screen.
this.setExtendedState(this.MAXIMIZED_BOTH);
}
else // Window mode
{*/
// Size of the frame.
this.setSize(1000, 700);
// Puts frame to center of the screen.
this.setLocationRelativeTo(null);
// So that frame cannot be resizable by the user.
this.setResizable(false);
//}
}
Thank you all for helping.

Accessing a Button from another Object

I am busy doing a school project and hoped some awesome people out there could help me.
I currently have a Main, a Log in GUI and a Search frame (designed with Netbeans Gui dev).
I have an actionPerformed(ActionEvent e) method, where I am struggling is to access the Log in button that is on my Log in GUI. Currently I am doing this.
In my constructor: Declare the Frame. LogInFrame x = new LogInFrame();
In
public actionPerformed(ActionEvent eve)
{
if(eve.getSource()==x.LogInBtn())
{
x.setVisible(false);
}
}
At the moment the button isn't responding, so I was wondering if I was doing anything wrong.
The current Frame is just a standard frame. Really simple
public static void main (String[] args)
{
JFrame LogInFrame = new JFrame ("Log in");
LogInFrame.setSize (300, 300);
JButton close = new JButton ("Hid frame");
LogInFrame.getContentPane ().add (close);
}
}
Thats about everything that is needed. The problem does not lie with the GUI itself as I can run the GUI in netbeans fine. I can use the auto generated actionPerformed method of the button by double clicking on it. But i want to be able to access my GUI's compenents in my main.(tell the button what to do from my main). I have made sure that the button is public and can be accessed. I dont get any physical "coding" errors, the code just doesnt seem to be working (the button isnt responding if I add events from my main)

How do i find if a window is opened on swing

I have a problem with my application where the user will open more than one window at a time. And i have added dispose() method to call on closing the window. Now i should keep at-least one window open all the time so that the application does not hides without closed fully. If you don't understand read the following scenario:
I have window A and window B opened at the same time. Now i can close either window A or Window B but not both. In other words window B should be allowed to close only if window A is opened and vice versa. How do i do this in swing ??
A simple kind-of windowManger is not really tricky, all you need is
WindowListener which keeps tracks of the Windows it's listening to
a defined place to create the windows and register the the listener
make the windows do-nothing-on-close and make the listener responsible for the decision of whether to close or not (will do so for all except the last)
Some snippet:
// the listener (aka: WindowManager)
WindowListener l = new WindowAdapter() {
List<Window> windows = new ArrayList<Window>();
#Override
public void windowOpened(WindowEvent e) {
windows.add(e.getWindow());
}
#Override
public void windowClosing(WindowEvent e) {
if (windows.size() > 1) {
windows.remove(e.getWindow());
e.getWindow().dispose();
}
}
};
// create the first frame
JFrame frame = createFrame(l);
frame.setVisible(true);
// a method to create a new window, config and add the listener
int counter = 0;
private JFrame createFrame(final WindowListener l) {
Action action = new AbstractAction("open new frame: " + counter) {
#Override
public void actionPerformed(ActionEvent e) {
JFrame frame = createFrame(l);
frame.setVisible(true);
}
};
JFrame frame = new JFrame("someFrame " + counter++);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.add(new JButton(action));
frame.addWindowListener(l);
frame.pack();
frame.setLocation(counter * 20, counter * 10);
return frame;
}
Just a possible approach...
Create a class, call it WindowManager, that manages creation and disposal of windows.
It could for example retain the count of the windows currently open, and allow a dispose operation only if there are more than one windows "alive", otherwise show a confirm message with JOptionPane telling the user "Really close? That would terminate the application." or something like that.
The "tricky" part is that you have to do this kind of window-related operations throughout the WindowManager, otherwise everything would screw up.
Dunno if Swing has something like this built-in, I've never seen such a scenario.
simply check if the other window is open before closing with window.isVisible();

Flashing JFrame

I would like to create a JFrame with two specifal features:
JFrame should not grab focus while maximized from minimized state.
When a JFrame created or became maximized from minimized state, it should flash in the Windows bar until a user will grant a focus to it. (like as in ICQ clients ).
Does anybody know how the second requirement can be implemented?
Little self-explained example:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class JFrameTest {
private static JFrame childFrame;
public static Container getParentContentPane() {
JPanel panel = new JPanel();
JButton button = new JButton("Create\\Restore child frame");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
createOrRestoreChildFrame();
}
});
panel.add(button);
return panel;
}
private static void createOrRestoreChildFrame() {
if (childFrame == null) {
childFrame = new JFrame("Child Frame");
childFrame.setLocation(200, 200);
childFrame.add(new JLabel("Child Frame"));
childFrame.pack();
setChildFrameVisible();
} else {
setChildFrameVisible();
}
}
private static void setChildFrameVisible() {
childFrame.setFocusableWindowState(false);
childFrame.setVisible(true);
flashInWindowsBar(childFrame);
childFrame.toFront();
childFrame.setFocusableWindowState(true);
}
/**
* Should Make child frame flash in Windows bar.
* Currently, it does not work for me.
* Could anybody help me to fix this please? )
*/
private static void flashInWindowsBar(JFrame childFrame) {
childFrame.setState(JFrame.ICONIFIED);
childFrame.toFront();
}
private static void createAndShowGUI() {
JFrame parentFrame = new JFrame("JFrame Demo");
parentFrame.setLocation(100, 100);
parentFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
parentFrame.setContentPane(getParentContentPane());
parentFrame.pack();
parentFrame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Thanks!
The following code worked for me exactly as you described:
f.setState(JFrame.ICONIFIED);
f.toFront();
f is a JFrame.
Unfortunately, this isn't something that you can do natively under any Java platform. Anyone who manages to get it working by using the kind of 'trickery' that you've shown, will be disappointed to find that it is unlikely to work on another version of Windows, or even another computer with the same version of Windows. The only times I've ever seen a Java window flash is due to some glitch in Swing when minimizing all windows to the taskbar.
As this article on making Java applications feel native shows, it's the same on Mac OS.
Your best bet is to use the techniques described in the above article to make a JNI which does the Windows API call, or get a license for JNIWrapper (search for it) which does it all for you (best option if you are making a commercial app, or making it for a client who is willing to pay for such a feature). It looks like you can get a 30-day trial for that.
The only other thing I could suggest is create a poor-man's equivalent of a pop-up notification system. When you want to alert the user, create a Frame without a border, put it in the bottom-right corner of the screen, make it non-focusable and show it for a brief period of time.
The JPanel does not flash. Try it instead of JFrame.

SVG in Java not displaying correctly

Ok, I have a Java program, that displays some tiles that are SVGs in a FlowLayout. It does this by being a class ScrabbleRack, and extending JPanel, then adding JSVGCanvas tiles to this panel.
Afterwards I created a frame and added the panel, this. (packed it and displayed it). On appearing, the panel does not display properly. It just displays the first tile and then in the space where the rest of the tiles should be displayed, there is whitearea.
But if I resize the frame by any amount, the image will render correctly.
public class ScrabbleRackGUI extends JPanel{
ScrabbleRack rack=new ScrabbleRack();
JSVGCanvas rackContentsImages[]=new JSVGCanvas[8];
public ScrabbleRackGUI() {
setLayout(new FlowLayout());
createComponents();
}
public void createComponents() {
//INITIALISE SOURCE IMAGES
initImages();
for (int i=0;i<rackContentsImages.length;i++){
this.add(rackContentsImages[i]);
}
}
private void initImages(){
File tempImages[]=new File[8];
for(int i=0;i<8;i++){
tempImages[i]= new File("./src/res/rackBackground.svg");
rackContentsImages[i]=new JSVGCanvas();
try {
rackContentsImages[i].setURI(tempImages[i].toURL().toString());
} catch (MalformedURLException ex) {
Logger.getLogger(ScrabbleBoardGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void main(String args[])
{
JFrame frame = new JFrame("ScrabbleTest");
ScrabbleRackGUI rack= new ScrabbleRackGUI(1);
frame.add(rack);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(214,70);
frame.setVisible(true);
}
}
Any ideas on how I can get this panel to display properly, first time.
Or some hack that will resize it at the end of the program.
I used batik to render the SVGs in Java, for those who want to reproduce this problem.
You problem may be that the construction of your GUI is not being done on the EDT.
Your main should look something like:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyWindow window = new MyWindow();
MyWindow.setVisible(true);
}
});
}
and the rest of your code in your current main should be in the MyWindow constructor.
More detailed information can be found at http://leepoint.net/JavaBasics/gui/gui-commentary/guicom-main-thread.html (among other places)
This might be related to Batik issue 35922 reported here: https://issues.apache.org/bugzilla/show_bug.cgi?id=35922
If I understand that bug report correctly, you can workaround the problem by adding the JSVGCanvas instances (and the ScrabbleRackGUI instance) and calling pack() first, and then set the URIs on each JSVGCanvas.
First of all, you wrote:
ScrabbleRackGUI rack= new ScrabbleRackGUI(1);
and you don't have constructor that takes int.
Secondly, you're setting FlowLayout to JPanel component, and JPanel by default has FlowLayout as layout. better call super(); to get all the benefits of JPanel.
Try to run your application inside of Event Dispatching Thread (EDT), as others mentioned already.
SwingUtilities.invokeLater(new Runnable() {
// your code here
}
Also you should set your URI like this:
setURI(f.toURI().toURL().toString());
because f.toURL() is deprecated.
I hope it helps.

Categories

Resources