Strange tab-order with editable JComboBoxes - java

I've got a JFrame that looks like this:
It's got two JTextFields on it, one JComboBox between them and a JPanel at the bottom (that you can't see).
One of the features of the JComboBox is that it can be given a custom editor. These implement the ComboBoxEditor interface. In each of the following three cases, the GUI looks exactly the same, and I would have expected them all to behave exactly the same:
I do not specify a custom editor, and use the default one.
I create a custom editor whose editor component is a JTextField.
I create a custom editor whose editor component is a JPanel with a JTextField on it (using a BorderLayout).
When the editor for the editable combo box is set to the default, pressing Tab moves the focus from the top JTextField into the editing area on the JComboBox and then into the other JTextField. If I create a custom editor whose editor component is a JTextField and otherwise does what you would expect, the same thing happens.
BUT, if I instead create a custom editor whose editor component is a JPanel with a JTextField added to it, the focus makes one additional stop. If the focus is on the top JTextField, then pressing Tab moves the focus to the little arrow at the right of the editable combo box before moving into the text area.
Why is this happening? The focus never moves on to the JPanel at the bottom of the frame, so why does the presence of a JPanel holding the JTextField affect the tab order on the combo box?
The following is an S(-ish)SCCE, which has one text field and all three types of combo box on it:
import javax.swing.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
public class ComboBoxTest extends JFrame
{
private JPanel layoutPanel;
private JTextField meaninglessTextField;
private JComboBox defaultEditorComboBox;
private JComboBox textFieldEditorComboBox;
private JComboBox panelEditorComboBox;
public ComboBoxTest()
{
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
layoutPanel = new JPanel();
layoutPanel.setLayout(new BoxLayout(layoutPanel, BoxLayout.Y_AXIS));
meaninglessTextField = new JTextField();
defaultEditorComboBox = new JComboBox(); // Just a default JComboBox.
defaultEditorComboBox.setEditable(true);
textFieldEditorComboBox = new JComboBox();
textFieldEditorComboBox.setEditable(true);
textFieldEditorComboBox.setEditor(new TextFieldEditor());
panelEditorComboBox = new JComboBox();
panelEditorComboBox.setEditable(true);
panelEditorComboBox.setEditor(new PanelEditor());
layoutPanel.add(Box.createRigidArea(new Dimension(500,0)));
layoutPanel.add(meaninglessTextField);
layoutPanel.add(defaultEditorComboBox);
layoutPanel.add(textFieldEditorComboBox);
layoutPanel.add(panelEditorComboBox);
Container contentPane = getContentPane();
contentPane.add(layoutPanel, BorderLayout.CENTER);
pack();
}
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run()
{
new ComboBoxTest().setVisible(true);
}
});
}
private class PanelEditor extends JPanel implements ComboBoxEditor
{
public JTextField inputTextField = new JTextField();
public PanelEditor()
{
setLayout(new BorderLayout());
add(inputTextField, BorderLayout.CENTER);
}
#Override
public String getItem()
{
return inputTextField.getText();
}
#Override
public void setItem(Object newText)
{
if (newText != null) {
inputTextField.setText(newText.toString());
}
else {
inputTextField.setText("");
}
}
#Override
public Component getEditorComponent()
{
return this;
}
#Override
public void removeActionListener(ActionListener listener)
{
inputTextField.removeActionListener(listener);
}
#Override
public void addActionListener(ActionListener listener)
{
inputTextField.addActionListener(listener);
}
#Override
public void selectAll()
{
inputTextField.selectAll();
}
}
private class TextFieldEditor extends PanelEditor implements ComboBoxEditor
{
// The same, except that the editor component is now just the JTextField
// rather than the whole panel.
public TextFieldEditor()
{
}
#Override
public JTextField getEditorComponent()
{
return inputTextField;
}
}
}
Note: this behaviour becomes a problem if I want to add a JLabel to the editor. Then I have to put a JPanel there to hold both the label and the text field.

