JTextField get no focus when in a heavy-weight popup - java

I want do display a text filed in a popup. When popup is completly over the application frame (MediumWeightPopup) - all works fine, but when a part of popup is outside of frame (HeavyWeightPopup) it cannot be focused. In this case caret is invisible and no text input is possible.
Here is my code:
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class PopupTest {
public static void main(String[] args) {
JFrame frm = new JFrame("Popup test");
JPanel p = new JPanel();
p.addMouseListener(new MouseAdapter() {
Popup pop;
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
if (pop != null) {
pop.hide();
}
JPanel popupPanel = new JPanel(new BorderLayout());
JTextField field = new JTextField(20);
popupPanel.add(field);
pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
pop.show();
System.out.println("Popup type: " + pop.getClass().getName());
System.out.println("Can get focus? " + field.requestFocusInWindow());
}
}
});
frm.add(p);
frm.setSize(500, 300);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
}
On right click near to right border of window I get a non-focusable text field. The same problem I get with any other component in popup that allows key control (for example JTable).
How can I focus a component in a HeavyWeightPopup?

I also struggled with this years ago. I can't figure out how to give initial focus to a component on the popup. Here are some of my questions/observations:
What is the Popup class used for?
I always thought that a Popup should have some basic functionality, such as the pupup should close when:
a) the escape key is pressed
b) the popup loses focus
The popup class provides none of the above functionality and in fact seems to require some obscure code to even get the keyboard focus to work properly.
Using a JWindow seems to provide the same functionality as a Popup.
JPopupMenu seems to support both of the above requirements.
Run the following program:
a) click on each of the buttons
b) click on an empty part of the frame
It appears to me that whenever you need a "popup" you should use a JPopupMenu.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class PopupTest extends JFrame
{
String[] numbers = { "one", "two", "three", "four", "five" };
public PopupTest()
{
getContentPane().setLayout( new FlowLayout() );
getContentPane().setBackground(Color.YELLOW);
JButton popup = new JButton("Popup as Popup");
popup.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
popupPopup(e);
}
});
getContentPane().add(popup);
JButton window = new JButton("Window as Popup");
window.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
windowPopup(e);
}
});
getContentPane().add(window);
JButton menu = new JButton("PopupMenu as Popup");
menu.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
menuPopup(e);
}
});
getContentPane().add(menu);
}
private void popupPopup(ActionEvent e)
{
JList list = new JList(numbers);
list.setSelectedIndex(0);
PopupFactory factory = PopupFactory.getSharedInstance();
Popup popup = factory.getPopup(this, list, getLocation().x, getLocation().y+100);
//popup.show();
Window window = SwingUtilities.windowForComponent(list);
if (window != null)
{
window.setFocusableWindowState(true);
}
popup.show();
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(list);
}
private void windowPopup(ActionEvent e)
{
JList list = new JList(numbers);
list.setSelectedIndex(0);
JWindow window = new JWindow(this);
window.getContentPane().add(list);
window.pack();
window.setVisible(true);
window.setLocation(getLocation().x + 200, getLocation().y+100);
window.addWindowListener( new WindowAdapter()
{
public void windowDeactivated(WindowEvent e)
{
System.out.println("deactivated");
}
});
}
private void menuPopup(ActionEvent e)
{
JList list = new JList(numbers);
list.setSelectedIndex(0);
JPopupMenu menu = new JPopupMenu();
menu.add( new JTextField(10) );
menu.add( list );
menu.show((Component)e.getSource(), 0, 100);
}
private static void createAndShowGUI()
{
JFrame frame = new PopupTest();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(500, 200);
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
Edit:
Based on Sergiy's answer, this code was close to working. The difference in the popupPopup() method is that the show() method needs to be invoked AFTER the window is made focusable. Code updated to reflect this change.

Source code analyse brought me another solution
pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
// some new stuff
Window win = SwingUtilities.windowForComponent(popupPanel);
if (win instanceof JWindow && win.getType() == Window.Type.POPUP) {
win.setFocusableWindowState(true);
}
// continue old stuff
pop.show();
So the complete example looks like
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class PopupTest {
public static void main(String[] args) {
JFrame frm = new JFrame("Popup test");
JPanel p = new JPanel();
p.addMouseListener(new MouseAdapter() {
Popup pop;
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
if (pop != null) {
pop.hide();
}
JPanel popupPanel = new JPanel(new BorderLayout());
JTextField field = new JTextField(20);
popupPanel.add(field);
pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
Window win = SwingUtilities.windowForComponent(popupPanel);
if (win instanceof JWindow && win.getType() == Window.Type.POPUP) {
win.setFocusableWindowState(true);
}
pop.show();
System.out.println("Popup type: " + pop.getClass().getName());
System.out.println("Can get focus? " + field.requestFocusInWindow());
}
}
});
frm.add(p);
frm.setSize(500, 300);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
}
Interesting: the call field.requestFocusInWindow() still returns false, but field gets focus anyway.
BTW: this solution is also better for me because in my real code I get the Popup from a JComboBox (my goal is to create JTableComboBox with a table in popup and an optional filter field on top of the table).

