I'm porting an existing application over to netbeans platform, and while I will probably change some of the existing dialogs to the new notify methods, some of the dialogs are quite complex (multiple panels etc) and I would rather not port them, at least not yet. I found out how to get the mainframe,
mainFrame = (JFrame) WindowManager.getDefault().getMainWindow();
But I have no idea what to use for the .getApplication().show()
public void configScoreboard() {
if (!in_race) {
if (CSBox == null) {
CSBox = new SBconfig(mainFrame, true);
CSBox.setLocationRelativeTo(mainFrame);
}
Sst01App.getApplication().show(CSBox);
}
}
The Sst01App of course does not exist in my new Netbeans Platform App and I can't seem to find the app (I think I tried all of the varaibles)
Found it under DialogDescriptor documentation after lots more searching...
https://ui.netbeans.org/docs/ui_apis/dide/index.html
Where I figured out how to create the custom dialog that I could decorate, The .show() method was still a problem, but I found the DialogDisplayer would work with the object I created. So done.
Dialog sb2Dlg = DialogDisplayer.getDefault().createDialog(sb2);
Still having lots of fun with borderless and full screen, but thats another topic.
class MyPanel extends javax.swing.JPanel implements java.awt.event.ActionListener {
//buttons, fields, labels, etc.
...
public void requestFocus () { //set focus for one components
myField.requestFocus ();
}
...
public void actionPerformed(final java.awt.event.ActionEvent ap) { // handling code for buttons
...
}
}
MyPanel mp = new MyPanel(); // create new MyPanel
Object [] options = { new JButton ("Choice 1"),
new JButton ("Choice 2")};
DialogDescriptor dd = new DialogDescriptor (mp,
"Text in title",
true,
options,
null,
DialogDescriptor.DEFAULT_ALIGN,
null,
mp); //create new modal DialogDescriptor with defined ActionListener
mp.requestFocus(); // set focus to component which was specified in MyPanel's requestFocus() method
TopManager.getDefault ().createDialog (dd).show (); //show dialog
Related
I have a class BaseWindow with a JFrame mainFrame, and a bunch of methods that work on mainFrame. Actual windows in my app are made by extending BaseWindow.
The class extending BaseWindow inherits mainFrame, and that somehow prevents window builder from "seeing" it when it parses the code. All I see in window builder's design tab is an empty window, but when I run the code everything works fine.
How can I make this approach work with window builder, or "trick" window builder into parsing mainFrame? Here is an example class extending BaseWindow:
package GUIApp;
//took out the imports to save space
class SampleWindowOne extends BaseWindow{
public JLabel txtSampleText;
public JButton btnMagicButton;
public SampleWindowOne() {
initialize();
}
public void run(){
mainFrame.setBounds(getCenteredBounds());
mainFrame.setVisible(true);
}
private void initialize() {
mainFrame = new JFrame();
mainFrame.setBounds(100,100,700,525);
mainFrame.setTitle("Sample Window One");
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.getContentPane().setLayout(null);
txtSampleText = new JLabel();
txtSampleText.setFont(new Font("Dialog", Font.PLAIN, 25));
txtSampleText.setHorizontalAlignment(SwingConstants.CENTER);
txtSampleText.setText("Sample Window");
txtSampleText.setBounds(12, 50, 674, 51);
mainFrame.getContentPane().add(txtSampleText);
JTextArea txtrLoremIpsumDolor = new JTextArea();
txtrLoremIpsumDolor.setEditable(false);
txtrLoremIpsumDolor.setFont(new Font("Dialog", Font.PLAIN, 16));
txtrLoremIpsumDolor.setForeground(Color.DARK_GRAY);
txtrLoremIpsumDolor.setWrapStyleWord(true);
txtrLoremIpsumDolor.setLineWrap(true);
txtrLoremIpsumDolor.setText("Lorem ipsum dolor sit amet...");
txtrLoremIpsumDolor.setBounds(57, 131, 609, 296);
mainFrame.getContentPane().add(txtrLoremIpsumDolor);
btnMagicButton = new JButton("End Program");
btnMagicButton.setEnabled(false);
btnMagicButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
requestTerminate();
}
});
btnMagicButton.setBounds(257, 451, 175, 25);
mainFrame.getContentPane().add(btnMagicButton);
}
}
I'm sure you're past that now, but for others searching solution to this:
In eclipse go to:
Window -> Preferences -> Window Builder(tree) -> Swing -> Code Generation
Set initGUI method from the combo box of "Method name for new statements" at the top of the page. (you can also try to set another method name)
In "Variable generation" section, click once on third tab: "Init. Field" so that you can see its' square filled with v sign(and the other tabs have an empty square).
Click ok.
Restart eclipse.
Create a method named initGUI as follows:
private void initGUI() {
}
Copy all your code from the constructor to that method.
Call that method from your constructor:
public WindowTest()
{
initGUI();
}
Go to window builder design by clicking: "Design" at the bottom of the editor.
Click a lot of reparse if necessary.
Now add one component (JButton for instance) to the window, and watch it go into iniGUI method. Once you've seen that happens - it is safe to take out code lines that are not realted to GUI from that method and put them in the constructor if you want.
Okay, I found a way to trick window builder into working! I changed the constructor from:
public SampleWindowOne() {
initialize();
}
to:
public SampleWindowOne() {
JFrame mainFrame;
initialize();
}
Hopefully this helps someone with their own code.
Edit: not fully solved after all, see below. I will update if I find a better solution.
Edit2: Okay, after a good night's sleep the solution is pretty obvious. I now declare a separate JFrame at the beginning of the class. I add all my elements to this frame instead of mainFrame, and at the end of initialize I put
mainFrame = newFrame;
I just created a GUI, now I want to create another GUI and link both together.
So on the first GUI when the user selects 'next' button, the second GUI is displayed.
For this, do I have to create a new class and just create a GUI again?
Here is what I have now:
import java.awt.Color;
import javax.swing.*;
public class Wizard {
private JLabel lblPicture;
private JRadioButton btLdap, btKerbegos, btSpnego, btSaml2;
private JButton btNext;
private JPanel panel;
public static void main(String[] args) {
new Wizard();
}
public Wizard() {
JFrame frame = new JFrame("Wizard");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,360);
frame.setVisible(true);
MyPanel();
RadioButtons();
Button();
Image();
groupButton();
frame.add(panel);
frame.setVisible(true);
}
public void MyPanel() {
panel = new JPanel();
panel.setLayout(null);}
public void RadioButtons() {
btLdap = new JRadioButton ("Ldap");
btLdap.setBounds(60,85,100,20);
panel.add(btLdap);
btKerbegos = new JRadioButton ("Kerbegos");
btKerbegos.setBounds(60,115,100,20);
panel.add(btKerbegos);
btSpnego =new JRadioButton("Spnego");
btSpnego.setBounds(60,145,100,20);
panel.add(btSpnego);
btSaml2 = new JRadioButton("Saml2");
btSaml2.setBounds(60,175,100,20);
panel.add(btSaml2);
}
public void Button() {
btNext = new JButton ("Next");
btNext.setBounds(400,260,100,20);
panel.add(btNext);
}
public void Image() {
ImageIcon image = new ImageIcon("image.jpg");
lblPicture = new JLabel(image);
lblPicture.setBounds(200,20, 330, 270);
panel.add(lblPicture);
}
private void groupButton() {
ButtonGroup bg1 = new ButtonGroup( );
bg1.add(btLdap);
bg1.add(btKerbegos);
bg1.add(btSpnego);
bg1.add(btSaml2);
}
}
To display another window, you would create the window, be it a JFrame, JDialog, or what have you, and call setVisible(true) just like you do for your first window.
You ask if your other "window" should be in another class, and likely that answer is yes. Since it will have a completely different set of behaviors and goals from the first class, better to separate out concerns.
Having said that, what you plan to do, to show multiple windows is not always the best user interface design. Better often is to show multiple views using a container that uses a CardLayout.
If you want to display another window in a modal fashion, that is, have the first window wait for the second window to be processed before allowing user interaction, the second window should be a modal JDialog or JOptionPane (a JDialog in disguise).
I think for what you want to achieve, the use of a CardLayout would be appropriate.
This enables you to have multiple panels within the one frame with only one panel visible at a time and has functionality to 'flip' through the panels like a 'deck of cards'. So on initialising your frame you create the panels you want, and specify which one to start at then your next button will go to the next panel in the list.
See the tutorial here there are also some video tutorials available on youtube.
Write the two GUI's in different classes. When you start your program, start the first GUI.
FirstGUI frame1 = new FirstGUI("Title text");
frame1.setVisible(true);
Then, in the action listener code for the button you call "next"...
frame1.setVisible(false); //if you want to save the frame
frame1.dispose(); //if you want to kill the frame
SecondGUI frame2 = new SecondGUI("Title text");
frame2.setVisible(true);
I'm trying to change content dynamically based on a JRadioButton selection... My simplified code looks something like this.
//import
public class Thing {
//
JPanel pnlMain, pnl1, pnl2, pnlRt, pnlLt;
JRadioBtn btn1, btn2;
//
Thing () {
//
//initialize panels, add to them, etc.
pnlMain.add(pnlLt);
pnlMain.add(pnl1);
pnlMain.add(pnlRt);
//
//Get it showing and stuff.
//
}
//
//One instance of this class connected to all radio buttons.
class Evt implements ActionListener {
public void actionImplemented (ActionEvent evt) {
//
pnlMain.remove(1);
//
if (evt.getActionCommand().equals("Radio 1"))
pnlMain.add(pnl1);
else pnlMain.add(pnl2);
//
pnlMain.validate();
//
}
}
//
public static void main (String[] args) {
new Thing();
}
//
}
This lets me change panels, but i cannot change back to a panel i had previously selected... I don't understand why. Please help!!!
You should be using CardLayout instead, as this is exactly what that is for. Check out the tutorial here.
Use a proper layout manager. In this scenario, I recommend using CardLayout. This enables the developer to delegate the "complexity" of panel exchanging to the layout manager, which is how it should be.
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.