The basic problem is that the combo's ui delegate can't handle compound editor components. There are several places where it assumes that the editor component is the target of whatever configuration it needs to do. The concrete mis-behaviour here is that it explicitly sets the editor's focusability to that of the combo itself
// in BasicComboBoxUI
protected void configureEditor() {
....
editor.setFocusable(comboBox.isFocusable());
....
]
The implications
by default, the panel's focusable is true because the combo's is true
forcing the panel's focusable to false in its constructor has no effect (the ui resets it later on and whenever the LAF is switched)
disabling combo's focusable disables the panel's as well
To fix on the level of the editor, you can implement its isFocusable to return false unconditionally:
private class PanelEditor extends JPanel implements ComboBoxEditor
public boolean isFocusable() {
return false;
}
...
}
An aside: for code hygiene, better not extend a view to implement its role as ComboBoxEditor (even though here you need a subclassed JPanel to avoid the problem, so it's arguably borderline :-) - instead implement the editor and let it use the tweaked panel.
Also beware that you might stumble into more problems with the compound editor (check the code of BasicComboUI for more places where it assumes a plain childless component), so you might consider not doing it at all but think of a different way to achieve your requirement.

Try this:
public PanelEditor()
{
// other code...
addFocusListener(new FocusAdapter()
{
#Override
public void focusGained(FocusEvent e)
{
inputTextField.requestFocusInWindow();
}
});
}

The focus isn't transferring to the JPanel; it's transferring to the JComboBox itself.
You can stop a component from receiving the focus by using its setFocusable method. If you add the line
setFocusable(false)
to the constructor of the PanelEditor in the example above, then the strange behaviour is still there, since the PanelEditor implements JPanel, so the setFocusable method of the JPanel overrides that of the JComboBox. Since the setFocusable method of a JPanel essentially does nothing, nothing changes.
If instead you add the line
panelEditorComboBox.setFocusable(false)
to the constructor of the JFrame itself then the JComboBox will not be able to receive the focus, but the JTextField inside the editor will. This isn't a perfect fix, since it would be better if the editor itself were responsible for turning off the focusability of the JComboBox, so you could always pass in the parent JComboBox as a parameter to the constructor of the editor, and have the focusability turned off there.
I don't know why the behaviour is different when you've got a JTextField as the editor. Some weird Swing thing.

Related

Java Swing: Controlling focus with textfield and autocompletion dialog/menu

I have a JTextField that I'm trying to add an autocompletion menu to. But I'm having issues with how I should handle the focus.
Here's a SSCCE
package test;
import java.awt.Point;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class SSCCE extends JFrame implements DocumentListener {
private AutocompletionDialog dialog;
public SSCCE() {
dialog = new AutocompletionDialog ();
JTextField textField = new JTextField(20);
textField.getDocument().addDocumentListener(this);
add(textField);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SSCCE().setVisible(true);
}
});
}
public void insertUpdate(DocumentEvent e) {
Point p = this.getLocationOnScreen();
dialog.setLocation(p.x, p.y + 50);
dialog.setVisible(true);
}
public void removeUpdate(DocumentEvent e) { }
public void changedUpdate(DocumentEvent e) { }
private class AutocompletionDialog extends JDialog {
JList<String> list = new JList<>(
new String[] { "One", "Two", "Three" });
AutocompletionDialog() {
setSize(100, 100);
add(list);
}
}
}
Of course there's more logic to it in the real program, but the issue I'm having is that I want to show the autocompletion dialog/menu, but still be able to continue typing in the text field. At the same time, I also want to be able to navigate the menu with the up/down arrows and the enter key, as well as with the mouse, to select one of the completion options.
Can someone please help me with how I should proceed here? Thanks!
EDIT:
Thanks to #camickr's reply I played around a bit with setFocusableWindowState together with an InputMap/ActionMap to always keep the focus in the text field, and manually control the selected list item. The problem is that you get a visual difference when doing it that way compared to if the list had proper focus. See the screen shots.
This is what it looks like if I don't mess with the focus (this is what I want).
This is what it looks like if I run setFocusableWindowState(false)
The main differences are the highlight border (darker blue) around the selected list item, but also the blue highlight around the entire dialog. Then there's also the differences in the title bar.
(Don't mind the render artifacts, I'm connecting to a three year old virtual Linux installation using an old NX client)
EDIT 2:
I was afraid that it was the Look and Feel or OS that determined how the selected list item should look (with the highlighted border for example). But it turns out that it is indeed just the cell renderer that makes that call. Knowing that I felt much better about writing my own cell renderer, and I now have a solution that I'm happy with.
This is the code I ended up using:
private class CellRenderer extends DefaultListCellRenderer
{
#Override
public Component getListCellRendererComponent(
JList<?> jlist, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(
jlist, value, index, isSelected, cellHasFocus);
if (isSelected) {
Border border = UIManager.getBorder(
"List.focusSelectedCellHighlightBorder");
if (border == null) {
border = UIManager.getBorder(
"List.focusCellHighlightBorder");
}
setBorder(border);
}
return this;
}
}
As I show the auto completion menu the focus is given to that dialog.
To prevent focus from going to the popup window you can use:
JDialog dialog = new JDialog(...);
dialog.setFocusableWindowState( false );
...
dialog.setVisible( true );
I also want to be able to navigate the menu with the up/down arrows and the enter key
Then you need to override the default Actions provided by the text field. Check out Key Bindings for more information.
You can also check out: button highlighting using keyboard keys where I just provided a simple example of implementing an Action.