Related

Resetting toggle buttons

I am designing an elevator for my software engineering class. I am using toggle buttons on the elevator cars inside panel for floor selection. I cannot figure out how to toggle the button off if the current floor equals the button being toggled. I have included a code snippet.
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
public class test {
public JPanel createContentPane() {
// We create a bottom JPanel to place everything on.
JPanel totalGUI = new JPanel();
totalGUI.setLayout(null);
// Creation of a Panel to contain the buttons
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(null);
buttonPanel.setLocation(10, 80);
buttonPanel.setSize(500, 500);
totalGUI.add(buttonPanel);
final JToggleButton floor3 = new JToggleButton("3");
floor3.setSize(50, 50);
floor3.setLocation(68, 100);
buttonPanel.add(floor3);
floor3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (3 == 3) {
AbstractButton abstractButton = (AbstractButton) e
.getSource();
boolean selected = abstractButton.getModel().isSelected();
System.out.println("Action - selected=" + selected + "\n");
floor3.setSelected(!selected);
// code to toggle the third floor button off
}
}
});
totalGUI.setOpaque(true);
return totalGUI;
}
static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Elevator");
// Create and set up the content pane.
test Welp = new test();
frame.setContentPane(Welp.createContentPane());
frame.setSize(250, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

How can I switch focus to a canvas?

I have this class and I want to switch focus to the Game class right after it was invoked. I might've not understand the purpose of focus but when I press start I have to click on the game canvas itself so I can use the keyboard . In other words: How can I make it so I don't have to click on it to use the keyboard?
package com.runner.panels;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import com.runner.main.Game;
import com.runner.main.Main;
public class PlayPanel extends JPanel{
private static final long serialVersionUID = 1L;
public PlayPanel(){
//setting the layout of the playpanel to null
setLayout(null);
//setting up the info panel : high score, meters ran, pause button etc...
JPanel info = new JPanel();
info.setBounds(0,0,1200,50);
add(info);
//back button
JButton back = new JButton("Back");
info.add(back);
Game game = new Game();
game.setBounds(0,50,1200,521);
game.setBackground(Color.black);
add(game);
back.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout) Main.mainp.getLayout();
cl.show(Main.mainp, "Menu");
}
});
}
}
Off topic: (kinda)
The fact that you are doing Main.mainp.getLayout();, calling the panel statically tells me you have poor design and should be looking into other options like an Model-view-controller pattern, an Observer pattern, or at the very least passing a reference of of the Main to the panel, instead of using static objects/calls.
Back on topic
Sounds like a common KeyListener problem. Generally to gain focus you call requestFocusInWindow(). But you still have to worry about other components stealing the focus way after the fact.
I would instead recommend using Key Bindings instead of KeyListener. You have more control over the focus. For instance, by using
InputMap im = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("SPACE"), "hitSpace");
panel.getActionMap().put("hitSpace", new AbstractAction(){
public void actionPerformed(ActionEvent e) {
// do something.
}
});
The panel will have immediate access to the action once you show it from the CardLayout. If you happen to use any other components that would steal the focus away from the panel, the action is still accessible because of the WHEN_IN_FOCUSED_WINDOW input map
Here's a simple example. Type A if it is on panel A, you will see it print. If you type B, it won't print because panel A is in the window. Also if you try and press the button in the panel to steal the focus, you can still type and it will still print. Same goes for panel B
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Main {
CardLayout layout = new CardLayout();
JPanel panel = new JPanel(layout);
JPanel p1 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
JPanel p2 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
JButton b1 = new JButton("panelA");
JButton b2 = new JButton("panelB");
public Main() {
addKeyBind(p1, "pressA", "A");
addKeyBind(p2, "pressB", "B");
p1.add(new JButton("Button for Panel A"));
p2.add(new JButton("Button for Panel B"));
panel.add(p1, "panelA");
panel.add(p2, "panelB");
b1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
show("panelA");
}
});
b2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
show("panelB");
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(b1);
buttonPanel.add(b2);
JFrame frame = new JFrame();
frame.add(panel);
frame.add(buttonPanel, BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void show(String panelName) {
layout.show(panel, panelName);
}
private void addKeyBind(JComponent comp, String name, final String stroke) {
InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(stroke), name);
comp.getActionMap().put(name, new AbstractAction(){
public void actionPerformed(ActionEvent e) {
System.out.println(stroke + " pressed");
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new Main();
}
});
}
}
Take some time to go over the link I gave you for Key Bindings to learn more.
Back off-topic
Take a look at #AndrewThompson's comment about the null layouts. Learn how to use the LayoutManagers
I believe your problem would be fixed if you add
setFocusable(true);
to your PlayPanel constructor (works for me).
Also, if you want a specific Panel in your GUI to have focus when you start your application, follow the link in the comment of "user3218114", as this will explain how to implement this functionality with Listeners.
Good luck!
You don't need to do anything. The container should be focusable for that.
Here is a code to demonstrate.
package one;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
public class PlayPanel extends Canvas {
public static void main(String... args) {
PlayPanel p = new PlayPanel();
p.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
p.msg = "Focus gained";
p.repaint();
}
#Override
public void focusLost(FocusEvent e) {
p.msg = "Focus Lost";
p.repaint();
}
});
p.setBackground(Color.GRAY);
JFrame f = new JFrame();
f.add(p);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 200);
f.setLocation(300, 300);
f.setVisible(true);
}
String msg = "NO FOCUS";
public void paint(Graphics g) {
g.drawString(msg, 50, 50);
}
}

