I have a very basic question on 'panel'.
I have my same program below, which I want to hit on a submit button on panel 1 and my program would print a hello you hit on a submit button on panel 2.
I do not see the program print hello you hit on a submit button on panel 2 while a hit a submit button on panel 2. But when I touch the frame, then magically the hello you hit on a submit button on panel 2 appear on panel 2.
What is going on ? I don't know the answer so I would like to ask if you know why?
Attached is my code:
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.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class Main {
private JFrame frame = new JFrame();
private JLayeredPane lpane = new JLayeredPane();
private JPanel panelBlue = new JPanel();
private JPanel panelGreen = new JPanel();
private JButton btn1 = new JButton ("Button1");
public Main()
{
frame.setPreferredSize(new Dimension(600, 400));
frame.setLayout(new BorderLayout());
frame.add(lpane, BorderLayout.CENTER);
lpane.setBounds(0, 0, 600, 400);
panelBlue.setBackground(Color.BLUE);
panelBlue.setBounds(0, 0, 600, 400);
panelBlue.setOpaque(true);
panelBlue.add (btn1);
panelGreen.setBackground(Color.GREEN);
panelGreen.setBounds(200, 100, 100, 100);
panelGreen.setOpaque(true);
btn1.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
panelGreen.add(new JLabel ("You click button1"));
}});
lpane.add(panelBlue, new Integer(0), 0);
lpane.add(panelGreen, new Integer(1), 0);
frame.pack();
frame.setVisible(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new Main();
}
}
Call panelGreen.revaliate() and panelGreen.repaint() after you add the label. Swing layouts are lazy.
#Override
public void actionPerformed(ActionEvent e) {
panelGreen.add(new JLabel ("You click button1"));
panelGreen.revaliate();
panelGreen.repaint();
}});
Calling setOpaque is irrelevant as the components are opaque to start with
Related
I seem to not be able to find a way to get my code to work.
I am making a program and until now everything was working, i have some buttons and they do what they should.
But now i added a button that when a user click it, it should close the current GUI and open a new one.
I also want to point out that i created a new class for this new GUI.
The other GUI class that i want to call is the GuiCrafting, in that class the GUI is also all coded, and works if i call it on the Main.
My question is what do i type here (I tried a lot of things like dispose() etc but i just get error messages) :
public void actionPerformed(ActionEvent event) {
if( str.equals("Crafting")){
//insert code to call the GuiCrafting class and open his GUI
}
Thanks in advance and if you need something more please let me know.
Multiple JFrames are frowned upon as you can read about here and here
Perhaps what you want to use is a CardLayout which manages two or more components (usually JPanel instances) that share the same display space.
After clicking the button "Goto Card 2"
TestApp.java:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestApp {
final static String CARD1 = "Card1";
final static String CARD2 = "Card2";
public TestApp() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestApp::new);
}
private void initComponents() {
JFrame frame = new JFrame("TestApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create the panel that contains the "cards".
JPanel cards = new JPanel(new CardLayout());
// card 1 components
JButton buttonGotoCard2 = new JButton("Goto Card 2");
buttonGotoCard2.addActionListener((ActionEvent e) -> {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, CARD2);
});
// create card 1
JPanel card1 = new JPanel();
card1.add(new JLabel("Card 1"));
card1.add(buttonGotoCard2);
// card 2 components
JButton buttonGotoCard1 = new JButton("Goto Card 1");
buttonGotoCard1.addActionListener((ActionEvent e) -> {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, CARD1);
});
// create card 2
JPanel card2 = new JPanel();
card2.add(new JLabel("Card 2"));
card2.add(buttonGotoCard1);
// add cards to cards panel
cards.add(card1, CARD1);
cards.add(card2, CARD2);
frame.getContentPane().add(cards, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
There is also a JDialog which could be what you want.
HOWEVER
You can easily do something like that (Open a JFrame from another If you must):
TestApp.java:
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class TestApp {
public TestApp() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestApp::new);
}
private void initComponents() {
JFrame mainFrame = new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
JLabel label = new JLabel("JFrame 1");
JButton button = new JButton("Open JFrame 2");
button.addActionListener((ActionEvent e) -> {
this.showNewJFrame(new WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent e) {
// here we listen for the second JFrame being closed so we can bring back the main JFrame
mainFrame.setVisible(true);
}
});
// hide the main JFrame
mainFrame.setVisible(false);
});
panel.add(label);
panel.add(button);
mainFrame.add(panel);
mainFrame.pack();
mainFrame.setVisible(true);
}
private void showNewJFrame(WindowAdapter windowAdapter) {
JFrame frame2 = new JFrame();
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // we dont wnat to exit when this JFrame is closed
JPanel panel2 = new JPanel();
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
panel2.setBorder(new EmptyBorder(10, 10, 10, 10));
JLabel label2 = new JLabel("JFrame 2");
panel2.add(label2);
frame2.add(panel2);
frame2.addWindowListener(windowAdapter);
frame2.pack();
frame2.setVisible(true);
}
}
This produces:
and when the "Open JFrame 2" is clicked:
and when JFrame 2 is closed it brings back the main JFrame via the WindowAdapter#windowClosing.
I have a JFrame with a button labelled as "order". When that button is clicked, a dialog box comes up. This dialog box is supposed to show a summary of items that are ordered as a text view. I thought of having a string as a way to view the order, but that did not work out...
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.SwingUtilities;
import javax.swing.JRadioButton;
public class PizzaOrder3 {
PizzaOrder3() {
JFrame frame = new JFrame();
JButton order = new JButton("Order");
JPanel panel1 = new JPanel();
panel1.add(order);
frame.getContentPane().add(panel1);
panel1.setBounds(350,632,110,40);
panel1.setOpaque(false);
//Action listener for showing summary of the order
order.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JDialog d = new JDialog(frame, "Hello", true);
//Where the coding for text view is meant to go
d.setSize(400, 300);
d.setVisible(true);
}
});
frame.setLayout(null);
frame.setSize(600, 700);
frame.getContentPane().setBackground(new Color(40, 80, 120));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
PizzaOrder3 PizzaOrder3 = new PizzaOrder3();
}
}
I'm trying to figure out how to position my buttons in the center right position. I added what Ive done so far and I'll add a drawing of how I want it to be.
I'm trying to understand how to determine the position I want in Swing, can't really understand the advantages of each layout.
My code so far:
package Game;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.Timer;
public class MainWindow extends JFrame implements ActionListener {
private JButton exit;
private JButton start_Game;
private ImageIcon puzzleBackground;
// private JLabel back_Label;
// private GridBagConstraints grid = new GridBagConstraints();
private JPanel menu;
public MainWindow()
{
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(450,300);
setLocationRelativeTo(null);
this.setLayout(new FlowLayout(FlowLayout.RIGHT));
menu = new JPanel();
menu.setLayout(new BorderLayout());
//setResizable(false);
//===== Background =====
puzzleBackground = new ImageIcon("MyBackground.jpg");
setContentPane(new JLabel(puzzleBackground));
exit = new JButton("Exit");
menu.add(exit, BorderLayout.CENTER);
exit.addActionListener(this);
start_Game = new JButton("Start to play");
menu.add(start_Game, BorderLayout.SOUTH);
exit.addActionListener(this);
start_Game.addActionListener(this);
//
// back_Label = new JLabel(puzzleBackground);
// back_Label.setLayout(new BorderLayout());
//===== Buttons =====
// back_Label.add(exit,BorderLayout.CENTER);
//
// back_Label.add(start_Game,BorderLayout.EAST);
//
add(menu);
setVisible(true);
}
public static void main(String args[])
{
MainWindow a = new MainWindow();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == exit)
{
System.exit(0);
}
else
{
//open start up window.
}
}
}
A better way to add a BG image is to use a custom painted JPanel. Then set the layout of the panel and add other panels or components to it. Note that here the buttons are not appearing largely because they are being added to a JLabel.
Here is an alternative that works along the same lines, with the red panel being the panel which custom paints the background image and the menu panel being set to transparent (look for the opaque method).
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
public class MainWindow extends JFrame {
private JPanel menu;
private JPanel contentPane = new JPanel(new BorderLayout(4,4));
public MainWindow() {
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//setSize(450, 300); // use pack() instead
setContentPane(contentPane);
contentPane.setBorder(new EmptyBorder(8,8,8,8));
contentPane.setBackground(Color.RED);
contentPane.add(new JLabel(new ImageIcon(
new BufferedImage(400,200,BufferedImage.TYPE_INT_RGB))));
menu = new JPanel(new GridLayout(0,1,10,10));
menu.add(new JButton("Exit"), BorderLayout.CENTER);
menu.add(new JButton("Start to play"), BorderLayout.SOUTH);
JPanel menuCenterPanel = new JPanel(new GridBagLayout());
menuCenterPanel.add(menu);
add(menuCenterPanel, BorderLayout.LINE_END);
pack();
setLocationRelativeTo(null); // do AFTER pack()
setMinimumSize(getSize());
setVisible(true);
}
public static void main(String args[]) {
MainWindow a = new MainWindow();
}
}
So, your basic problem boils down the following lines...
this.setLayout(new BorderLayout());
//...
//===== Background =====
puzzleBackground = new ImageIcon("MyBackground.jpg");
setContentPane(new JLabel(puzzleBackground));
Can you tell me what the layout manager in use actually is now? Wrong. The layout manager is now null, because JLabel doesn't actually have a default layout manager.
So, the "simple" answer would be to move the setLayout call to below the setContentPane call, but this would be a short sighted answer, as JLabel calculates it's preferred based on the icon and text properties only, not it's contents of child components.
A better solution would be to do something demonstrated in How to set a background picture in JPanel (see the second example)
This means that if the image is smaller then the required space, the components will disappear off the screen.
I went through and cleaned up the code slightly, only with the intention of getting the layout to work
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainWindow extends JFrame implements ActionListener {
private JButton exit;
private JButton start_Game;
private JPanel menu;
public MainWindow() {
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
menu = new JPanel();
menu.setLayout(new GridBagLayout());
exit = new JButton("Exit");
exit.addActionListener(this);
start_Game = new JButton("Start to play");
exit.addActionListener(this);
start_Game.addActionListener(this);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = gbc.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(exit, gbc);
menu.add(start_Game, gbc);
// This is just a filler, it can be removed, but it helps prove the point
add(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
add(menu, BorderLayout.EAST);
pack();
setVisible(true);
}
public static void main(String args[]) {
MainWindow a = new MainWindow();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
} else {
//open start up window.
}
}
}
I'd also like to point out that extending directly from JFrame is also short sighted, it's locking you into a single use container and you're not actually adding any new functionality to the class.
Example of better structure...
The following is a simple example of a possibly better structure. It's missing the concept of a "controller", which controls stuff and "model" which maintains the state information which is used by the UI to display "stuff", but gives a starting point
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String args[]) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Welcome");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
setLayout(new BorderLayout());
// This is just a filler, it can be removed, but it helps prove the point
add(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
add(new MenuPane(), BorderLayout.EAST);
}
}
public class MenuPane extends JPanel {
private JButton exit;
private JButton start_Game;
private JPanel menu;
public MenuPane() {
menu = new JPanel();
menu.setLayout(new GridBagLayout());
ActionHandler actionHandler = new ActionHandler();
exit = new JButton("Exit");
exit.addActionListener(actionHandler);
start_Game = new JButton("Start to play");
start_Game.addActionListener(actionHandler);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = gbc.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(exit, gbc);
menu.add(start_Game, gbc);
}
public class ActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
} else {
//open start up window.
// This should be used to notifiy a controller class
// that some new action needs to take place, the controller
// is then responsible for making it happen
}
}
}
}
}
Doing UI in Java is not advised, but ignoring that.
You get (calculate) the height and width of the screen. Then start drawing buttons depending on that. Drawing a button on screens 50% of pixel value width and 50% of pixel value of height will center the button.
Simply crate buttons with variable location that is calculated from main screen px size and place them where ever you want.
I am simply making a user interface and all i want it to do after the button is pressed is display thanks... I am pretty new to this but from what i see there are no errors? I have tried playing around with the set visible and to no avail...Any help is great thanks
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.JTextField;
import javax.swing.JLabel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JList;
public class GuiApp1 {
public static void main(String args[]) {
String title = (args.length == 0 ? "CheckBox Sample" : args[0]);
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel(new GridLayout(0, 1));
Border border = BorderFactory.createTitledBorder("Pizza Toppings");
panel.setBorder(border);
JLabel label1 = new JLabel("Enter name below:");
panel.add(label1);
JTextField field = new JTextField(20);
panel.add(field);
JCheckBox check = new JCheckBox("Car0");
panel.add(check);
check = new JCheckBox("Car1");
panel.add(check);
check = new JCheckBox("Car2");
panel.add(check);
check = new JCheckBox("Car3");
panel.add(check);
check = new JCheckBox("Car4");
panel.add(check);
JButton button = new JButton("Submit");
final JPanel listPanel = new JPanel();
listPanel.setVisible(false);
JLabel listLbl = new JLabel("Vegetables:");
listPanel.add(listLbl);
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
listPanel.setVisible(!listPanel.isVisible());
panel.setVisible(!panel.isVisible());
}
});
Container contentPane = frame.getContentPane();
contentPane.add(panel, BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);
frame.setSize(300, 300);
frame.setResizable(true);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
The reason for the vegetables panel not appearing is simple: Xou never add ist to the contentPane.
For the code to function properly you need to add/remove the panels in the ActionListener of the button:
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
listPanel.setVisible(!listPanel.isVisible());
panel.setVisible(!panel.isVisible());
if (listPanel.isVisible()) {
contentPane.remove(panel); // Vegetables are visible, so remove the Cars
contentPane.add(listPanel, BorderLayout.CENTER); // And add the Vegetables
} else {
contentPane.remove(listPanel); // Vice versa
contentPane.add(panel, BorderLayout.CENTER);
}
}
});
Then, you need to move the ActionListener below the contentPane declaration and make it final.
Also you should consider putting the different checkboxes is different variables, so you can read the state of them. If you don't want to have so many variables hanging you could put them into an array.
JCheckBox[] checks = new JCheckbox[5];
checks[0] = new JCheckBox("Car0");
panel.add(checks[0]);
...
I'm having trouble understanding the behaviour of a modal JDialog.
When the dialog is set to visible all works fine until the user clicks back on the parent JFrame that was used to launch it. Although the dialog remains on top as expected, all subsequent mouse clicks back on the JDialog are ignored. The form items in the JDialog can still be filled in, but only if you navigate using tab. Is this normal or am I missing something obvious?
Below is a simple example that illustrates the behaviour:
import java.awt.BorderLayout;
import java.awt.Dialog.ModalityType;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class TestApp {
private JFrame frame;
public TestApp() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnRun = new JButton("run");
btnRun.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
JDialog dialog = getChildDialog();
dialog.setModalityType(ModalityType.APPLICATION_MODAL);
dialog.setVisible(true);
}
});
frame.getContentPane().add(btnRun, BorderLayout.CENTER);
}
public JDialog getChildDialog() {
JDialog dialog = new JDialog();
dialog.setModalityType(ModalityType.APPLICATION_MODAL);
dialog.setBounds(100, 100, 450, 300);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JTextField(), BorderLayout.CENTER);
panel.add(new JTextField(), BorderLayout.NORTH);
panel.add(new JTextField(), BorderLayout.SOUTH);
panel.add(new JLabel("Blah"), BorderLayout.EAST);
panel.add(new JLabel("Blah"), BorderLayout.WEST);
dialog.getContentPane().setLayout(new BorderLayout());
dialog.getContentPane().add(panel, BorderLayout.CENTER);
return dialog;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestApp window = new TestApp();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
Thank you for the feedback. I think this must be a bug in the JVM I'm using (OpenJDK 2.4.7 7u55-2.4.7-1ubuntu1).
I've just run the same code on a Windows Java 7 JVM and don't get the same behaviour. I will submit a bug report.