mouseEntered and mouseExited method questions

Working on a homework assignment and I'm having issues with figuring out how to print a line of text when a mouse cursor enters and exits a certain colored area (a JPanel called panel in this case) while using the MouseListener interface.
I choose a color from the bottom panel (either Red, blue, or yellow) and then when I move to the upper panel it should be able to print which color the mouse has entered in while the mouse is in the panel and which color I exited from when my mouse finds itself outside of said panel...
Hopefully that makes sense. Here's a code snippet of what I have so far. This is for the color RED:
class RedButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
panel.setBackground(Color.RED);
class RedMouseListener implements MouseListener
{
public void mouseEntered(MouseEvent event)
{
}
public void mouseExited(MouseEvent event)
{
}
public void mousePressed(MouseEvent event) { }
public void mouseReleased(MouseEvent event) { }
public void mouseClicked(MouseEvent event) { }
}
}
}
ActionListener redListener = new RedButtonListener();
bRed.addActionListener(redListener);
Here's a relevant question from Stack Overflow Mouse moved event within JPanel
I'd recommend once you ensure that triggers are being correctly listened to (try printing "Hello World") From there you need to get the communication of the color state within the mouse event. If everything is within the same instance you can just access the variables needed within the event listener.
Here are the docs on MouseEvent http://docs.oracle.com/javase/7/docs/api/java/awt/event/MouseEvent.html
Make sure you added the mouse listener try the following
panel.addMouseListener(new RedMouseListener());
start simple making the following work
public void mouseEntered(MouseEvent event)
{
System.out.println("Hello World!");
}
if you need to access the color of the panel within the event listener try the following snippet
panel.getBackground();
This returns a Color object.
Its worth mentioning the extra class declaration can be avoided by using an anonymous inner class. see How are Anonymous (inner) classes used in Java? These overridden methods are essentially a sub class of MouseListener but we don't need to call it by name.
panel.addMouseListener(new MouseListener(){
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseClicked(MouseEvent e) {}
});
Introduction
Since this is such an old question, I thought I'd put together a simple Swing GUI to illustrate how a MouseListener works.
Here's the GUI before I do anything.
The main panel in the center will take on the selector color when the mouse is moved into the selection area. The main panel will return to it's original color when the mouse is moved out of the selection area.
Here's the GUI when my mouse is in the blue selection area.
Explanation
If you're not familiar with Java Swing, Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
When I create a Swing GUI, I use the model/view/controller (MVC) pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.
The MVC pattern implies that you create the model first, then the view, then the controller. This is more of an iterative process than a waterfall.
In Java Swing, the MVC pattern means:
The view reads information from the model.
The view may not update the model.
The controller updates the model and repaints / revalidates the view.
The model consists of one or more plain Java getter/setter classes.
The view consists of a JFrame and however many JPanels it takes to create the GUI.
There's usually not one controller "to rule them all". Each listener acts as an independent controller to manage its part of the model and view.
This is a simple application, so it consists of two model classes, one view class, and one controller class. The model is not updated at all in this example.
I did not code this entire application at one time. I wrote a few lines of code and ran tests. I made lots of changes to the code before I was satisfied with how it worked.
Model
The ColorSelection class is a plain Java getter/setter class that holds the color name, background color, and foreground color.
The MouseMovementModel class is a plain Java getter/setter class that holds the ColorSelection instances. The GUI builds the selection JPanel based on this information. If you want to add another selection color, you would add it here.
View
The view consists of a JFrame, a selection JPanel, and the main JPanel.
The JFrame has a default BorderLayout. The selection JPanel goes into the NORTH section and the main JPanel goes into the CENTER section. Only one component can be placed in a section. That component is usually a JPanel.
The selection JPanel uses a FlowLayout to hold the color selection JPanels. The color selection JPanels are created based on the number of ColorSelection instances in the application model.
A color selection JPanel is a simple JPanel created to use the information from a ColorSelection instance.
The main JPanel is a simple JPanel that will show a background color. The controller will be responsible for changing the background color.
Controller
The ColorListener class extends a MouseAdapter. The MouseAdapter class implements the MouseListener, MouseMotionListener, and MouseWheelListener interfaces. Using the MouseAdapter class allows me to implement just the mouse listener methods I'm writing code for.
The mouseEntered method sets the main JPanel to the ColorSelection color. The code is really simple. It updates the view with the ColorSelection background color.
The mouseExited method sets the main JPanel back to its original color.
Code
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MouseMovementExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new MouseMovementExample());
}
private final JPanel mainPanel;
private final JPanel[] colorPanel;
private final MouseMovementModel model;
public MouseMovementExample() {
this.model = new MouseMovementModel();
this.mainPanel = createMainPanel();
this.colorPanel = new JPanel[model.getSelections().length];
}
#Override
public void run() {
JFrame frame = new JFrame("Mouse Movement Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createSelectionPanel(), BorderLayout.NORTH);
frame.add(mainPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createSelectionPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
ColorSelection[] selections = model.getSelections();
for (int index = 0; index < selections.length; index++) {
ColorSelection selection = selections[index];
ColorListener listener = new ColorListener(this, selection);
colorPanel[index] = createColorPanel(selection, listener);
panel.add(colorPanel[index]);
}
return panel;
}
private JPanel createColorPanel(ColorSelection selection, ColorListener listener) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(selection.getBackgroundColor());
panel.addMouseListener(listener);
panel.setPreferredSize(new Dimension(200, 100));
JLabel label = new JLabel(selection.getColorName());
label.setFont(panel.getFont().deriveFont(Font.BOLD, 36f));
label.setForeground(selection.getForegroundColor());
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label, BorderLayout.CENTER);
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
return panel;
}
public Color getMainPanelBackground() {
return this.mainPanel.getBackground();
}
public void setMainPanelBackground(Color color) {
this.mainPanel.setBackground(color);
}
public class ColorListener extends MouseAdapter {
private final Color originalBackgroundColor;
private final ColorSelection selection;
private final MouseMovementExample view;
public ColorListener(MouseMovementExample view, ColorSelection selection) {
this.view = view;
this.selection = selection;
this.originalBackgroundColor = view.getMainPanelBackground();
}
#Override
public void mouseEntered(MouseEvent e) {
view.setMainPanelBackground(selection.getBackgroundColor());
}
#Override
public void mouseExited(MouseEvent e) {
view.setMainPanelBackground(originalBackgroundColor);
}
}
public class MouseMovementModel {
private final ColorSelection[] selections;
public MouseMovementModel() {
this.selections = new ColorSelection[3];
this.selections[0] = new ColorSelection("Red", Color.RED, Color.WHITE);
this.selections[1] = new ColorSelection("Green", Color.GREEN, Color.BLACK);
this.selections[2] = new ColorSelection("Blue", Color.BLUE, Color.WHITE);
}
public ColorSelection[] getSelections() {
return selections;
}
}
public class ColorSelection {
private final Color backgroundColor, foregroundColor;
private final String colorName;
public ColorSelection(String colorName, Color backgroundColor, Color foregroundColor) {
this.colorName = colorName;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public Color getForegroundColor() {
return foregroundColor;
}
public String getColorName() {
return colorName;
}
}
}

