I'm trying to create the top buttons of a window. I have a JFrame and a JPanel with the differents buttons when I try to add the panel with the buttons to a JPanel on the frame, it doesn't show... digging and trying to find the solution, I realize that the issue is when I set the orientation to the panel with the buttons on the BorderLayout panel. I think that it might be something dumb that I haven't realize but I haven't found any issue like this.
The issue is here when I set the orientation:
contentPanel.add(buttons,BorderLayout.PAGE_START);
if I remove the:
BorderLayout.PAGE_START
it works
This is my Frame:
package view;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.CardLayout;
import java.awt.BorderLayout;
public class MainFrame extends JFrame{
private JPanel contentPanel, layOutPanel;
private CardLayout mainCardLayout;
private BorderLayout borderLayout;
private static MainFrame instance = null;
private FrameButtonsPanel buttons;
private MainFrame(){
setSize(1000,700);
//setUndecorated(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPanel = new JPanel();
borderLayout = new BorderLayout();
contentPanel.setLayout(borderLayout);
add(contentPanel);
buttons = new FrameButtonsPanel();
buttons.setBackground(Color.red);
contentPanel.add(buttons,BorderLayout.PAGE_START);
/*layOutPanel = new JPanel();
mainCardLayout = new CardLayout();
layOutPanel.setLayout(mainCardLayout);
layOutPanel.setBackground(Color.red);
contentPanel.add(layOutPanel,BorderLayout.SOUTH);*/
}
public static MainFrame getInstance(){
if (instance == null){
instance = new MainFrame();
}
return instance;
}
public static void main(String[] args) {
MainFrame.getInstance().setVisible(true);
}
}
and this is my panel with the buttons:
package view;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import javax.swing.Spring;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class FrameButtonsPanel extends JPanel{
private Spring spring;
private JButton iconify, maximize, close;
public FrameButtonsPanel(){
SpringLayout mySpring = new SpringLayout();
setLayout(mySpring);
iconify = new JButton("-");
add(iconify);
maximize = new JButton("O");
add(maximize);
close = new JButton("X");
add(close);
spring = Spring.constant(850,850,2000);
mySpring.putConstraint(SpringLayout.WEST,iconify,spring,SpringLayout.WEST,this);
mySpring.putConstraint(SpringLayout.WEST,maximize,3,SpringLayout.EAST,iconify);
mySpring.putConstraint(SpringLayout.WEST,close,3,SpringLayout.EAST,maximize);
mySpring.putConstraint(SpringLayout.EAST,this,3,SpringLayout.EAST,close);
iconifyWindow();
maximizeWindow();
closeWindow();
}
private void iconifyWindow(){
iconify.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
MainFrame.getInstance().setExtendedState(JFrame.ICONIFIED);
}
});
}
private void maximizeWindow(){
maximize.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
if(MainFrame.getInstance().getExtendedState() == JFrame.MAXIMIZED_BOTH){
MainFrame.getInstance().setExtendedState(JFrame.NORMAL);
}else{
MainFrame.getInstance().setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
});
}
private void closeWindow(){
close.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
}
}
I have no idea why you are trying to use a SpringLayout to display buttons.
Just use a JPanel with a right aligned FlowLayout.
Read the FlowLayout API for more information on how to right align the components added to the panel.
Related
So, I'm trying to make a basic functional menu for a simple game. I tried to do this by creating 2 JPanels, one for the actual game, and another for my menu.
What I'm trying to do is have a button on my Menu panel that when pressed, switches the JPanel being displayed in the parent JFrame from that of the menu to that of the actual game.
Here is my code:
class Menu extends JPanel
{
public Menu()
{
JButton startButton = new JButton("Start!");
startButton.addActionListener(new Listener());
add(startButton);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Container container = getParent();
Container previous = container;
System.out.println(getParent());
while (container != null)
{
previous = container;
container = container.getParent();
}
previous.setContentPane(new GamePanel());
}
}
}
As you can see, I created a Listener for my start button. Inside the listener, I used a while loop to get to the JFrame, via the getParent() method. The program is getting the JFrame object, however it's not letting me call the setContentPane method...
Does anyone know how to get this to work, or a better way to switch back and forth between a menu and game?
Like so :
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CardLayoutDemo extends JFrame {
public final String YELLOW_PAGE = "yellow page";
public final String RED_PAGE = "red page";
private final CardLayout cLayout;
private final JPanel mainPane;
boolean isRedPaneVisible;
public CardLayoutDemo(){
setTitle("Card Layout Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
mainPane = new JPanel();
mainPane.setPreferredSize(new Dimension(250,150));
cLayout = new CardLayout();
mainPane.setLayout(cLayout);
JPanel yellowPane = new JPanel();
yellowPane.setBackground(Color.YELLOW);
JPanel redPane = new JPanel();
redPane.setBackground(Color.RED);
mainPane.add(YELLOW_PAGE, yellowPane);
mainPane.add(RED_PAGE, redPane);
showRedPane();
JButton button = new JButton("Switch Panes");
button.addActionListener(e -> switchPanes() );
setLayout(new BorderLayout());
add(mainPane,BorderLayout.CENTER);
add(button,BorderLayout.SOUTH);
pack();
setVisible(true);
}
void switchPanes() {
if (isRedPaneVisible) {showYelloPane();}
else { showRedPane();}
}
void showRedPane() {
cLayout.show(mainPane, RED_PAGE);
isRedPaneVisible = true;
}
void showYelloPane() {
cLayout.show(mainPane, YELLOW_PAGE);
isRedPaneVisible = false;
}
public static void main(String[] args) {
new CardLayoutDemo();
}
}
basically I'm trying to understand Threads in Java.So I thought I'd create a main JFrame class containing two JPanels from external classes and then do something in one and control it with messages from the second panel.So far I have only created the first external panel and there the probleme starts! It does not show correctly although it appears to be "loaded".(see system.out lines)
So here is the Main Class
package com.maybee.gui;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class Maybee extends JFrame implements Runnable
{
public JFrame maynFrame = null;
public JPanel contentPanel = null;
public SimPanel simPanel = null;
public int screenWidth = 0;
public int screenHeight = 0;
public Maybee()
{
}
private void init()
{
System.out.println("In Inint");
maynFrame = new JFrame("Maybee");
maynFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
screenWidth = gd.getDisplayMode().getWidth();
screenHeight = gd.getDisplayMode().getHeight();
maynFrame.setPreferredSize(new Dimension(screenWidth,screenHeight - 100));
maynFrame.setContentPane(getContentPanel());
maynFrame.setVisible(true);
maynFrame.pack();
}
public JPanel getContentPanel()
{
if (contentPanel == null)
{
contentPanel = new JPanel();
contentPanel.setPreferredSize(new Dimension(screenWidth,screenHeight - 100));
contentPanel.setBorder(new LineBorder(Color.BLUE));
contentPanel.setBackground(Color.RED);
contentPanel.setLayout(new BorderLayout());
contentPanel.add(getSimPanel(),BorderLayout.CENTER);
}
return contentPanel;
}
public SimPanel getSimPanel()
{
if(simPanel == null)
{
simPanel = new SimPanel(this);
}
return simPanel;
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
System.out.println("Start");
Maybee maybee = new Maybee();
maybee.run();
}
});
}
public void run()
{
init();
}
}
and now the first external JPanel class
package com.maybee.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class SimPanel extends JPanel
{
public Maybee localMaybee = null;
public JPanel simPanel = null;
private JButton btn;
public SimPanel(Maybee interMaybee)
{
localMaybee = interMaybee;
init();
}
public void init()
{
simPanel = new JPanel();
simPanel.setLayout(new BorderLayout());
simPanel.setPreferredSize(new Dimension(localMaybee.screenWidth/4,localMaybee.screenHeight - 100));
simPanel.setBackground(Color.GREEN);
simPanel.add(getBtn(),BorderLayout.CENTER);
simPanel.setVisible(true);
System.out.println("IN SIM" + localMaybee.screenWidth);
}
public JButton getBtn()
{
if(btn == null)
{
btn = new JButton("ENDE");
btn.setSize(70, 20);
btn.setForeground(Color.YELLOW);
btn.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
}
});
}
return btn;
}
}
So what am I missing?
Many thanks!
The immediate issue is the second instance of JPanel created in SimPanel.init(). SimPanel is already a JPanel, there is no need to maintain public JPanel simPanel member.
The same problem is in the Maybee class which extends JFrame, but maintains public JFrame maynFrame member.
Also, as already mentioned in comments above (thanks #Frakcool!) :
Make sure to call pack() before setVisible();
Don't call setPreferredSize(), do override getPreferredSize() intead;
No need to extend JFrame;
No need to call setVisible on JPanel;
Don't call btn.setSize(), it is a job for a layout manager;
No need for setContentPane(), JFrame by default has a JPanel as content pane with BorderLayout. Calling add() is enough in this case.
Here is a slightly modified version of the original code (simplified for clarity):
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.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Maybee2 {
static class SimPanel extends JPanel {
public SimPanel() {
setLayout(new BorderLayout());
JButton btn = new JButton("ENDE");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//TODO
}
});
add(btn, BorderLayout.CENTER);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
}
private static void createAndShowGUI() {
final JFrame frame = new JFrame("Maybee");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SimPanel simPanel = new SimPanel();
frame.add(simPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
EDIT:
The application may consist of many panels. The high level container such as JFrame is not aware of all the underlying layout complexities and cannot enforce a certain size. The panel itself knows its internal layout and its content. So the panel reports its preferred size to the layout manager which eventually packs the content. See Laying Out Components Within a Container for more information.
setBackground has its effect although the button occupies the center of the BorderLayout which takes all the space of the panel. Change the layout of the panel and see the effect. Or move the button into another area, ie - add(btn, BorderLayout.NORTH); Read more in A Visual Guide to Layout Managers.
I wrote a keylistener to that would switch from a screensaver JPanel back to the main screen and added it to the screensaver JPanel creation method however it is not firing on key press and nothing is happening.
Anyone have any idea what is happening?
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import static javax.swing.SwingUtilities.invokeLater;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class layoutdemo {
JPanel cards; // panel that uses CardLayout
CardLayout clo;
final static String WELCOMEPANEL = "Card with welcome message";
final static String SCREENSAVERPANEL = "Card with screensaver";
final static String ENTERPINPANEL = "Card with PIN input"; // not implemented yet
final static String[] FILEARRAY = new String[] {"/cardlayouttest/newpackage/btc-zg.jpg","/cardlayouttest/newpackage/pic2.jpeg"};
static layoutdemo ldm = null;
private static int INDEX = 0;
private JLabel screenImage;
private Timer changeTimer;
public void addComponenttoPane(Container pane){ //method for adding CardLayout and components to JFrame
cards = new JPanel(new CardLayout());
cards.add(welcomePanel(),WELCOMEPANEL);
cards.add(screensaverPanel(),SCREENSAVERPANEL);
pane.add(cards,BorderLayout.CENTER);
}
public JPanel welcomePanel(){ //method for creating the "Welcome" panel
JPanel welcomePanel;
welcomePanel = new JPanel();
JLabel welcomeLabel = new JLabel("Dobrodošli na depozitni bankomat!",SwingConstants.CENTER);
JLabel instructionLabel = new JLabel("Molim vas ubacite karticu u utor sa desne strane",SwingConstants.CENTER);
instructionLabel.setFont(new Font(instructionLabel.getFont().getFontName(),Font.PLAIN,28));
welcomeLabel.setFont(new Font(instructionLabel.getFont().getFontName(),Font.PLAIN,28));
welcomePanel.setLayout(new GridLayout(0,1));
welcomePanel.add(welcomeLabel);
welcomePanel.add(instructionLabel);
return welcomePanel;
}
public JPanel screensaverPanel(){ // method for creating the "Screensaver" panel
JPanel screensaverPanel;
screensaverPanel = new JPanel();
screenImage = new JLabel();
screenImage.setIcon(new ImageIcon(getClass().getResource("/cardlayouttest/newpackage/btc-zg.jpg")));
screensaverPanel.add(screenImage);
screensaverPanel.addKeyListener(stopScreensaver());
screensaverPanel.setFocusable(true);
return screensaverPanel;
}
private static layoutdemo createAndShowGUI(){ // method for creating and showing the GUI
JFrame frame1 = new JFrame("layoutdemowithswitch");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
layoutdemo ldm = new layoutdemo();
ldm.addComponenttoPane(frame1);
frame1.pack();
frame1.setVisible(true);
frame1.getGraphicsConfiguration().getDevice().setFullScreenWindow(frame1);
ldm.clo = (CardLayout) ldm.cards.getLayout();
ldm.clo.show(ldm.cards, WELCOMEPANEL);
return ldm;
}
public ActionListener timeoutPanelListener(Timer timer){ //listener for main screen timeout - returns to ads
ActionListener timeout = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, SCREENSAVERPANEL);
timer.stop();
changeTimer = new Timer(5000,changeImageListener(screenImage));
changeTimer.start();
}
};
return timeout;
}
public ActionListener changeImageListener(JLabel image){ //listener for changing images in Screensaver
ActionListener change = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
image.setIcon(new ImageIcon(getClass().getResource(FILEARRAY[INDEX])));
INDEX++;
if (INDEX >= FILEARRAY.length) INDEX = 0;
}
};
return change;
}
public KeyListener stopScreensaver(){
KeyListener key = new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, WELCOMEPANEL);
Timer timer2 = new Timer(10000,null);
ActionListener timeout = ldm.timeoutPanelListener(timer2);
timer2.addActionListener(timeout);
timer2.start();
System.out.println("key typed");
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, WELCOMEPANEL);
Timer timer2 = new Timer(10000,null);
timer2.start();
ActionListener timeout = ldm.timeoutPanelListener(timer2);
}
};
return key;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, UnsupportedLookAndFeelException{
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
invokeLater(new Runnable(){
#Override
public void run(){
ldm = createAndShowGUI();
Timer timer = new Timer(5000,null);
ActionListener timeout = ldm.timeoutPanelListener(timer);
timer.addActionListener(timeout);
timer.start();
}
});
}
}
When using CardLayout focus is not placed on the panel when the card is switched. Since the panel doesn't have focus it can't receive KeyEvents.
So first you need to make the panel focusable.
Secondly, you need to give the panel focus when it is made visible. Check out Card Layout Focus. This is a class extends CardLayout and gives the panel focus when it is made visible.
I have 4 JPanels. In one of the panel I have a combo Box.Upon selecting "Value A" in combo box Panel2 should be displayed.Similarly if I select "Value B" Panel3 should be selected....
Though action Listener should be used in this context.How to make a call to another tab with in that action listener.
public class SearchComponent
{
....
.
public SearchAddComponent(....)
{
panel = addDropDown(panelList(), "panel", gridbag, h6Box);
panel.addComponentListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ItemSelectable is = (ItemSelectable)actionEvent.getSource();
Object name=selectedString(is);
}
});
}
public static final Vector<String> panelList(){
List<String> panelList = new ArrayList<String>();
panelList.add("A");
panelList.add("B");
panelList.add("C");
panelList.add("D");
panelList.add("E");
panelList.add("F);
Vector<String> panelVector = null;
Collections.copy(panelVector, panelList);
return panelVector;
}
public Object selectedString(ItemSelectable is) {
Object selected[] = is.getSelectedObjects();
return ((selected.length == 0) ? "null" : (ComboItem)selected[0]);
}
}
Use a Card Layout. See the Swing tutorial on How to Use a Card Layout for a working example.
Try This code:
import java.awt.EventQueue;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class CardLayoutExample {
JFrame guiFrame;
CardLayout cards;
JPanel cardPanel;
public static void main(String[] args) {
//Use the event dispatch thread for Swing components
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new CardLayoutExample();
}
});
}
public CardLayoutExample()
{
guiFrame = new JFrame();
//make sure the program exits when the frame closes
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("CardLayout Example");
guiFrame.setSize(400,300);
//This will center the JFrame in the middle of the screen
guiFrame.setLocationRelativeTo(null);
guiFrame.setLayout(new BorderLayout());
//creating a border to highlight the JPanel areas
Border outline = BorderFactory.createLineBorder(Color.black);
JPanel tabsPanel = new JPanel();
tabsPanel.setBorder(outline);
JButton switchCards = new JButton("Switch Card");
switchCards.setActionCommand("Switch Card");
switchCards.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
cards.next(cardPanel);
}
});
tabsPanel.add(switchCards);
guiFrame.add(tabsPanel,BorderLayout.NORTH);
cards = new CardLayout();
cardPanel = new JPanel();
cardPanel.setLayout(cards);
cards.show(cardPanel, "Fruits");
JPanel firstCard = new JPanel();
firstCard.setBackground(Color.GREEN);
addButton(firstCard, "APPLES");
addButton(firstCard, "ORANGES");
addButton(firstCard, "BANANAS");
JPanel secondCard = new JPanel();
secondCard.setBackground(Color.BLUE);
addButton(secondCard, "LEEKS");
addButton(secondCard, "TOMATOES");
addButton(secondCard, "PEAS");
cardPanel.add(firstCard, "Fruits");
cardPanel.add(secondCard, "Veggies");
guiFrame.add(tabsPanel,BorderLayout.NORTH);
guiFrame.add(cardPanel,BorderLayout.CENTER);
guiFrame.setVisible(true);
}
//All the buttons are following the same pattern
//so create them all in one place.
private void addButton(Container parent, String name)
{
JButton but = new JButton(name);
but.setActionCommand(name);
parent.add(but);
}
}
I have a MainPanel which uses the Gridlayout. Consequently I have created four JPanel classes for the: NORTH, EAST, CENTER and EAST layouts respectively. I then add all four to my MainPanel.
However, on my WEST panel I use another grid layout to store JButtons and JTextFields. I want to constantly update my JTextFields as they display a value (that changes when a button on another panel is clicked). How do I allow that value to be changed when the JFrame is running?
I tried using paintComponent, but it keeps on adding multiple copies of the same JTextField after each other, as I add it in my paintComponent method. If I remove the add method the values won't update.
Action works well to encapsulate such functionality. In the example below, a number of text fields listen for an ActionEvent received from a single Update button. The common UpdateHandler is derived from AbstractAction.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
/** #see http://stackoverflow.com/a/14947144/230513 */
public class Test {
private JButton button = new JButton("Update");
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(createPanel(button), BorderLayout.NORTH);
f.add(createPanel(button), BorderLayout.WEST);
f.add(createPanel(button), BorderLayout.EAST);
f.add(createPanel(button), BorderLayout.SOUTH);
JPanel p = new JPanel();
p.add(button);
f.add(p, BorderLayout.CENTER);
f.getRootPane().setDefaultButton(button);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static JPanel createPanel(JButton b) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
final JTextField text = new JTextField();
b.addActionListener(new UpdateHandler(text));
panel.add(text);
return panel;
}
private static class UpdateHandler extends AbstractAction {
private JTextField text;
private DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS");
public UpdateHandler(JTextField t) {
super("update");
t.setText(df.format(new Date()));
this.text = t;
}
#Override
public void actionPerformed(ActionEvent e) {
text.setText(df.format(new Date()));
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}