How to Close JInternalFrame when JButton click and show another JInternalFrame?

For Example:
When JButton1 click JInternalFrame1 Show on the JDesktopPane
And when JButton2 Click JInternalFrame1 Close and JInternalFrame2 Show on the JDesktopPane.
thx before
Edit: with code from comment
if (JInternalFrame1 == null) {
JInternalFrame1 = new FJInternalFrame();
Desktop.add(JInternalFrame1);
JInternalFrame1.toFront();
} else {
JInternalFrame1.dispose();
}
Take a look at this example. I created a custom JInternalFrame that has a different title every time you create a new frame. when you click on the button, a new one is created and the old one disapears
Here is the important code that may help you out. I add a new frame if the desktop size is equal to 0, other wise I remove the previous one, add a new frame, and revalidate
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (desktop.getAllFrames().length == 0) {
desktop.add(new MyInternalFrame());
} else {
desktop.remove(0);
desktop.add(new MyInternalFrame());
revalidate();
repaint();
}
}
});
Here is the complete code. It's two different files.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class InternalFrameDemo1 extends JPanel {
JDesktopPane desktop;
JButton button;
public InternalFrameDemo1() {
desktop = new JDesktopPane();
button = new JButton("Get Next Frame");
setLayout(new BorderLayout());
add(desktop, BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (desktop.getAllFrames().length == 0) {
desktop.add(new MyInternalFrame());
} else {
desktop.remove(0);
desktop.add(new MyInternalFrame());
revalidate();
repaint();
}
}
});
}
public static void createAndShowGui() {
JFrame frame = new JFrame();
frame.add(new InternalFrameDemo1());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
import javax.swing.JInternalFrame;
public class MyInternalFrame extends JInternalFrame {
static int openFrameCount = 0;
static final int xOffset = 30, yOffset = 30;
public MyInternalFrame() {
super("Document #" + (++openFrameCount),
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
setSize(300,300);
setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
setVisible(true);
}
}

stopCellEditing on JDialog

My question is similar to this one: JTable Cell Update doesn't work.
However, I am using JDialog instead of a JTable specified in above link. I have a custom class which extends JDialog. I use JEditorPane as a text-component in that dialog and create simple OK, Cancel buttons. Now the problem is, when I enter something in the JEdiorPane and presses OK button, the value is not applied to the text-component until I move the focus out of a JDialog or hit tab/ENTER.
I want the container to be notified that I am done with editing as soon as I press the OK button. In short I want to explicitly have a feature similar to stopCellEditing(). How can I do that?
See this example which seems to work correctly and does the same thing as you described:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TestEditorPaneDialog {
public void init() {
final JFrame frame = new JFrame();
JButton clickMe = new JButton("Click me");
clickMe.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showDialog(frame);
}
});
frame.add(clickMe);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
showDialog(frame);
}
private void showDialog(final JFrame frame) {
final JDialog dialog = new JDialog(frame, true);
final JEditorPane pane = new JEditorPane();
pane.setText("Type something here");
JPanel south = new JPanel();
JPanel buttons = new JPanel(new GridLayout(1, 0, 10, 10));
JButton ok = new JButton("OK");
ok.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
JOptionPane.showMessageDialog(frame, "You have typed in: " + pane.getText());
}
});
JButton cancel = new JButton("Cancel");
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
buttons.add(ok);
buttons.add(cancel);
south.add(buttons);
dialog.add(new JScrollPane(pane));
dialog.add(south, BorderLayout.SOUTH);
dialog.setSize(250, 150);
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestEditorPaneDialog().init();
}
});
}
}