Java first GUI, two classes

I'm trying to program my first GUI-class in Java, using the Window Builder. Ok, the GUI is ready but has no functions yet (it contains 10 checkboxes (yes, they are all neccessary) and 2 buttons and a JTextField, so nothing special). So I just drag'n'dropped the checkboxes and button into the window, I haven't coded anything yet.
I have two classes:
GUI.java -> only for the layout
Main.java -> should get 'inputs' from GUI.java
Now the user should check or uncheck the checkboxes and then finally press a button.
But how do I 'read out' if a checkbox is checked or not - I have two classes?
I have to add that I'm a beginner to Java and especially to GUI-programming, but I just want to learn it. I would be happy to receive some help but NOT the complete code.
Basically you instantiate an object of your GUI from the Main.java. Then you have access to this GUI (assumed you have setter/getter-methods or the Components in the GUI are public). In the GUI constructor you call all builder methods, so when you then call new GUI() from Main.java, you got a) the GUI running and b) access to it from Main.java
For your specific question about the checkboxes, you can call
nameOfCheckbox.isSelected()
which returns a boolean wheter the checkbox is checked or not.
Viceversa: since your Main.java has (or should have) static methods (like the main-method), you can then simply call Main.anyMethodName() from GUI.java (assuming this anyMethod is static) and pass data from the "visual area" to the "logic area" (it is recommended to seperate this two componentes as good as possible).
I know you said you didn't want the full, code but this isn't really it, just a very basic working demo of what you want to do
Gui.java
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Gui {
JFrame frame;
JButton button;
JCheckBox checkBox;
JLabel label;
public Gui() {
frame = new JFrame("demo");
button = new JButton("is it checked?");
checkBox = new JCheckBox();
label = new JLabel("no");
JPanel panel = new JPanel();
panel.add(checkBox);
panel.add(button);
panel.add(label);
frame.add(panel);
frame.pack();
//frame.setSize(200, 60);
frame.setResizable(false);
frame.setLocation(400, 400);
frame.setVisible(true);
}
// method to add an action listener to the gui's
// private button
public void setButtonActionListener(ActionListener al) {
button.addActionListener(al);
}
// gui method to check if box is checked
public boolean isBoxChecked() {
return checkBox.isSelected();
}
// method to set lable
public void setText(String text) {
label.setText(text);
}
}
Main.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main {
public static void main(String[] args) {
// create an instance of your gui class
final Gui gui = new Gui();
// add the action listener to the button
// notice how we reference the gui here by running the methods in the
// gui class
// this action listener could be created in the gui
// class but in general you don't want to do that because actions will
// involve multiple classes
gui.setButtonActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
gui.setText((gui.isBoxChecked() ? "yes" : "no"));
}
});
}
}
Attach an ItemListener.
You can determine if the box is rising (unchecked to checked) or falling (checked to unchecked) with the following line in itemStateChanged(ItemEvent e)
boolean selected = e.getStateChange() == ItemEvent.SELECTED;
To determine whether it is checked when it is not changing, just use isSelected()
Either like that:
checkbox.isSelected();
Or this would be a way by an Itemlistener which will be called if there is a change:
checkbox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.DESELECTED) {
foo = false;
} else {
foo = true;
}
}
});
You could expose all of your gui objects as fields in your gui class
public JTextField getNameTextField() {
return nameTextField;
}
public JCheckBox getCheckBox1() {
return checkBox1;
}
and then in main:
if (gui.getCheckBox1().isSelected())
// do stuff
Assuming your checkbox is an object named "myCheckBox", you can check if it's selected or not by using:
myCheckBox.isSelected()
Returns true if the checkbox is selected.
I reccomend you to check Java's tutorials on how to use the various GUI components, e.g:
http://docs.oracle.com/javase/tutorial/uiswing/components/button.html

