I'm working on a little menu for a game. I already did the game itself, but I'm experiencing some problems with my menu. When I click on the buttons "Rules and Controls", "Options", and "About", the JLabels attached to them don't show up.
What am I doing wrong..?
Thanks in advance.
import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
public class Menu extends JFrame
{
private static final long serialVersionUID = 1L;
public Menu()
{
// Creating a new JFrame and setting stuff
JFrame frame = new JFrame("BREAK THE BRICKS - MENU");
frame.setResizable(false);
frame.setBounds(43, 10, 1280, 720);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//Creating a menu panel
JPanel menupanel = new JPanel();
menupanel.setLayout(null);
setContentPane(menupanel);
frame.add(menupanel);
//PRINCIPAL BUTTONS OF THE MENU
//Creating buttons
JButton buttonrules = new JButton();
JButton buttonoptions = new JButton();
JButton buttonabout = new JButton();
JButton buttonplay = new JButton("PLAY");
//Setting their bounds
buttonrules.setBounds(56, 224, 400, 83);
buttonoptions.setBounds(56, 302, 400, 82);
buttonabout.setBounds(56, 379, 400, 83);
buttonplay.setBounds(56, 486, 400, 110);
//Setting their border's color
buttonrules.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 5));
buttonoptions.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 5));
buttonabout.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 5));
buttonplay.setBorder(BorderFactory.createLineBorder(Color.GRAY, 5));
//Setting their content and font
buttonrules.setContentAreaFilled(false);
buttonoptions.setContentAreaFilled(false);
buttonabout.setContentAreaFilled(false);
buttonplay.setFont(new Font("Mesquite Std", Font.PLAIN, 99));
//Adding them to the principal panel
menupanel.add(buttonrules);
menupanel.add(buttonoptions);
menupanel.add(buttonabout);
menupanel.add(buttonplay);
//BACKGROUND MENU'S IMAGE
//Attaching the principal background image to the principal panel
JLabel labelbackground = new JLabel();
menupanel.add(labelbackground);
labelbackground.setBounds(0, 0, 1280, 720);
Image background = new ImageIcon(this.getClass().getResource("/Menu_Principal.jpg")).getImage();
labelbackground.setIcon(new ImageIcon(background));
//BOXES ON THE RIGHT-HAND SIDE OF THE SCREEN
//RULES AND CONTROLS
//Creating a JLabel and setting stuff
JLabel labelboxrules = new JLabel();
labelboxrules.setForeground(Color.WHITE);
labelboxrules.setBounds(475, 159, 754, 500);
//Importing rules and controls' image and setting it to its label
Image rulandconimg = new ImageIcon(this.getClass().getResource("/Rules_And_Controls.jpg")).getImage();
labelboxrules.setIcon(new ImageIcon(rulandconimg));
//OPTIONS
//Creating a JLabel and setting stuff
JLabel labelboxoptions = new JLabel();
labelboxoptions.setForeground(Color.WHITE);
labelboxoptions.setBounds(475, 159, 754, 500);
//Importing options' image and setting it to its label
Image optionsimg = new ImageIcon(this.getClass().getResource("/Options.jpg")).getImage();
labelboxoptions.setIcon(new ImageIcon(optionsimg));
//ABOUT
//Creating a JLabel and setting stuff
JLabel labelboxabout = new JLabel();
labelboxabout.setForeground(Color.WHITE);
labelboxabout.setBounds(475, 159, 754, 500);
//Importing about's image and setting it to its label
Image aboutimg = new ImageIcon(this.getClass().getResource("/About.jpg")).getImage();
labelboxabout.setIcon(new ImageIcon(aboutimg));
//THEIR FUTURE BORDER
Border boxborder = BorderFactory.createLineBorder(Color.LIGHT_GRAY, 5);
//ASSOCIATING ACTIONS WITH MENU'S BUTTONS
//Rules and Controls
buttonrules.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent a)
{
labelboxrules.setBorder(boxborder);
labelbackground.add(labelboxrules);
labelboxrules.setVisible(true);
}
});
//Options
buttonoptions.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent a)
{
labelboxoptions.setBorder(boxborder);
labelbackground.add(labelboxoptions);
labelboxoptions.setVisible(true);
}
});
//About
buttonabout.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent a)
{
labelboxabout.setBorder(boxborder);
labelbackground.add(labelboxabout);
labelboxabout.setVisible(true);
}
});
//Play
buttonplay.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent c)
{
Game.myGame();
}
});
}
}
you have to revalidate and repaint the panel after you add components .but as camicker and madprogrammer pointed out revalidate is pointless when not using layout managers.if you use layout managers then you have to call revalidate before repaint.
also by the default jlables are visible unlike jframes so calling labelboxoptions.setVisible(true); is redundant .
for example
buttonoptions.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a) {
labelboxoptions.setBorder(boxborder);
labelbackground.add(labelboxoptions);
labelboxoptions.setVisible(true);
menupanel.repaint();
}
});
note:
don't use null layout. use layout managers. .
As suggested by Andrew and MadProgrammer
Dont use setLayout(null),
Updated and removed the not required statements
Related
I wrote a little something here. It's working if I don't backPanel.setLayout(new GridBagLayout);
But without the grid bag, the content stays in the top left I maximise the screen.
With the grid bag I only get the red backPanel in the frame. Well, there is a gray pixel in the middle of the screen. I'm assuming that's my panel, but I can't make it bigger. I tried setSize but it doesn't change. Also, I had the panel.setBounds(0, 0, getWidth(),getHeight());. I'm not sure why I removed it.
My main is in the other file. The only thing it does at the moment is to call the LoginFrame.
Here is the code:
package first;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
public class LoginFrame extends JFrame implements ActionListener {
private JTextField textField;
private JPasswordField passwordField;
public LoginFrame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500, 300);
JPanel backPanel = new JPanel(new GridBagLayout());
backPanel.setBackground(Color.RED);
JPanel panel = new JPanel();
panel.setSize(500, 300);
panel.setBackground(Color.LIGHT_GRAY);
panel.setLayout(null);
JLabel label;
panel.add(label = new JLabel("Username:"));
label.setBounds(20, 100, 100, 25);
panel.add(textField = new JTextField());
textField.setBounds(140, 100, 200, 25);
panel.add(label = new JLabel("Password:"));
label.setBounds(20, 145, 100, 25);
panel.add(passwordField = new JPasswordField());
passwordField.setBounds(140, 145, 200, 25);
panel.add(label = new JLabel("CTC Bank"));
label.setFont(new Font("New Times Roman", Font.BOLD, 50));
label.setBounds(0, 0, getWidth(), 100);
label.setHorizontalAlignment(JLabel.CENTER);
JButton button;
panel.add(button = new JButton("Login"));
button.setBounds(140, 200, 100, 25);
button.addActionListener(this);
button = defaultActionKeyEnter(button, KeyEvent.VK_ENTER);
panel.add(button = new JButton("Register"));
button.setBounds(240, 200, 100, 25);
button.addActionListener(this);
button = defaultActionKeyEnter(button, KeyEvent.VK_ENTER);
//add(panel);
backPanel.add(panel);
add(backPanel, BorderLayout.CENTER);
revalidate();
repaint();
setLocationRelativeTo(null);
setVisible(true);
}
public static JButton defaultActionKeyEnter(JButton button, int desiredKeyCode) {
InputMap inputMap = button.getInputMap(JComponent.WHEN_FOCUSED);
KeyStroke spaceKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false);
KeyStroke spaceKeyReleased = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true);
KeyStroke desiredKeyPressed = KeyStroke.getKeyStroke(desiredKeyCode, 0, false);
KeyStroke desiredKeyReleased = KeyStroke.getKeyStroke(desiredKeyCode, 0, true);
inputMap.put(desiredKeyPressed, inputMap.get(spaceKeyPressed));
inputMap.put(desiredKeyReleased, inputMap.get(spaceKeyReleased));
inputMap.put(spaceKeyPressed, "none");
inputMap.put(spaceKeyReleased, "none");
return button;
}
// Unfinished code dont worry bout it...
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Login")) {
if (textField.getText().equals("Heinz")
&& (new String(passwordField.getPassword()).equals("password123"))) {
// color = Color.GREEN;
} else {
JOptionPane.showMessageDialog(this, "Wrong Username or Password", "Error", JOptionPane.WARNING_MESSAGE);
// color = Color.RED;
}
} else {
JOptionPane.showMessageDialog(this, "Cya");
dispose();
setVisible(false);
}
// panel.setBackground(color);
}
}
I have seen questions about this but none of the answers were helpful in my case.
Calling the following didn't help.
revalidate();
repaint();
Did I maybe add it in the wrong order?
And how does the code look like to you? Would you consider this clean?
The layout of backPanel will mis-calculate the dimensions of "panel" because "panel" does not participate in layout management properly, without a layout manager of its own.
One solution to this is to use setLayout(null) also on the "backPanel", or add "panel" directly to the JFrame.
With the first suggestion ("backPanel.setLayout(null);" just after it is created), plus the following main method:
public static void main(String[] args) {
new LoginFrame();
}
I get this:
I am trying to show a text saying "The background is (color)" whenever I press a button that has the name of the color written on it but the text doesn't show up.
How it is supposed to be:
but mine is like this:
Here is my code:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ThreeBtn extends JFrame {
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
public class ButtonListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == btnRed) {
(getContentPane()).setBackground(Color.red);
JLabel label = new JLabel("빨간색 배경입니다."); //it means "The background is red" in Korean label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
(getContentPane()).add(label);
}
else if(e.getSource()==btnGreen) {
(getContentPane()).setBackground(Color.green);
JLabel label = new JLabel("초록색 배경입니다."); //it means "The background is green" in Korean
label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
(getContentPane()).add(label);
}
else if(e.getSource()==btnBlue) {
(getContentPane()).setBackground(Color.blue);
JLabel label = new JLabel("파란색 배경입니다."); //it means "The background is blue" in Korean
label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
(getContentPane()).add(label);
}
}
}
public ThreeBtn() {
setSize(300, 200);
setTitle("Three Button Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setLayout(new FlowLayout());
btnRed = new JButton("RED");
btnGreen = new JButton("GREEN");
btnBlue = new JButton("Blue");
ButtonListener listener = new ButtonListener();
btnRed.addActionListener(listener);
btnGreen.addActionListener(listener);
btnBlue.addActionListener(listener);
cPane.add(btnRed);
cPane.add(btnGreen);
cPane.add(btnBlue);
}
public static void main(String[] args) {
(new ThreeBtn()).setVisible(true);
}
}
I am wondering if I used JLabel in a wrong way in the ActionListener but I can't figure it out.
I would really appreciate your help.
When adding or deleting components to your GUI on runtime, you have to tell Swing that you did so. To do this, you should use revalidate() and repaint() on the container where the modification happened.
However, in your case, you don't actually need to always add a new JLabel on runtime, as you can simply do that when setting up the GUI, and only modifying the label that is already there. By doing it this way, you avoid having to revalidate() and repaint() (and it is also easier and cleaner this way).
I updated your code and did the following modificiations:
Moved the declaration and initialization of the JLabel out of the actionPerformed(), so you don't have to create a new JLabel each time a button is pressed. Now, only the text is changed. (A side effect of this change is, that the revalidate() and repaint() are actually not needed anymore, as no more component is added during runtime)
Started the GUI on the Event Dispatch Thread via SwingUtilities.invokeLater().
Usually it is also good practice in Swing to not create a subclass of JFrame if this is not specifically needed (like in your case). The better approach is to subclass JPanel, add the necessary components there, override getPreferredSize() and then add this to the JFrame. I have not included this change here, since it might have caused too much confusion.
Updated code:
public class ThreeBtn extends JFrame {
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
private JLabel label;
public class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Container contentPane = getContentPane();
if (e.getSource() == btnRed) {
contentPane.setBackground(Color.red);
label.setText("red in korean");
} else if (e.getSource() == btnGreen) {
contentPane.setBackground(Color.green);
label.setText("green in korean");
} else if (e.getSource() == btnBlue) {
contentPane.setBackground(Color.blue);
label.setText("blue in korean");
}
}
}
public ThreeBtn() {
setSize(300, 200);
setTitle("Three Button Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setLayout(new FlowLayout());
btnRed = new JButton("RED");
btnGreen = new JButton("GREEN");
btnBlue = new JButton("BLUE");
label = new JLabel("");
label.setFont(new Font("Serif", Font.BOLD, 25));
label.setForeground(Color.yellow);
ButtonListener listener = new ButtonListener();
btnRed.addActionListener(listener);
btnGreen.addActionListener(listener);
btnBlue.addActionListener(listener);
cPane.add(btnRed);
cPane.add(btnGreen);
cPane.add(btnBlue);
cPane.add(label);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> (new ThreeBtn()).setVisible(true));
}
}
Output:
This now works as per your requirements with the used FlowLayout. However, you may use another layout manager (or combine different ones) if you plan on doing more with it.
The Dimensions of the frame and panel where small so they did not show the text when you pressed the buttons.
Dimension size = label.getPreferredSize();
label.setBounds(150, 100, size.width, size.height);
I dont know if there are any rules for your program, but I would suggest, just limiting your if statements in ActionListener to the point where you set the foreground. Then make your JLabel object a class variable, and add the JLabel in the constructor. Here is the full edited code:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ThreeBtn extends JFrame {
private static final long serialVersionUID = 1L;
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
private JLabel text = new JLabel();
public class ButtonListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == btnRed) {
(getContentPane()).setBackground(Color.red);
text.setText("red"); //it means "The background is red" in Korean
text.setFont(new Font("Serif", Font.BOLD, 25));
text.setForeground(Color.yellow);
}
else if(e.getSource()==btnGreen) {
(getContentPane()).setBackground(Color.green);
text.setText("green"); //it means "The background is green" in Korean
text.setFont(new Font("Serif", Font.BOLD, 25));
text.setForeground(Color.yellow);
}
else if(e.getSource()==btnBlue) {
(getContentPane()).setBackground(Color.blue);
text.setText("blue"); //it means "The background is blue" in Korean
text.setFont(new Font("Serif", Font.BOLD, 25));
text.setForeground(Color.yellow);
(getContentPane()).add(text);
}
}
}
public ThreeBtn() {
setSize(300, 200);
setTitle("Three Button Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setLayout(new FlowLayout());
btnRed = new JButton("RED");
btnGreen = new JButton("GREEN");
btnBlue = new JButton("Blue");
ButtonListener listener = new ButtonListener();
btnRed.addActionListener(listener);
btnGreen.addActionListener(listener);
btnBlue.addActionListener(listener);
cPane.add(btnRed);
cPane.add(btnGreen);
cPane.add(btnBlue);
cPane.add(text);
}
public static void main(String[] args) {
(new ThreeBtn()).setVisible(true);
}
}
Iam trying to build a desktop application with multiple screens inside one single JFrame.
So each button click event will take us to the separate screen with refreshed components in the screen. So far this approach is working for me but the problem I am facing is even after using ".dispose(), .repaint(), .revalidate(), .invalidate()" functions. JInternalFrame or Jpanel seems to not refresh its components.
Which works something like below gif.
Tabbed Style
I do know JtabbedPane exists but for my method JtabbedPane is not viable.
Below I am posting minified code by replicating the problem I am facing.
MainMenu.Java(file with Main Class)
package test;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JInternalFrame;
public class MainMenu extends JFrame {
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainMenu frame = new MainMenu();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MainMenu() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 841, 522);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(10, 10, 807, 63);
contentPane.add(panel);
panel.setLayout(new GridLayout(1, 0, 0, 0));
JButton Tab1 = new JButton("Tab1");
panel.add(Tab1);
JButton Tab2 = new JButton("Tab2");
panel.add(Tab2);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 88, 807, 387);
contentPane.add(scrollPane);
JInternalFrame internalFrame1 = new JInternalFrame();
JInternalFrame internalFrame2 = new JInternalFrame();
Tab1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Panel1 panel1 = new Panel1();
if(internalFrame1 !=null) {
internalFrame1.dispose();
panel1.invalidate();
panel1.revalidate();
panel1.repaint();
}
internalFrame1.setTitle("Panel 1");
scrollPane.setViewportView(internalFrame1);
internalFrame1.getContentPane().add(panel1);
internalFrame1.setVisible(true);
}
});
Tab2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Panel2 panel2 = new Panel2();
if(internalFrame2 !=null) {
internalFrame2.dispose();
panel2.invalidate();
panel2.revalidate();
panel2.repaint();
}
internalFrame2.setTitle("Panel 2");
scrollPane.setViewportView(internalFrame2);
internalFrame2.getContentPane().add(panel2);
internalFrame2.setVisible(true);
}
});
}
}
and the corresponding Jpanel class files where JInternal Frames
Panel1.java
package test;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
public class Panel1 extends JPanel {
private JTextField textField;
/**
* Create the panel.
*/
public Panel1() {
setLayout(null);
textField = new JTextField();
textField.setBounds(10, 60, 430, 19);
add(textField);
textField.setColumns(10);
JButton btnNewButton = new JButton("Example Button");
btnNewButton.setBounds(10, 156, 430, 21);
add(btnNewButton);
}
}
Panel2.java
package test;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
public class Panel2 extends JPanel {
private JTextField textField;
/**
* Create the panel.
*/
public Panel2() {
setLayout(null);
textField = new JTextField();
textField.setBounds(10, 60, 430, 19);
add(textField);
textField.setColumns(10);
JButton btnNewButton = new JButton("New button2");
btnNewButton.setBounds(21, 157, 419, 21);
add(btnNewButton);
}
}
P.S: This is my first time asking question in Stackoverflow so forgive me and if possible guide me if i miss anything
Thank you :)
Edit:
The problem I am facing is on the surface it looks like the Jpanel has been refreshed but the components like JtextField Still hides the previously written text in it and only show the text when i click on that JTextField
Below I am Attaching another gif which show highlights the issue. I have highlighted the part where I am facing issue.
Issue I am Facing
The dispose() method does not remove components so you keep adding components to the internal frame when you use the following:
internalFrame1.getContentPane().add(panel1);
Instead you might do something like:
Container contentPane = internalFrame1.getContentPane();
contentPane.removeAll();
contentPane.add( panel1 );
contentPane.revalidate();
contentPane.repaint();
You can use the JPanels in the Jframes and then use the CardLayout to change the panel ( which could than act like the different screens )
As the title, I want to create two buttons in java swing and these two buttons can overlap each other (as image). I searched the internet but I could not find it.
Thanks so much
You can simply do this by setting the JFrame layout to Absolute Layout, and adding a JButton on top of another JButton. Make sure the small button is on top of the other button in the navigator.
You can use an OverlayLayout here.
An SSCCE (with comments inside) would be:
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
import javax.swing.SwingUtilities;
public class OverlayLayoutExample extends JFrame {
JPanel overlayoutPanel;
JButton jButton2, jButton1;
public OverlayLayoutExample() {
overlayoutPanel = new JPanel() {
#Override
public boolean isOptimizedDrawingEnabled() {
//Required to have always visible both components
return false;
}
};
OverlayLayout overlay = new OverlayLayout(overlayoutPanel);
overlayoutPanel.setLayout(overlay);
jButton1 = new JButton("jButton");
Dimension d1 = new Dimension(350, 100);
jButton1.setMaximumSize(d1);
jButton1.setAlignmentX(0.7f); //Some X-Y values, play with them
jButton1.setAlignmentY(0.65f); //Some X-Y values, play with them
jButton2 = new JButton("jButton2");
Dimension d2 = new Dimension(100, 25);
jButton2.setMaximumSize(d2);
jButton2.setAlignmentX(0.01f); //Some X-Y values, play with them
jButton2.setAlignmentY(0.01f); //Some X-Y values, play with them
overlayoutPanel.add(jButton2); //First the top component
overlayoutPanel.add(jButton1); //Then the above component
getContentPane().add(overlayoutPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 300);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(() -> new OverlayLayoutExample().setVisible(true));
}
}
More about isOptimizedDrawingEnabled() can be found here.
Preview:
You can do this using the layered pane of JFrame like this:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
public class ButtonOnTop
{
public static void main(String[] args)
{
JButton button1 = new JButton("jButton1");
button1.setBounds(30, 50, 260, 160);
JButton button2 = new JButton("jButton2");
button2.setBounds(150, 150, 100, 40);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLayeredPane layeredPane = f.getLayeredPane();
layeredPane.add(button1, Integer.valueOf(0));
layeredPane.add(button2, Integer.valueOf(1));
f.setBounds(300, 200, 400, 300);
f.setVisible(true);
}
}
After some years working in Java in the back end I ended up working in a project to build a GUI and Java Swing is driving me crazy.
So I am doing some tests with the JScrollPane, because I have a JPanel that is too big to fit in the screen. In the following example I am adding couple buttons to a JPanel and then creating a JScrollPane with the JPanel, but nothing appears in the screen.
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class TestScrollPane extends JDialog {
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
TestScrollPane dialog = new TestScrollPane();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create the dialog.
*/
public TestScrollPane() {
setBounds(100, 100, 857, 541);
getContentPane().setLayout(null);
{
JPanel panel = new JPanel();
panel.setBounds(131, 167, 141, 221);
getContentPane().add(panel);
panel.setLayout(null);
{
JButton btnNewButton = new JButton("New button");
btnNewButton.setBounds(0, 0, 115, 29);
panel.add(btnNewButton);
}
{
JButton btnNewButton_1 = new JButton("New button");
btnNewButton_1.setBounds(26, 192, 115, 29);
panel.add(btnNewButton_1);
}
JScrollPane jsp = new JScrollPane(panel);
getContentPane().add(jsp);
}
{
JPanel buttonPane = new JPanel();
buttonPane.setBounds(0, 446, 835, 39);
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane);
{
JButton okButton = new JButton("OK");
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("Cancel");
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
}
}
I don't understand why is not appearing. I create the JPanel I add the buttons, and the the JScrollPane, which I add to the window. I am using WindwBuilder Pro that's why the code looks so weird.
Thanks.
I have changed
getContentPane().setLayout(null);
panel.setLayout(null);
to
getContentPane().setLayout(new FlowLayout());
panel.setLayout(new FlowLayout());
Now I see all 4 buttons.
The components of a panel must be lay out by code if not using a layout manager, that is, when using setLayout(null). Most components start with dimension zero and will therefore not be displayed.
In above code there is missing the position and dimension of the scroll pane: jsp.setBounds(...) like done with the other components.
Normally it is not recommend to lay out the components yourself, better use a LayoutManager (e.g. GridBagLayout, BorderLayout,...) for that.
See Oracle's tutorial: Lesson: Laying Out Components Within a Container