I have a question regarding coding a Swing UI. If I want to make a software with some option e.g. on the first Frame I have three buttons (New, Option, Exit).
Now if a user clicks the new button, I want to change the entire content in the Frame to something else. I know I have to use addActionListener to that button. But my question is how to change the contents in the frame. Creating new Frames and then use setVisible() isn't an option for me.
And to use frame.remove() all the objects seems awkward if it is several things that needs to be removed. Or is it the right way?
Look into the Card Layout. I would also probably use menu items instead of buttons.
CardLayout is indeed the better choice in this case; but, when the occasion demands, a Component may be removed from a Container using either the remove() or removeAll() method. Afterward, the essential step is to invoke the [validate()](http://java.sun.com/javase/6/docs/api/java/awt/Container.html#validate()) method to lay out the container's subcomponents again. Oscar Reyes' example uses the Frame's [pack()](http://java.sun.com/javase/6/docs/api/java/awt/Window.html#pack()) method, inherited from Window, to achieve this effect. In this example, the resetGame() method reconstructs the display panel in a similar way.
You may use frame.remove()
The difference is that you may remove a whole panel instead of removing "several" things, and you just replace it with a new panel
frame.add( mainPanel );
...
// in the action listener
frame.remove( mainPanel );
frame.add( theNewPage );
The point is, you don't have to be afraid of removing awkwardly things in the main frame, for you have to place all those things into a single panel and then just change panels.
UPDATE
I've made the code needed to test what I'm talking about.
Here's a running sample:
alt text http://img190.imageshack.us/img190/5206/capturadepantalla200912p.png
later
alt text http://img301.imageshack.us/img301/1368/capturadepantalla200912n.png
Here's the running sample:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class ChangePage {
JComponent mainPage;
JComponent newPage;
JFrame frame;
public static void main( String [] args ) {
ChangePage changePageDemo = new ChangePage();
changePageDemo.show();
}
private void show(){
frame = new JFrame("Demo");
frame.add( getMainPage() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
private JComponent getMainPage() {
if( this.mainPage != null ) {
return this.mainPage;
}
this.mainPage = new JPanel(new BorderLayout());
mainPage.add( new JLabel("Choose an option") );
mainPage.add( new JPanel(){{
add( new JButton("New"){{
addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
SwingUtilities.invokeLater( new Runnable(){
public void run(){
frame.remove( getMainPage() );
frame.add( getNewPage() );
//frame.setContentPane( getNewPage() );
frame.pack();
}
});
}
});
}});
add( new JButton("Options"));
add( new JButton("Exit"));
}}, BorderLayout.SOUTH );
return this.mainPage;
}
private JComponent getNewPage() {
if( newPage != null ) {
return newPage;
}
this.newPage = new JPanel();
this.newPage.add( new JLabel("<html>This is the \"new\" page.<br> Do you like it?<br></html>"));
this.newPage.add( new JButton("Return"){{
addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
SwingUtilities.invokeLater( new Runnable(){
public void run(){
frame.remove( getNewPage() );
frame.add( getMainPage() );
//frame.setContentPane( getMainPage() );
frame.pack();
}
});
}
});
}});
return this.newPage;
}
}
Alternatively you may use setContentPane :)
The easiest way is to use a Tabbed Pane.
Related
I want to know how can I switch JPanels inside my main JFrame, I have tried this code but when I click the menu item it changes then I click other menu item and does not change, I click the menu Item I clicked first and it changes ....is there other way I can easily switch jpanels? do not show me the cardLayout crap because it doesn't work with what i need and it seems that every answer on google involves that demo, anyway if there is a simple way of doing things I appreciate it if someone helps me point in the right direction thanks.
menuItem.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
mainPane.remove(getContentPane());
mainPane.add(cdPanel, BorderLayout.CENTER);
mainPane.validate();
}
});
there are two ways
remove (JFrame.getContentPane.removeAll()) and add JPanel to JFrame, required to call JFrame.(re)validate and JFrame.repaint after all changes to already visible Swing GUI is done, once time, last code lines
(better, correct, proper of ways) use CardLayout, code example in official Oracle tutorial, a few good, some excelent examples here
Edited Code:
public static void main(String[] args)
{
// TODO code application logic here
JFrame frame = new JFrame();
frame.setSize( 300, 300);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JPanel panelOne = new JPanel();
panelOne.setBackground( Color.red );
JPanel panelTwo = new JPanel();
panelTwo.setBackground(Color.blue);
frame.setContentPane( panelOne );
frame.setVisible(true);
//This delay is just here so you can see the transition
try
{
Thread.sleep( 1000 );
}
catch ( InterruptedException ie )
{
ie.printStackTrace();
}
panelTwo.setSize( frame.getContentPane().getSize() );
frame.setContentPane( panelTwo );
}
I would like to point out that there is a class called JTabbedPane. It might not be what you're looking for, but it's essentially one pane, with multiple tabs on it that a user can click and switch views.
http://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
http://docs.oracle.com/javase/6/docs/api/javax/swing/JTabbedPane.html
I am using Swing to build a GUI in Java. The code to make the button and add it is like this:
//Create a button
JButton exitButton = new JButton("Exit");
exitButton.setSize(90, 40);
exitButton.setLocation(800, 450);
exitButton.setVisible(true);
//Adding components
window.getContentPane().add(exitButton);
When I run the app, the button appears in the whole window, sometimes appears as its intended and sometimes doesn't come. Is this some sort of java bug or a prob with my sdk. In case you wish to know what sort of window it is,
//Create a window
JFrame window = new JFrame("First Window");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
window.setVisible(true);
window.setSize(1000, 550);
window.setLocation(150, 150);
It's all within static void main. BTW, how I get the button to close the window through System.exit(0); (I am a beginner and this is my first self-written GUI)
You need a layout. See A Visual Guide to Layout Managers.
Also please check my tutorials here.
I got this sample code. This might be helpful Simple swing buttons
package com.ack.gui.swing.simple;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class SimpleSwingButtons extends JFrame {
public static void main( String[] argv ) {
SimpleSwingButtons myExample = new SimpleSwingButtons( "Simple Swing Buttons" );
}
public SimpleSwingButtons( String title ) {
super( title );
setSize( 150, 150 );
addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent we ) {
dispose();
System.exit( 0 );
}
} );
init();
setVisible( true );
}
private void init() {
JPanel my_panel = new JPanel();
my_panel.setLayout( new GridLayout( 3, 3 ) );
for( int i = 1; i < 10; i++ ) {
ImageIcon icon = new ImageIcon( i + ".gif" );
JButton jb = new JButton( icon );
jb.setToolTipText( i + ".gif" );
my_panel.add( jb );
}
getContentPane().add( my_panel );
my_panel.setBorder( BorderFactory.createEtchedBorder() );
}
}
courtesy Java.happycodings
You must check your layout, if you want to use custom position for your components, set Layout as null and use the setBounds(x,y,weight,height) method.
JFrame window = new JFrame("First Window");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
window.setLayout(null);
JButton exitButton = new JButton("Exit");
exitButton.setBounds(15,45,150,30);//This is just an example
exitButton.setVisible(true);
Best regards.
I'm having a little trouble with my project.
I have one class that is a panel displaying 4 buttons.
I have 4 classes(only one so far) that are panels displaying various components. These panels will occupy one space and only one panel should be visible at a time.
What I want to do is to control the visibility of the panels with their respective button.
For example, when the user clicks on button1, panel1 should appear, and when button2 is pressed, panel2 appears, etc.
This is my first time working with a GUI in java and any help is appreciated.
These are the options before you, (Given in the order I guess the most suitable for you)
CardLayout
A CardLayout object is a layout manager for a container. It treats each component in the container as a card. Only one card is visible at a time, and the container acts as a stack of cards.
for more info see How to Use CardLayout
JTabbedPane
A component that lets the user switch between a group of components by clicking on a tab with a given title and/or icon
for more info, see How to Use Tabbed Panes
JDialog(Maybe an undecorated one)
for more info see How to Make Dialogs
CardLayout is the best option for your requirement.
http://www.java2s.com/Code/Java/Swing-JFC/CardLayoutDemo.htm
As with the other answers, in a recent GUI I created I used CardLayout to accomplish this task.
The solution is simple, have one panel in your Parent JFrame that will hold the CardLayout and when you add each panel you want to show you associate a String with it so you can grab it later such as:
panelManager.add(typeSelectionView, TYPEVIEW);
Where panelManager is my JPanel containing my layout (Which you have to add before this so you can use this add() method.
Ensure you are storing these Strings which identify your hidden panels in some form, as I have here with my final variables, and when it comes time to show this panel which is hidden within the layout simply call:
cl.show(panelManager, newPanel);
Where in my case, newPanel was calculated by the controller and handed down to the view. It uses the final Static Strings in the view's Class.
Although CardLayout is already suggested, and even a link to the Swing tutorial already provided, I will add some sample code which makes use of the CardLayout as an answer.
public class CardLayoutDemo {
private static JFrame createGUI(){
JFrame testFrame = new JFrame( );
testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
List<String> layoutConstraints = Arrays.asList( "first", "second", "third");
final JPanel contentsPane = new JPanel( );
final CardLayout cardLayout = new CardLayout( );
contentsPane.setLayout( cardLayout );
//listener which will be used to switch between the different layouts
ActionListener listener = new ActionListener() {
public void actionPerformed( ActionEvent aActionEvent ) {
String constraint = aActionEvent.getActionCommand();
cardLayout.show( contentsPane, constraint );
}
};
//add components to card layout with specific constraint
for ( String constraints : layoutConstraints ) {
contentsPane.add( new JLabel( constraints ), constraints );
}
//create buttons allowing to switch between the different layouts
JPanel buttonPanel = new JPanel();
for ( int i = 0; i < layoutConstraints.size(); i++ ) {
String constraint = layoutConstraints.get( i );
JButton button = new JButton( "Layout " + i);
button.setActionCommand( constraint );
button.addActionListener( listener );
buttonPanel.add( button );
}
testFrame.add( contentsPane, BorderLayout.CENTER );
testFrame.add( buttonPanel, BorderLayout.SOUTH );
return testFrame;
}
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
public void run() {
JFrame frame = createGUI();
frame.pack();
frame.setVisible( true );
}
} );
}
}
I have a JTreeTable and have successfully implemented a MouseMotionListener to show a tooltip whenever the mouse is over one of the cells. However when clicking on the cell the tooltip does not show up. I've tried several things like setting the text on the mouseClicked and mouseReleased events but that doesn't work. I found this code -
Action toolTipAction = treeTable.getActionMap().get("postTip");
if(toolTipAction != null){
ActionEvent postTip = new ActionEvent(treeTable,ActionEvent.ACTION_PERFORMED, "");
toolTipAction.actionPerformed(postTip);
}
to use in the mouseReleased method, which does make the tooltip popup, but it's then in the wrong position. So next i tried overriding the getTooltipLocation method on the JTreeTable, and this works fine for mouseMoved events but doesn't get called with the above method. Can anyone shed some light on how to do this?
Thanks
Andy
You can use the following approach to show the tooltip (there will be a slight delay). Then you can override the getToolTipLocation() method since a MouseEvent will now be generated:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ToolTipOnRelease extends JPanel
{
public ToolTipOnRelease()
{
JLabel label = new JLabel( "First Name:" );
add( label );
JTextField textField = new JTextField(15);
add( textField );
MouseListener ml = new MouseAdapter()
{
public void mouseReleased(MouseEvent e)
{
JComponent component = (JComponent)e.getSource();
component.setToolTipText("Mouse released on: " + component.getClass().toString());
MouseEvent phantom = new MouseEvent(
component,
MouseEvent.MOUSE_MOVED,
System.currentTimeMillis(),
0,
0,
0,
0,
false);
ToolTipManager.sharedInstance().mouseMoved(phantom);
}
};
label.addMouseListener( ml );
textField.addMouseListener( ml );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("ToolTipOnRelease");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new ToolTipOnRelease() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
org.apache.jorphan.gui.JTreeTable extends javax.swing.JComponent
javax.swing.JComponent#setToopTipText() doesn't work?
I do realize that you want to use Action but for tooltips? I would use Action when multiple UI actions would need to share it.
I want to maximize a JPanel inside a JFrame when the user clicks a button.What is the best way to achieve this.The view and the data model should be in sync in both the panels,that is the panel which in the JFrame and the maximized one.Please suggest me some solution.
my requirement is: i have a JFrame with 4 JPanels named as
JPanelA,JPanelB,JPanelC,JPanelD
Here the JPanelD contains a JList and
a button below it say "MAXIMIZE
PANEL" button . JList has a JTree
with in it . Sometimes the JList may
have huge set of data and it is not
visible to the user clearly.
So he need to maximize this JPanelD alone to see the contents of the JList clearly.For that he clicks "MAXIMIZE PANEL" button.After the click action ,the JPanelD in the JFrame remains there,also a new JPanel with the same JList data(ie.,the replica of the JPanelD say JPanelDMaximized)should be popped up.This is what i want to do ..
Of course you could do this yourself, but you should really look at JInternalFrame and consider using that for your panel. It will save a bunch of headache.
Edit: Sun's tutorial should get you what you need.
Follow-up to your clarification of the problem:
Take my code, and remove:
maximizedFrame.setUndecorated( true );
and size the frame bigger before you make it visible. That should satisfy the maximize-like behaviour you need.
Your other problem is that you cannot add JPanelD to the two JFrames. The pop-up frame must have its own unique JPanel object (let's call it JPanelE). So you need to:
Initialize and lay out JPanelE like you do JPanelD. That means giving JPanelE its own JList (and JTree, and so on).
Share the ListModel from JPanelD's JList with JPanelE's JList, and so on. The feasibility and details of executing this successfully depends on the specifics of your implementation, and is beyond the scope of your original problem.
Create a JWindow (or an undecorated JFrame) with a JPanel. Leave the JWindow invisible, initially. (The wiring of this new JPanel to the same data model used by the original JPanel is left as an exercise.)
When your maximize-panel button's ActionListener executes, it must:
2.1. Update the (invisible) JWindow's location and size to match the (visible) JFrame's.
2.2. Make your JFrame invisible.
2.3. Make your JWindow visible.
When your unmaximize-panel button's ActionListener executes, it must:
3.1. Update the (invisible) JFrame's location and size to match the (visible) JWindow's.
3.2. Make your JWindow invisible.
3.3. Make your JFrame visible
Example:
package stackoverflow;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MaximizingPanelApp extends JFrame {
private JPanel framePanel;
private JPanel windowPanel;
private JFrame maximizedFrame;
public static void main(String[] args) {
JFrame appFrame = new MaximizingPanelApp();
appFrame.setVisible( true );
}
public MaximizingPanelApp() throws HeadlessException {
super( "Application" );
setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
initialize();
}
private void initialize() {
// JFrame
{
Container container = getContentPane();
container.setLayout( new BorderLayout() );
framePanel = new JPanel();
framePanel.setBackground( Color.ORANGE );
container.add( framePanel, BorderLayout.CENTER );
JButton button = new JButton( new MaximizeAction() );
container.add( button, BorderLayout.SOUTH );
setSize( 400, 300 );
}
// JWindow
{
maximizedFrame = new JFrame();
Container container = maximizedFrame.getContentPane();
container.setLayout( new BorderLayout() );
windowPanel = new JPanel();
windowPanel.setBackground( Color.ORANGE );
container.add( windowPanel, BorderLayout.CENTER );
JButton button = new JButton( new UnMaximizeAction() );
container.add( button, BorderLayout.SOUTH );
maximizedFrame.setSize( getSize() );
maximizedFrame.setUndecorated( true );
}
}
private class MaximizeAction extends AbstractAction {
private MaximizeAction() {
super( "Maximize" );
}
public void actionPerformed(ActionEvent e) {
maximizedFrame.setSize( getSize() );
maximizedFrame.setLocation( getLocation() );
setVisible( false );
maximizedFrame.setVisible( true );
}
}
private class UnMaximizeAction extends AbstractAction {
private UnMaximizeAction() {
super( "Un-Maximize" );
}
public void actionPerformed(ActionEvent e) {
setLocation( maximizedFrame.getLocation() );
setSize( maximizedFrame.getSize() );
maximizedFrame.setVisible( false );
maximizedFrame.dispose();
setVisible( true );
}
}
}
This depends on the layout manager you use. If you add a JPanel to a JFrame using the default layout manager, and the JFrame only contains the JPanel and nothing else, you'll achieve what you describe.
Here's an example. The JPanel is green; notice how it resizes as you resize the JFrame.
import javax.swing.*;
import java.awt.*;
public class ScratchSpace {
public static void main(String[] args) {
JFrame frame = new JFrame("Stretchy panel demo");
final JPanel panel = new JPanel();
panel.setOpaque(true);
panel.setBackground(Color.GREEN);
panel.setPreferredSize(new Dimension(600, 400));
final JComponent contentPane = (JComponent) frame.getContentPane();
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}