Problem updating JPanel in JDialog with JComboBox

I have created a JDialog which contains a JComboBox and a panel underneath which should display a different content based on the value selected in the JComboBox. I have created a JPanel (panel_1) which is added to the content pane of the dialog and an additional JPanel for each of the possible items in the JComboBox (for example panel_item_1 and panel_item_2 if it does have only 2 items). I have attached the following listener class in the JComboBox:
public class SelectedListener implements ActionListener {
private SettingsDialog dialog;
public SelectedListener(SettingsDialog dialog){
this.dialog = dialog;
}
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String selected_settings = (String)cb.getSelectedItem();
if(selected_settings.compareTo("Option 1") == 0){
dialog.panel_1 = dialog.panel_item_1;
dialog.panel_1.updateUI();
}else if(selected_settings.compareTo("Option 2") == 0 ){
dialog.panel_1 = dialog.panel_item_2;
dialog.panel_1.updateUI();
}
}
}
However this doesn't make the panel update with the new content. Any suggestion? Thanks in advance
which should display a different content based on the value selected in the JComboBox.
Read the section from the Swing tutorial on How to Use Card Layout which has a working example that does exactly what you want.
Edit:
dialog.panel_1 = dialog.panel_item_1;
The real problem is that you can't just change the reference to a variable and expect the component to show up on the panel. You still need to add the component to the panel before you do a revalidate() on the panel. So your code is like:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
However, the better solution is to use a CardLayout which does all this work for you.

Passing values between JFrames

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.

Categories

Resources