Passing JList value from JFrame to JDialog - java

I'm currently building an application and it has a JFrame and a JDialog. The JFrame has a JList called:
JList lstMainVenuesEvents = new JList();
And I'm trying to get the value of lstMainVenuesEvents by using:
lstMainVenuesEvents.getSelectedIndex();
I can get the value perfectly fine on my JFrame, but how do I pass it to my JDialog? I thought about creating a setter method in one of my class files and then just getting that value from my JDialog file, but surely there's an easy way? Is it possible to just have a method of some sort that passes the data from the JFrame to the JDialog like a POST request in PHP?
Apologies if I've missed anything crucial out.
Update: here's the code for my JList and JDialog show.
JList lstMainVenuesEvents = new JList();
lstMainVenuesEvents
.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
// stop from firing twice
if (e.getValueIsAdjusting()) {
EventModify evtWindow = new EventModify();
evtWindow.setVisible(true);
}
}
});

I can't be confident it's "right" but an inversion of control sort of approach usually reduces passing values around.
Assuming the value lstMainVenuesEvents.getSelectedIndex() is used on a particular action/event in the JDialog you could set an ActionListener from the JFrame.
// some where in the JFrame
jDialog.setButtonPressed(new ActionListener() {
public void actionPerformed(ActionEvent evt)
{
// lstMainVenuesEvents.getSelectedIndex() is accessible in this block
// put code logic here where
}
});

Related

How to add ActionListeners to a modal JDialog?

I wanted to create a JDialog which responds to mouse and key actions. The dialog holds a jTable where I want him to select a record. He should be able to select it by double click or by pressing a key (e.g. "2").
So I started by this:
public showDialog(TableModel model) {
super(new JFrame(), "Please select a record...");
table = new JTable(model);
//add JTable with ScrollPane
JScrollPane scrollPane = new JScrollPane();
scrollPane.setPreferredSize(new Dimension(800, Math.min(table.getPreferredSize().height+60, 800)));
scrollPane.getViewport().add(table);
add(scrollPane);
//display
setAlwaysOnTop(true);
toFront();
pack();
setVisible(true);
//mouse
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
System.out.println("clicked");
}
});
//keys
table.addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(java.awt.event.KeyEvent evt) {}
#Override
public void keyReleased(java.awt.event.KeyEvent evt) {}
#Override
public void keyPressed(java.awt.event.KeyEvent evt) {
System.out.println(evt.getKeyChar() + " pressed");
}
});
}
This works flawlessly.
However if I do the same thing with the statement setModal(true);, the listeners stop working.
How can I make my JDialog modal without losing the functionality of my listeners?
Simple solution: when the JDialog is modal, then setVisible() blocks the current thread, i.e. the Dialog's Constructor. Thus the Listeners are never added (actually only when the Dialog is closed). Therefore no events.
Solution: set 'setVisible(true);' to the end of the CTOR
BTW you should not to modal locking in the CTOR, having an extra method like 'void showTheDialog();' is better.
If you had done this from the beginning, the listeners would have been there and everything would have worked ;-)
Edit: Or use something like a Factory method, that's even better.
BTW PLEASE PLEASE stick to naming conventions, it took me 10 seconds to figure out that with 'public showDialog(TableModel model) {' you had not forgotten the method return type but that this would actually have been the CTOR itself :-)
I think this can cause a problem:
super(new JFrame(), "Please select a record...");
Why are you creating a new JFrame, you have to specify an existing one.
Btw, you should call super in constructor of your class which extends JDialog, not in some other method.
remove MouseListener is useless for your goal
remove KeyListener is useless for your goal
set proper ListSelectionMode to JTable
add ListSelectionListener to JTable

Communicating between JPanels

First off, I'm new to Java, so please be gentle.
I have a JFrame which has two 'JPanels', one of which is a separate class (i've extended the JPanel). Ideally I'd like to 'dispatch and event' or notify the other JPanel object on the JFrame.
I have an array of JButtons in the custom JPanel class, which i'd like to add an event listener to. Upon clicking the JButton, i'd like to change something on the other JPanel.
I'm really not sure how to do this, so I moved the event handler into the JFrame class, and tried to do the following:
panel.buttonArray[i][j].addActionListener(this);
However, doing that didn't work at all. Annoyingly, Eclipse didn't complain either...
Any tips on how I can achieve this?
This was horribly explained, sorry.
Think of this not in terms of panels but in terms of objects. As long an object, lets say it has a name of object77, has a reference to the other object, call it object42, object77 can call methods on object42.
object77.methodInObject42();
panel77.methodInPanel42();
As for the event handler, then
buttonOnPanelXX.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
panel77.methodInPanel42();
}});
or even better...
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
panel77.methodInPanel42();
}});
}});

