I've got a JPanel, which I want to respond to a mouse click and then open a JDialog. The JDialog constructor needs an instance of JFrame and not JPanel - how do I work around this?
You should really try to attach the JDialog to a parent Dialog or Frame, especially if you want it modal (by passing a parent Window, the dialog will be attached to your Window and bringing the parent will bring the child dialog as well). Otherwise, the user experience can really go wrong: lost dialogs, blocking windows without seeing the modal dialog, etc...
To find your JPanel parent Window, all you need is this code:
JPanel panel = new JPanel();
Window parentWindow = SwingUtilities.windowForComponent(panel);
// or pass 'this' if you are inside the panel
Frame parentFrame = null;
if (parentWindow instanceof Frame) {
parentFrame = (Frame)parentWindow;
}
JDialog dialog = new JDialog(parentFrame);
...
If you don't know if you are in a Frame or Dialog, make the "instanceof" test for both classes.
Using the parameter free constructor will make the dialog owner-less. I think that the best thing to do would be to make the Frame that owns your Panel the owner of the dialog.
By that, I mean that you should use the getParent() from your JPanel to find its owner and then send this object found as the owner of your JFrame.
A crude code for that would be
java.awt.Container c = myPanel.getParent();
while (!(c instanceof javax.swing.JFrame) && (c!=null)) {
c = c.getParent();
}
if (c!=null) {
JFrame owner=(javax.swing.JFrame) c;
JDialog myDialog=new JDialog(owner);
}
I have not tested this code, but it is good enought for you to understand the idea.
If you decided to go with a JOptionPane, you could add a MouseListener to the JPanel with a mouseAdapter inner class to handle mouseClicked events. You would have to declare the panel final in order to access the panel from within the inner class.
final JPanel testPanel = new JPanel();
testPanel.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e)
{
JOptionPane.showMessageDialog(testPanel,"Title","InformationMessage",JOptionPane.INFORMATION_MESSAGE);
}});//end of mouseClicked method
There's a constructor that don't need argument:
JDialog dialog = new JDialog();
If what you want is to make the dialog modal, maybe you can get a static reference of you main JFrame, something like:
JDialog dialog = new JDialog(MyMainJFrame.getInstance());
Related
I've a JFrame and a JPanel is added in. When I click o a button in the panel, a JDialog (named choiceDialog) appears. When I click on a particular button on the dialog I just want it to close.
I would want the dialog closed and the frame usable. Is it possible?
I tried to hide the dialog with setVisible(false) but it hid both the dialog and frame. Then I tried to do choiceDialog.dispose() but I lost both the elements again. At that point I found a way to set the Frame again visible but not usable.
Can anyone help me please? I don't really know what to do.
Here's the relevant code:
if (dimField.isEnabled()){
String dimFieldText = dimField.getText();
if (dimFieldText.equals("") || !isNumeric(dimFieldText)){ //if there's an error when filling the options in the JDialog
errorLabel = new JLabel(noDim, SwingConstants.CENTER);
/*other stuff
...
*/
}else{ //if it's all ok: I want the JDialog close but the JFrame to be usable
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this); //to catch the JFrame istance
choiceDialog.dispose();
topFrame.setVisible(true); //to make the JFrame visible again
//choiceDialog.setVisible(false);
}
You are setting topFrame to be the window ancestor of the button, which is the dialog itself. You need to get the window ancestor of the dialog instead. That assumes that when you created the dialog you specified the main frame as its parent rather than using the no-argument JDialog constructor.
I have class main extends jframe, it has a button that calls /shows another class that extends jdialog.
If the button from jdialog is triggered, it will dispose that dialog and will remove all component of jframe, then add it to a new jpanel.
What should I do?
Here's my new broken code:
public class mainz extends JFrame{
mainz(){
setVisible(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JToolBar r = new JToolBar();
r.add(Box.createHorizontalGlue());
add(r, BorderLayout.NORTH);
JButton n = new JButton();
r.add(n, BorderLayout.EAST);
n.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
show();
}
});
}
public void show(){
dialogz d = new dialogz(this);
d.setVisible(true);
}
public void lastHope(){
getContentPane().removeAll();
getContentPane().validate();
getContentPane().repaint();
}
public static void main (String[]args){
new mainz().setExtendedState(MAXIMIZED_BOTH);
}
}
public class dialogz extends JDialog{
public dialogz(final mainz owner) {
setSize(300, 300);
JButton n = new JButton("execute");
add(n);
final JFrame ew = (JFrame)super.getOwner();// <<
n.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
dispose();
//owner.lastHope;
ew.removeAll();// <<
ew.validate();// <<
ew.repaint();// <<
}
});
}
void yes(){
getOwner().removeAll();
getOwner().validate();
getOwner().repaint();
}
}
I know I can prevent my main class from extending jframe, and call it from main instead, but I want to do it like that...
Please help me ... T-T
Sorry for my English, I from a far away country ~,~"
update:
the error is
java.lang.ClassCastException: javax.swing.SwingUtilities$SharedOwnerFrame cannot be cast to javax.swing.JFrame
it will be done with delete the line that contain
// <<
then call lastHope();
but i think there's a another way to get that existing jframe to removeall
(by casting it first or something ~,~" )
You are calling getParent() but you never set the parent (or owner). That should happen in the constructor as already pointed out. Also, be mindful that getParent() returns a Container object and getOwner() returns a Window object. Both of these refer to the JFrame which is the parent and owner. If you want to use it as a JFrame, you'll have to cast the output as (JFrame). But removeAll() is in Container class so if that's all you want, there'll be no need for casting.
Update:
JFrame frame = new JFrame();
JDialog dialog = new JDialog(frame);//frame is owner
JFrame parentOfDialog = (JFrame)(dialog.getParent());
//OR
//JFrame parentOfDialog = (JFrame)(dialog.getOwner());
parentOfDialog.removeAll();
If you are using your custom class, pass JFrame in the constructor and call super.
Please read the javadoc on JDialog before you try to use it. Also, read more about inheritance.
I'm not clear on what your goal is, but if you want to change the components that are displayed in a container, such as a JFrame or JDialog's contentPane, then I recommend that you use a CardLayout to do this since it allows you to easily swap "views".
There could be two ways to do this:
Your JDialog class could use a reference to the JFrame that is passed in via its constructor (and you should then pass it immediately into the dialog's super constructor so that your modality will work correctly). You could then call any public methods in the JFrame's class.
Or since the JDialog is modal, the JFrame's code will halt while the dialog is visible. You could swap "views" immediately after the dialog has been disposed of and is no longer visible. this would keep the JFrame manipulating code in the JFrame class.
Edit: note that if you don't use CardLayout, then you're responsible for calling revalidate() and repaint() on any container who gets its components changed.
As an aside: since English is not your first tongue and nor is it the native language of many folks on this forum, please avoid using non-standard abbreviations. The clearer your communication with us, the easier it will be for us to understand you and help you.
I have a mainFrame with a custom class loader. My loader is loading Pannels in the mainFrame as needed. In one of the pannel i have a JDialog. I want the JDialog box to blocks all windows from the application.
in the pannel i would like to do somting like this.
myDialog = new JDialog(getSelectedFrame(),"",Dialog.ModalityType...);
Thanks!
You dont' need it. If you want to parent the dialog to a frame, dialog, or whatever you can simply call getTopLevelAncestor() on the component that is instantiating the JDialog. That makes knowing the frame irrelevant which helps ensure the person calling or reusing code can use it on any component: frame, another dialog, window, etc.
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#getTopLevelAncestor()
For example:
class MySpecialPanel extends JPanel {
public MySpecialPanel() {
JButton button = new JButton( new AbstractAction("Show") {
public void actionPerformed(ActionEvent event) {
JDialog dialog = new JDialog( (Window)getTopLevelAncestor(), "Some Title", Dialog.ModalityType.DOCUMENT_MODAL );
dialog.add( new DialogPanel() );
dialog.show();
}
});
}
}
Now by using MySpecialPanel.getTopLevelAncestor() the dialog you are creating doesn't need to know the exact component it is. And the client using MySpecialPanel is free to put this panel into any container it desires be that a JFrame, another JDialog, or whatever.
I'm trying to close a frame yet open a new frame.
My application has page A, a JPanel with some controls and a specific button, and when the user clicks the button, I want page A to disappear and page B to appear (page B has controls that depend on the choices that are made by the user on page A).
This has been asked before, but there was no satisfactory answer. Inside the ActionListener implementation, namely public void ActionPerformed(ActionEvent e) from my jpanelForPageA class, I can comfortably write this.setVisible(false), but how can I set page B to a visible state?
You can do the removal of panel a and then the addition of panel b trick. Another is to use a CardLayout.
When you create your panels, you add them to a containing JPanel that you initialize with a CardLayout:
JPanel container = new JPanel(new CardLayout());
containter.add(getPanelA(), "PANEL_A");
containter.add(getPanelB(), "PANEL_B");
Then, in your actionPerformed, when you want to show panelB, you do this:
CardLayout cl = (CardLayout) container.getLayout();
cl.show("PANEL_B");
Take a look at this tutorial for some more ideas.
For some reason, I can never to get setVisible() to work for me to do what you're describing. Instead, I do this:
frame.remove(panelA);
frame.add(panelB);
"frame" is just the JFrame you want to put the panels in. Try this if the setVisible() method doesn't work :)
To your original question, all you have to do is (like aioobe said):
panelB.setVisible(true);
((btw, posting some of your code would help me figure out what you're trying to ask))
And this is just a guess as to what you're trying to do -- I'm guessing your JPanels are in different classes. Then, you'll need to do this:
class pages extends JFrame implements ActionListener
{
public pages()
{
panelA a = new panelA(this)
}
changeToA(panelB b)
{
remove(panelB);
add(new panelA(this));
}
changeToB(panelA a)
{
remove(panelA);
add(new panelB(this));
}
}
class panelA extends JPanel implements ActionListener
{
pages p;
public panelA(pages p)
{
this.p = p
}
// all that actionlistener code stuff
p.changeToB(this);
}
class panelB extends JPanel implements ActionListener
{
pages p;
public panelB(pages p)
{
this.p = p
}
// all that actionlistener code stuff
p.changeToA(this);
}
You pass the pages class to the panels so the panels can tell the pages class to remove themselves.
((I don't know if there is an easier way, but this is what I do all the time))
I hope I helped :)
You have to remove Panel A from the frame, add Panel B to the frame, and call invalidate on the frame (or containing panel). At least in Swing, I'm not sure about AWT, there you might need repaint or revalidate instead of invalidate.
You could also just create a whole new JFrame and dispose the one containing panel A.
I am trying to maximize JFrame from within JMenuBar, I can not pass a reference to the frame. Is it possible to get a reference to the frame that it is used in?
i can get to the top level component but it does not have a way to maximize and minimize frame.
public Container getApplicationFrame(ActionEvent event){
JMenuItem menuItem = (JMenuItem) event.getSource();
JPopupMenu popupMenu = (JPopupMenu) menuItem.getParent();
Component invoker = popupMenu.getInvoker();
JComponent invokerAsJComponent = (JComponent) invoker;
Container topLevel = invokerAsJComponent.getTopLevelAncestor();
return topLevel;
}
You can get the Window that contains the JPanel via
Window window = SwingUtilities.getWindowAncestor(popupMenu);
You can then either maximise it using window.setSize() -- or, since you seem to know that it's a JFrame, cast it to Frame and use the setExtendedState method that Kevin mentions. Example code from the Java Developers' Almanac for that:
// This method minimizes a frame; the iconified bit is not affected
public void maximize(Frame frame) {
int state = frame.getExtendedState();
// Set the maximized bits
state |= Frame.MAXIMIZED_BOTH;
// Maximize the frame
frame.setExtendedState(state);
}
Surely you can stash the frame in question in a local variable somewhere?
As for actually maximizing the Frame once you've got ahold of it, Frame.setExtendedState(MAXIMIZED_BOTH) is probably what you want. Javadoc
While not as elegant as it could be, quick path to ground on your existing code:
public Frame getApplicationFrame(ActionEvent event){
if(event.getSource() == null) return null;
Window topLevel = SwingUtilities.getWindowAncestor(event.getSource());
if(!(topLevel instanceof Frame)) return null;
return (Frame)topLevel;
}
...
//Somewhere in your code
Frame appFrame = getApplicationFrame(myEvent);
appFrame.setExtendedState(appFrame.getExtendedState() | Frame.MAXIMIZED_BOTH);
...
Minimum Java version 1.4.2. Be forwarned I have not tested the above code, but you should get the idea.
The class that creates the frame and the menubar can also act as the ActionListener for the menu item, since it has access both the frame and the menubar.