Center JDialog over JPanel on JTabbedPane

I have tried all of the suggestions I found here and on other sites.
I can't seem to get this JDialog to be centered over the panel on the JTabbedPane.
Please note, I must have the close button disabled, so I can not use the standard JOptionPane.showDialogXYZ() methods.
Any ideas?
import java.awt.BorderLayout;
import java.awt.Dialog.ModalityType;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public class CenterDialog extends JFrame
{
public CenterDialog()
{
setResizable(false);
setName(getClass().getSimpleName());
setTitle("My Frame");
setSize(300, 300);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
// Add the panel
tabbedPane.addTab("Button panel", new MyButtonPanel());
add(tabbedPane, BorderLayout.CENTER);
getContentPane().add(tabbedPane);
}
private class MyButtonPanel extends JPanel
{
public MyButtonPanel()
{
JButton btnShowDialog = new JButton("Show Dialog");
btnShowDialog.addActionListener(new BtnShowDialogActionListener());
add(btnShowDialog);
}
private class BtnShowDialogActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// TODO: Figure out how to center this dialog box
final String YES = "Yup";
final String NO = "Nope";
final Object[] options = { YES, NO };
final JOptionPane optionPane = new JOptionPane("Is this centered.", JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION, null, options, NO);
Frame f = JOptionPane.getFrameForComponent(((JButton) e.getSource()).getParent());
final JDialog dialog = new JDialog(f, "Question", ModalityType.APPLICATION_MODAL);
dialog.setContentPane(optionPane);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
System.out.println("Ignoring close button");
}
});
optionPane.addPropertyChangeListener(new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent e)
{
String prop = e.getPropertyName();
if (dialog.isVisible() && (e.getSource() == optionPane))
{
if (prop.equals(JOptionPane.VALUE_PROPERTY))
{
dialog.setVisible(false);
}
}
}
});
dialog.pack();
dialog.setVisible(true);
}
}
}
private static void createAndShowGUI()
{
// Create and set up the window.
CenterDialog frame = new CenterDialog();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
});
}
}
}
The method which centers a dialog relative to a given component (no manual calculation needed, handles component-to-screen coordinate mapping internally):
dialog.setLocationRelativeTo(someComponent);
Choose the component, depending on what exactly you want to achieve:
// center relative to the button
dialog.setLocationRelativeTo((Component) e.getSource());
// center relative to button's parent
dialog.setLocationRelativeTo(((Component) e.getSource()).getParent());
// center relative to the tabbedPane
JTabbedPane tabbed = // walk the parent chain until you reach it
dialog.setLocationRelativeTo(tabbed);
I got slightly closer to what you're after by setting tabbedPane as global and then dialog.setLocationRelativeTo(tabbedPane);
Edit: a more elaborate, and probably visually accurate, solution is to calculate the x, y coordinates of your JDialog, something like this:
int xDiff = (tabbedPane.getWidth() - dialog.getWidth()) / 2;
int x = tabbedPane.getX() + xDiff;
int yDiff = (tabbedPane.getHeight() - dialog.getHeight()) / 2;
int y = tabbedPane.getY() + yDiff;
dialog.setLocation(x, y);
If I'm honest, I didn't get it working perfectly, but there's my theory!

Categories