why is this button still filling the whole frame? - java

I have this code
package com.net.Forms;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MainForm {
protected static JFrame window = new JFrame("Test Form");
protected static JButton btnOK = new JButton("OK!");
public static void Main() {
load();
return;
}
public static void load() {
window.setSize(500, 500);
window.setVisible(true);
//btnOK.setSize(50, 50); //here
window.add(btnOK);
btnOK.setEnabled(true);
btnOK.setVisible(true);
}
}
Why is the button still filling the frame instead of being 50 X 50 like i stated above
Any help would be appreciated

The default Layout for JFrame is BorderLayout. That's why when you are adding a JButton to it , It is adding the JButton to the center and expanding it to cover entire window. BorderLayout doesn't respect the setSize(..) method of components being added to them. If you still want to give a preferred size to the component being added to JFrame you should change the layout to be FlowLayout or GridLayout or others.. and then use setPreferredSize(..) method with the component while adding it to the JFrame. For example Your code could be modified in following way.
import java.awt.*;
import javax.swing.*;
public class MainForm {
protected JFrame window = new JFrame("Test Form");
protected JButton btnOK = new JButton("OK!");
public static void main(String st[]) {
SwingUtilities.invokeLater( new Runnable()
{
public void run()
{
MainForm mf = new MainForm();
mf.load();
}
});
}
public void load() {
Container c = window.getContentPane();
c.setLayout(new FlowLayout());//Set layout to be FlowLayout explicitly.
btnOK.setPreferredSize(new Dimension(100,50));//use set PreferredSize
c.add(btnOK);
c.setSize(500, 500);
c.setVisible(true);
}
}

Its just a bug or sth.
the last element added to frame Takes Whole of it.
all you need to do :
declare a new simple component like JLabel()
add it to frame.
Dont set Bounds Or Size For it.just a new Label.
MAKE SURE that this label is the last element added to frame.
Hope it Works.

Related

JDesktopPane not displaying any component

I'm experimenting with desktop panes so I can use them in my work projects. The problem here is that I want to use an JInternalFrame within a JDesktopPane, in a normal JPanel it shows normally but cannot move it, using the desktop pane doesn't display any component added.
Here is the code of the last try, is simple just for learning how it works:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Internal_FrameShowtst extends JFrame{
Internal_FrameShowtst(){
BorderLayout bl = new BorderLayout();
JDesktopPane p = new JDesktopPane();
JPanel p1 = new JPanel();
JButton b = new JButton("click");
JInternalFrame in = new JInternalFrame("Test");
Internal_Frametst ift = new Internal_Frametst();
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//p1.add(new JLabel("hola"));
//in.add(p1);
//in.setVisible(true);
ift.setVisible(true);
}
});
p1.add(b);
bl.addLayoutComponent(p,BorderLayout.CENTER);
//p.add(in);
p.add(ift);
p.repaint();
setLayout(bl);
add(p);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Internal_FrameShowtst().setVisible(true);
}
});
}
}
custom internal frame class:
import javax.swing.*;
public class Internal_Frametst extends JInternalFrame {
Internal_Frametst(){
JPanel p = new JPanel();
JLabel label = new JLabel("Halo");
setIconifiable(true);
//setIcon(true);
setClosable(true);
p.add(label);
p.setSize(300,300);
add(p);
//setVisible(true);
}
}
I've read and tried the following:
Components inside JDesktopPane not showing
JDesktopPane not displaying components when adding JInternalFrame
I've tried adding the components directly, adding a JPanel, adding the internal frame, trying without it, creating the internal frame in the main class, creating my own internal frame in its own class, using layout managers with both panels (normal and desktop), all with the same result.
Your code creates several components that are never added to the visible UI at all. In the version you have posted, the internal frame is invisible and the button to make it visible is not part of the frame. But there are also problems with the initial sizes of the components.
I strongly recommend to keep the creation of a component, the setting of its initial properties, and the code to add it to a parent component close together in your source code.
Further, consider the points discussed in Prefer composition over inheritance? Your subclasses are entirely unnecessary.
Here is a revised version of your code that will open the internal frame when the button is clicked:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.*;
public class UiExample {
public static void main(String[] args) {
EventQueue.invokeLater(UiExample::initializeUI);
}
static void initializeUI() {
JPanel p1 = new JPanel();
JButton b = new JButton("Show Internal Frame");
p1.add(b);
JInternalFrame ift = initializeInternalFrame();
b.addActionListener(e -> {
ift.pack();
ift.setVisible(true);
});
JDesktopPane p = new JDesktopPane();
p.add(ift);
JFrame mainFrame = new JFrame();
mainFrame.setSize(300, 200);
mainFrame.getContentPane().add(p, BorderLayout.CENTER);
mainFrame.getContentPane().add(p1, BorderLayout.PAGE_START);
mainFrame.setVisible(true);
}
static JInternalFrame initializeInternalFrame() {
JInternalFrame iFrame = new JInternalFrame();
iFrame.setIconifiable(true);
// setIcon(true);
iFrame.setClosable(true);
iFrame.setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);
JPanel p = new JPanel();
p.add(new JLabel("Hello"));
iFrame.add(p);
return iFrame;
}
}
Note that setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE) is necessary for being able to show the frame again via setVisible(true) after the internal frame has been closed.

