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.
Related
Alright I'm relatively new to programming and it may be just something simple that I'm missing but the other threads related to this topic the poster didn't give adequate information relative to their issue for others to provide quality answers so I will give it a shot.
public BenchUI(JFrame j){
jf = j;
init();
add(mainPanel);
topPanelButtons();
selectedCustomer();
rentalOptions();
clientListBox();
}
At this point i can point out that everything works perfectly until I add the clientListBox() method. (below)
public void clientListBox(){
clientList = new JComboBox(moo);
clientList.setPreferredSize(new Dimension(460,30));
gbc.gridx = 0;
gbc.gridy = 0;
leftSide.add(clientList,gbc);
}
i can comment it out and get my whole GUI back working perfectly but without a JComboBox.
moo is String [] moo = {"Fish","Goat", "Monkey"};
a dummy string just for testing purposes and initialized at the start.
So any idea why my GUI completely disappears when I place in the clientList?
If anything else is necessary I'll be watching this thread and can provide additional information.
As a side note I keep getting warnings for "Raw Types" but it works without specifiying, could I potentially run into trouble by not specifying my JComboBox?
EDIT:
ok I believe I've duplicated whatever the issue is in this code
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.*;
public class main {
public static void main(String[] args){
JFrame jf = new JFrame();
jf.setExtendedState(JFrame.MAXIMIZED_BOTH);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setResizable(false);
BenchUI bu = new BenchUI(jf);
jf.add(bu);
}
}
public class BenchUI extends JPanel{
JPanel one;
JFrame jf;
JComboBox<String> clientList;
String[] moo = {"Goat", "Fish", "Donkey"};
public BenchUI(JFrame j){
jf = j;
one = new JPanel(new GridBagLayout());
one.setBackground(Color.blue);
one.setPreferredSize(new Dimension(300,300));
clientList = new JComboBox<String>(moo);
one.add(clientList);
add(one);
}
}
with the clientList stuff commented out I get my silly little blue panel and once it is added I lose the blue panel and the combobox doesnt show up as well...betting on this is a facepalm issue at this point >.<
EDIT: to include the main class.
EDIT: took out the comment marks for the JComboBox constructor and implementer
Your posted sort of sscce-like (not a real SSCCE by the way since we can't run it) code doesn't add any such as the JComboBox to the JPanel and adds no components such as the current JPanel to the JFrame.
public class BenchUI extends JPanel{
JPanel one;
JFrame jf;
JComboBox<String> clientList;
String[] moo = {"Goat", "Fish", "Donkey"};
public BenchUI(JFrame j){
jf = j;
one = new JPanel(new GridBagLayout());
one.setBackground(Color.blue);
one.setPreferredSize(new Dimension(300,300));
//clientList = new JComboBox<String>(moo);
//one.add(clientList);
add(one);
}
}
and so it makes sense that none of the components will show up on any JFrame. You will want to read the Swing tutorials on how to add components to other components (or containers) and how to create and show a JFrame. Have a look at How to Use Swing Components.
Edit
Your latest code now does in fact add the BenchUI JPanel to the JFrame, but still you add no components to the BenchUI JPanel, and in fact you don't even construct your JComboBox but only create a JComboBox variable. Again, I strongly urge you to read the Swing tutorials which I've linked to above as well as the general Java tutorials.
Edit 2
Some general advice:
If you want to add a component to a GUI you must first create the component object. You are declaring your clientList JComboBox, but you never create the object.
Then you must add the component object to a container that eventually will be part of the hierarchy leading to a top level window such as a JFrame, JDialog, JApplet and such. You never add a clientList object to the GUI.
You should add your components to the top level window before calling pack() on the top level window -- which tells all the layout managers to lay out all the components they hold.
You should then call setVisible(true). One problem with your code (other than not creating important components and not adding them to the GUI!) is that you're calling setVisible(true) on your JFrame way too early before adding anything to the GUI.
Read the Swing tutorial, but especially the one on using layout managers and on adding components to a top level window.
Edit 3
OK, now you're creating your JComboBox, but you still are adding all components to your JFrame after setting it visible. Please re-check my 3rd and 4th bullets in the bullet list above.
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.
By input elements I mean things like JSpinners and JComboxBoxes. My glasspane is passed a JPanel containing JSpinners, JComboBoxes and for the most part, JLabels. The glasspane has a MouseListener attached. The surprising thing is that mouseEntered is called upon the mouse cursor leaving the input elements and hovering over the other parts or empty space of the JPanel! Is this normal behaviour? How can I get the input elements to be considered part of the JPanel for Glasspane purposes?
Here is a screenshot of my UI with its input elements and jLabels.
Here is an example piece of Code:
import javax.swing.*;
public class DialogTest {
public DialogTest() {
JPanel dialogPanel = new JPanel();
SpinnerModel edgeModel = new SpinnerNumberModel(1, 1, 9, 1);
JSpinner edgeSpn = new JSpinner(edgeModel);
dialogPanel.add(edgeSpn);
JDialog initialDialog = new JDialog(new JFrame(), "Test", true);
initialDialog.setContentPane(dialogPanel);
initialDialog.pack();
glass = new GlassComponent(dialogPanel);
initialDialog.setGlassPane(glass);
glass.setOpaque(false);
glass.setVisible(true);
initialDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
initialDialog.setVisible(true);
}
}
public class GlassComponent implements MouseListener {
JPanel c;
public GlassComponent(JPanel c) {
this.c = c;
this.c.addMouseListener(this);
}
...
public mouseEntered(MouseEvent e) {
System.out.println("Entered JPanel");
}
}
By way of explanation, my goal is to eventually use the GlassPane to block input for those elements marked with the prohibition sign. However, given that the mouseListener assigned to the dialogPanel is seemingly generating new events upon leaving the input elements, I may have some difficulties achieving this.
You can forward mouse events to the underlying components, as shown in The Glass Pane demo's method, redispatchMouseEvent().
You appear to be using glasspane in a way that I feel it shouldn't be used.
As far as I know, a glasspane typically shouldn't be holding components at all but rather cover over the top-level window and then can act as a gate-keeper for the components that are below it, all held by the top level window's contentPane.
you can use GlassPane for overlay required Container or JComponent by #camickr, or my questions based on his code here or here,
another suggestion could be use JLayer (required Java7 for Java6 is there JXLayer)
I'm creating an applet which consists of a class which extends JApplet, with a menubar and a class which extends a JPanel.(So there is a menubar and a JPanel shown in the applet).
In this class I add and remove some textfields to the JPanel. This all works fine. Here's where it gets tricky: it only works the first time. When I add some new textfields to the JPanel, they are added and visible in the JPanel, but the menubar in the JFrame stops working.
Since the code is too extensive I'll only post parts of it.
Here's the code where I add the JPanel to the JApplet:
public class Simulator extends JApplet implements ItemListener, ActionListener {
Container pane = getContentPane();
canvas = new DrawCanvas();
pane.add(canvas, BorderLayout.LINE_END);
}
Here's the code of the JPanel:
class DrawCanvas extends JPanel {
public void paintComponent(Graphics g) {
if(textfield != null)
remove(textfield);
textfield = new JTextField();
this.add(textfield);
}
}
This works the first time(when nothing is removed), but the second time the menubar stops working.
When I leave out the this.add(textfield); line, the menubar keeps working.
I once had similar problems with popup menus beeing painted behind other components.
Try calling static JPopupMenu.setDefaultLightWeightPopupEnabled(false); or the setLightWeightPopupEnabled on your specific submenu. This will make (all) popup menus (i.e. submenus) to heavy weight components that have a native peer.
I believe you are running into issues with threading. Adding and removing JComponents during painting might mess up the EDT (which is calling the paint method in the first place).
My program have 3 classes. 1) main, 2) frame, 3) drawingBoard. The logic of my program is that, a new drawing will be displayed every times user click on New pattern button (and this working fine).
1st class - main method
public class mainPage {
public static void main(String[]args){
JFrame appFrame = new Frame();
appFrame.setVisible(true);
appFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);*/
}
}
2nd class - describe the layout (I use Grid Bag Layout)
public class Frame extends JFrame implements ActionListener {
public Frame (){
GridBagLayout m = new GridBagLayout();
Container c = (Container)getContentPane();
c.setLayout (m);
GridBagConstraints con;
JButton bPattern = new JButton("New Pattern");
....
bPattern.addActionListener(this);
JPanel pDraw = new JPanel();
.....
pDraw.add(new drawingBoard()); //drawing will be placed in this panel
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
3rd class - run drawing functions e.g. paintComponent (), etc.
public class drawingBoard extends JPanel {
public drawingBoard(){}
public void paintComponent(Graphic g){}
....
}
The problem is that, when I look on the console, it seems that even though the user did not click on the button, the program call the class 'drawingBoard' and repaint. The paint component is in the 3rd class (drawingBoard). Although this seem not to give me a problem (e.g. no drawing displayed on the panel unless the user click the button), I am just curious how this happened. is that because I wrote this code at FRAME class (). My intention to write this code is to make sure the drawing should be place in this specific panel (I have 3 panels) but not to call the 3rd class unless the button has been clicked.
JPanel pDraw = new JPanel();
pDraw.add(new drawingBoard()); //place drawing here
The repaint method (and subsequently, the paintComponent method) is not only called by the JFrame but also by Swing itself as well, when there needs to be a repaint of the contents of the JPanel.
The Painting in AWT and Swing article is a good place to start to get information on how painting works.
In this case, the repaint method is being called by events which the article calls System-triggered Painting:
In a system-triggered painting
operation, the system requests a
component to render its contents,
usually for one of the following
reasons:
The component is first made visible on the screen.
The component is resized.
The component has damage that needs to be repaired. (For example,
something that previously obscured the
component has moved, and a previously
obscured portion of the component has
become exposed).