Performing action when closing JFrame

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.

How can I return a value from a JDialog box to the parent JFrame?

I have created a modal JDialog box with a custom drawing on it and a JButton. When I click the JButton, the JDialog box should close and a value should be returned.
I have created a function in the parent JFrame called setModalPiece, which receives a value and sets it to a local JFrame variable.
The problem is that this function is not visible from the JDialog box (even though the JDialog box has a reference to the parent JFrame).
Two questions:
1) Is there a better way to return a value from a JDialog box to its parent JFrame?
2) Why can't the reference to the JFrame passed to the JDialog be used to access my JFrame function setModalPiece?
I generally do it like this:
Dialog dlg = new Dialog(this, ...);
Value result = dlg.showDialog();
The Dialog.showDialog() function looks like this:
ReturnValue showDialog() {
setVisible(true);
return result;
}
Since setting visibility to true on a JDialog is a modal operation, the OK button can set an instance variable (result) to the chosen result of the dialog (or null if canceled). After processing in the OK/Cancel button method, do this:
setVisible(false);
dispose();
to return control to the showDialog() function.
You should do the opposite by adding a custom method getValue() to your custom JDialog.
In this way you can ask the value of the dialog from the JFrame instead that setting it by invoking something on the JFrame itself.
If you take a look at Oracle tutorial about dialogs here it states
If you're designing a custom dialog, you need to design your dialog's API so that you can query the dialog about what the user chose. For example, CustomDialog has a getValidatedText method that returns the text the user entered.
(you can find source of CustomDialog to see how they suppose that you will design your custom dialog)
I don't know if I can explain my method in a cool way...
Let's say I need productPrice and amount from a JDialog whos going to get that info from user, I need to call that from the JFrame.
declare productPrice and ammount as public non-static global variables inside the JDialog.
public float productPrice;
public int amount;
* this goes inside the dialog's class global scope.
add these lines in the JDialog constructor to ensure modality
super((java.awt.Frame) null, true);
setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
* this goes within the dialog's class constructor
let's say your JDialog's class name is 'MyJDialog' when calling do something like this
MyJDialog question = new MyJDialog();
MyJDialog.setVisible(true);
// Application thread will stop here until MyJDialog calls dispose();
// this is an effect of modality
//
// When question calls for dispose(), it will leave the screen,
// but its global values will still be accessible.
float myTotalCostVar = question.productPrice * question.ammount;
// this is acceptable.
// You can also create public getter function inside the JDialog class,
// its safer and its a good practice.
* this goes in any function within your JFrame and will call JDialog to get infos.
When you pass any value to JFrame to JDialog then create parametrized constructor of jdialog and in jframe whenever you want to call.
e.g. The parametrized constructor like :
public EditProduct(java.awt.Frame parent, boolean modal, int no) {
//int no is number of product want to edit.
//Now we can use this pid in JDialog and perform whatever you want.
}
When you want to pass values from JDialog to JFrame create a bean class with set and get method the the values using vector and get these values in jframe.
More info
Here is how I usually do it. I wasn't sure, that's why I've created that post:
Returning value from JDialog; dispose(), setVisible(false) - example
Add an interface to your constructor?
public class UploadConfimation extends JDialog {
private final JPanel contentPanel = new JPanel();
public interface GetDialogResponse{
void GetResponse(boolean response);
}
/**
* Create the dialog.
*/
public UploadConfimation(String title, String message, GetDialogResponse result) {
setBounds(100, 100, 450, 300);
setTitle(title);
getContentPane().setLayout(new BorderLayout());
contentPanel.setLayout(new FlowLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
{
JLabel lblMessage = new JLabel(message);
contentPanel.add(lblMessage);
}
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("YES");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
result.GetResponse(true);
dispose();
}
});
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("NO");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
result.GetResponse(false);
dispose();
}
});
buttonPane.add(cancelButton);
}
}
}
}

Desktop application - how do I dynamically create and destroy forms

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).

Categories

Resources