OK button and String not showing up on JPanel

I am trying to make a panel showing a printed statement "Hello World!" and an OK button. Neither will show up on the panel and I have no idea why. I started with a block of code that was supposed to create just a blank popup. The blank popup worked great. I can't add the string or button and see them. I have tried calling paintComponent. I have tried adding the content to the panel. Does anyone know what I am missing?
Here is my code
package painting;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SwingPaintDemo1 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static class SwingPaintDemo extends JPanel{
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("Hello World!", 20,30);
}
}
private static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(250,250);
f.setVisible(true);
JButton okbutton = new JButton("OK");
ButtonHandler listener = new ButtonHandler();
okbutton.addActionListener(listener);
SwingPaintDemo displayPanel = new SwingPaintDemo();
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okbutton, BorderLayout.SOUTH);
}
private static class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
You forgot to add the JPanel to the JFrame. Just add the following line at the bottom of your createAndShowGUI() method:
f.add(content);
I would also recommend moving your f.setVisible(true); line to the bottom of the method just to be safe. When you make the frame visible, the component tree is set up to take into account all the components added to the JFrame. If you add more components after that, you will need to do either manually revalidate the tree or do something that triggers an automatic revalidation. I'm assuming you're not revalidating your tree anywhere, so you should move f.setVisible(true); to after all the components are added.

how to put my background image at the bottom

I want to put my background image at the very bottom in this frame, and the button on top. However the code I wrote below doesn't work. Can anyone see where the problems are?
Another thing is that even though I set the location for my button, it keep showing at the top center on the frame.
Please ignore the comment lines. (I was just guessing, and hoping them will work, but they don't apparently.)
public class Menu extends JFrame{
private JLayeredPane pane;
private JLayeredPane pane2;
public Menu(){
final JFrame f = new JFrame("Chinese Chess");
JButton play = new JButton("Play vs. AI");
f.setLayout(new FlowLayout());
f.setLocationRelativeTo(null);
f.setSize(800, 800);
f.setVisible(true);
f.setResizable(false);
//f.pack();
pane = new JLayeredPane();
pane2 = new JLayeredPane();
f.add(pane);
f.add(pane2);
//background image
JLabel background = new JLabel(new ImageIcon("res/img/background.png"));
background.setLocation(0, 0);
background.setSize(800, 800);
pane.add(background, JLayeredPane.FRAME_CONTENT_LAYER);
pane2.add(play, JLayeredPane.DEFAULT_LAYER);
//pane.moveToBack();
//button PlayAI
play.setLocation(500,500);
play.setPreferredSize(new Dimension(100,50));
//f.setLayout(new FlowLayout());
//frame menu
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//f.getContentPane().add(play);
play.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
new PlayAI();
}
});
}
public static void main(String[] args){
new Menu();
}
Problems/Solutions:
setLocation(...) and setBounds(...) types of calls are ignored by most layout managers. The only way to use them is to set the layout of the container to null via .setLayout(null);
But having said that, while null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
So in sum -- don't do this, don't use null layouts or setBounds, but rather nest JPanels, each using its own layout manager, and thereby create easy to maintain and decent GUI's.
If you want an image to be in the background, then draw it in a JPanel that you use as a container for your GUI components by drawing it in the JPanel's paintComponent(Graphics g) method as has been demonstrated in many many similar questions on this site -- I'll find you some of mine in a second.
If you add any JPanels on top of this image drawing JPanel, be sure that you can see through them by calling setOpaque(false) on these overlying JPanels. Otherwise you'll cover up the image.
Your code has two JFrames when only one is needed. Get rid of the one you don't use.
You call setVisible(true) too early on the JFrame, before components have been added to the GUI -- don't. Call it only after adding everything to the GUI so all display OK.
You're creating two JLayedPanes, and completely covering one by the other by adding them to the JFrame without understanding how the JFrame's BorderLayout handles added components.
I suggest that you not even use one JLayeredPane but instead draw in the JPanel as noted above, and use that as your container.
Your code looks to be opening a completely new GUI window when the play button is pressed, and if so, this can get annoying to the user fast. Consider swapping views instead with a CardLayout.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
// extend JPanel so you can draw to its background
#SuppressWarnings("serial")
public class Menu2 extends JPanel {
private BufferedImage bgImage = null; // our background image
private JButton playButton = new JButton(new PlayVsAiAction("Play Vs. AI", KeyEvent.VK_P));
public Menu2(BufferedImage bgImage) {
this.bgImage = bgImage;
setLayout(new GridBagLayout()); // center our button
add(playButton);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bgImage != null) {
g.drawImage(bgImage, 0, 0, this);
}
}
// to size our GUI to match a constant or the image.
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
// if you want to size it based on the image
if (bgImage != null) {
int width = bgImage.getWidth();
int height = bgImage.getHeight();
return new Dimension(width, height);
} else {
return super.getPreferredSize();
}
// if you want to size the GUI with constants:
// return new Dimension(PREF_W, PREF_H);
}
private class PlayVsAiAction extends AbstractAction {
public PlayVsAiAction(String name, int mnemonic) {
super(name); // have our button display this name
putValue(MNEMONIC_KEY, mnemonic); // alt-key to press button
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to start program
}
}
private static void createAndShowGui() {
BufferedImage img = null;
String imagePath = "res/img/background.png";
try {
// TODO: fix this -- use class resources to get image, not File
img = ImageIO.read(new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
Menu2 mainPanel = new Menu2(img);
JFrame frame = new JFrame("Chinese Chess");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
Apart from the solution above... you should create and launch your swing application this way:
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
// Instantiate your JFrame and show it
}

JPanel repaint doesn't work

I have a simple task.
There is a frame. There are two panel in that frame. In second panel there is a button. When user click that button first panel must change its content.
Here is a code:
package test;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
class MyJPanel1 extends JPanel {
MyJPanel1() {
this.add(new JButton("MyJPanel1"));
}
}
class MyJPanel2 extends JPanel {
MyJPanel2() {
this.add(new JButton("MyJPanel2"));
}
}
class MyFrame extends JFrame {
JPanel topPanel = null;
MyFrame() {
super("Test");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridLayout(0, 1, 20, 20));
topPanel = new MyJPanel1();
this.add(topPanel);
JPanel bottomPanel = new JPanel();
this.add(bottomPanel);
JButton button = new JButton("switch");
button.addMouseListener(new MouseClickListener());
bottomPanel.add(button);
this.pack();
this.setVisible(true);
}
class MouseClickListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
topPanel = new MyJPanel2();
System.out.println("switch");
topPanel.invalidate();
topPanel.validate();
topPanel.repaint();
MyFrame.this.invalidate();
MyFrame.this.validate();
MyFrame.this.repaint();
}
}
}
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MyFrame();
}
});
}
}
But that don't work. After I click on button I see text in console, but first panel remain the same. I read that I must use invalidate() validate() and repaint() methods and I did, but it isn't help.
Any help would be appreciated.
If you want to "switch" panels then you should be using a CardLayout. The CardLayout allows 2 (or more) components to share the same space in a container but only one is ever visible at a time.
Read the section from the Swing tutorial on How to Use CardLayout for more information and working examples.
In your mouseClicked() method you create a new topPanel, but you don't do anything with it. Perhaps you meant to remove the original topPanel from myFrame, create a new topPanel, and then add the new toipPanel to myFrame.
Note that this may not be the best strategy (creating a new topPanel).

JButton not changing size

I've researched the ways to change the size of a jbutton to be displayed on a JFrame.
I am trying both the button.setSize(200,200) and button.setPreferredSize(new Dimension(200,200)), but it does not change. Here's the code:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Index extends JFrame{
private String title = "This is the motherfucking title";
Dimension dim = new Dimension(500,500);
public Index(){
this.setResizable(false);
this.setTitle(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(dim);
this.getContentPane().setBackground(Color.BLACK);
JButton button = new JButton("Button");
button.setSize(200,200);
this.add(button);
}
public static void main(String args[]){
Index ih = new Index();
ih.setVisible(true);
}
}
Here's the result: http://i.imgur.com/Llj0pfo.png
What am I doing wrong?
try this:
JButton button = new JButton("Button");
button.setSize(200,200);
getContentPane().setLayout(null);
getContentPane().add(button);
setVisible(true);
inside your constructor.
this.add(button);
You are adding the button to the content pane of the frame. By default the content uses a BorderLayout and the component is added to the CENTER. Any component added to the CENTER will automatically get the extra space available in the frame. Since you set the size of the frame to (500, 500) there is lots of space available.
As a general rule you should NOT attempt to set the preferred size of a component, since only the component know how big it should be in order to paint itself properly. So your basic code should be:
JButton button = new JButton("...");
frame.add(button);
frame.pack();
frame.setVisible(true);
Now the button will be at its preferred size. However, the button will change size if you resize the frame. If you don't want this behaviour, then you need to use a different Layout Manager.
Use SwingUtilities.invokeLater(); create your Index() inside it, then call setVisible(true); at the end of constructor. At the same time remeber that by default JFrame uses BorderLayout.
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Index();
}
});

Categories