JFrame setComponentZOrder() changes size of the objects - java

I'm trying to write an undecorated JFrame. I'm trying to put my button over my background label. However setting the button's Z order causes the button streches to size of jframe and neither setBounds() nor setSize() changes the situation. Here is my code:
import javax.swing.*;
public class MyApp {
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.setBounds(0, 112, 100, 50);
mainFrame.setLayout(null);
mainFrame.setUndecorated(true);
JLabel lblBackground = new JLabel(new ImageIcon(JFrame.class.getResource("/res/green.png")));
lblBackground.setBounds(0, 0, 100, 50);
JButton btnStart = new JButton("");
btnStart.setBounds(5, 15, 10, 15);
mainFrame.add(lblBackground);
mainFrame.add(btnStart);
mainFrame.setComponentZOrder(btnStart, 0);
mainFrame.setComponentZOrder(btnStart, 1);
mainFrame.setVisible(true);
}
}
Thanks for replies.

Use a JLayeredPane for this.
You will need to create a new JLayeredPane:
JLayeredPane layered = new JLayeredPane();
Set your JFrame to use this as a content pane:
mainFrame.setContentPane(layered);
And add your components, in this format:
layered.add(Component c, int layerNumber);
Hope that works for you!
More on JLayeredPanes

Don't play with null layouts. Swing was designed to be used with layout managers
Add the button to the label. For example:
JLabel label = new JLabel(...);
label.setLayout( new FlowLayout() );
JButton button = new JButton(...);
label.add( button );
frame.add(label);
frame.pack();
frame.setVisible(true);
Now the frame should be the same size as your image. The button should be centered on the top of the image. If you want the button positioned somewhere else then use a different layout manager.

Related

How do you make it so that a button doesn't interfere with the location of drawn shape?

So basically when I add a button it essentially pushes the black rectangle drawn in this program down, putting it out of its given location. How would you fix this?
import javax.swing.*;
import java.awt.*;
public class Grid {
public class homeGraphics extends JComponent {
homeGraphics() {
setPreferredSize(new Dimension(450, 600));
}
public void paint(Graphics g) {
super.paint(g);
g.fillRect(200, 275, 50, 50);
}
}
public void homeFrame() {
JFrame frame1 = new JFrame();
frame1.setSize(450, 600);
frame1.setResizable(false);
frame1.setDefaultCloseOperation(frame1.EXIT_ON_CLOSE);
JButton playButton = new JButton("Play");
playButton.setPreferredSize(new Dimension(60, 30));
JPanel panel1 = new JPanel();
panel1.add(playButton);
panel1.add(new homeGraphics());
frame1.add(panel1);
frame1.setVisible(true);
}
public static void main(String args[]) {
Grid frame = new Grid();
frame.homeFrame();
}
}```
it essentially pushes the black rectangle drawn in this program down, putting it out of its given location.
What do you mean out of its location? Painting is always done relative to the component. So your painting will always be done at (200, 275) of the component.
If you are attempting to paint at (200, 275) relative to the "frame", then don't. That is NOT how painting works.
Other problems with your code:
Don't attempt to set the size of your frame. If the custom panel is (450, 600) how can the frame possibly be the same size? The frame also contains the "title bar" and "borders". Instead of using setSize(), you invoke frame.pack()just beforeframe1.setVisible(….)`.
Class names start with an upper case character. Learn by example. Have you ever seen a class name in the JDK that doesn't start with an upper case character?
Custom painting is done by overriding paintComponent(…), not paint().
By default a JPanel uses a FlowLayout. So what you see it the button on one line and then the "HomeGraphics" class is too big to fit on the same line so it wraps the to the second line.
You should be more explicit when you do frame layout. So your code should be something like:
JPanel wrapper = new JPanel();
wrapper.add( playButton );
//JPanel panel1 = new JPanel();
//panel1.add(playButton);
//panel1.add(new homeGraphics());
JPanel panel1 = new JPanel( new BorderLayout() );
panel1.add(wrapper, BorderLayout.PAGE_START);
panel1.add(new HomeGraphics(), BorderLayout.CENTER);
Now the code shows your layout attempt more clearly.

How to fix a JButton to not take up the whole JFrame

I am a beginner in coding and I am learning Java. I'm busy making a log in system, and I have made a JFrame, but when I add a JButton, it takes up the whole JFrame.
public class LogInSystem extends Application{
#Override
public void start(Stage primaryStage)
{
// Setting the JFrame
JFrame frame = new JFrame("Log in System");
frame.setSize(2000, 2000);
frame.setVisible(true);
// Setting the button
JPanel panel = new JPanel();
Button btn1 = new Button();
btn1.setText("1");
btn1.setBounds(50, 150, 100, 30);
frame.add(btn1);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
It seems like you declare a panel and not adding button into it as well as not adding the panel to the frame. You can try to add your button into panel and panel into frame,
panel.add(btn1);
frame.add(panel);
You can also use some useful layout for a particular panel. For example, BoxLayout, GridLayout and etc. By default, everything is set to be FlowLayout.

Trying to put button and using center mode

Im trying to make a option menu to be able to choose flags to be displayed, Im trying to put the tailand button on the left down corner and it seems it does not want to budge.
import java.awt.*;
import javax.swing.*;
public class Flags {
public static void startup() {
Dimension d = new Dimension(400,300);
JFrame menu = new JFrame("Flag Menu");
menu.setResizable(true);
JButton tailand = new JButton("Tailand");
JPanel tailandPanel = new JPanel();
tailand.setLayout(null);
tailandPanel.setLayout(null);
tailand.setBounds(300,100,100,600);
tailandPanel.add(tailand);
menu.add(tailandPanel);
tailandPanel.setBackground(Color.LIGHT_GRAY);
tailand.setBackground(Color.WHITE);
tailandPanel.setPreferredSize(d);
tailand.setPreferredSize(d);
tailandPanel.setLocation(1, 1);
tailand.setLocation(1, 1);
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu.setLocationRelativeTo(null);
menu.setSize(600, 400);
menu.setResizable(false);
menu.setVisible(true);
menu.setLocationRelativeTo(null);
}
}
I have tried tailand.setPreferredSize(d); and tailandpanel.setPreferredSize(d); but no luck.
Also Is their a way to use center mode? (Eg. Give 300,200 and the center of the button would be their?)
Don't use null layouts
Don't use setPreferredSize(...)
Swing was designed to be used with layout managers
For example:
JButton button = new JButton( "Tailand" );
JPanel left = new JPanel( new BorderLayout() );
left.setBackground( Color.WHITE );
left.add(button, BorderLayout.PAGE_END);
JFrame frame = new JFrame("Flag Menu");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frane.setLocationRelativeTo(null);
frame.add(left, BorderLayout.LINE_START);
frame.setSize(600, 400);
frame.setVisible(true);
Read the section from the Swing tutorial on Layout Manager for more information and example of using each layout manager.

Gridlayout makes its own margin

I had been making game with grid gui and I made MyPanel, which extends JPanel to display bg image, and own Buttons. The problem is, when I make gridlayout, which is larger than 12x12 then it makes its own margin:
Image on left is <=13 case and buttons fit perfectly, when in image on right, case >13 there is small margin, which I can't get rid of . Code:
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
MyPanel panel = new MyPanel();
panel.setBounds(10, 10, 360, 360);
frame.getContentPane().add(panel);
panel.setLayout(new GridLayout(size,size));
buttons = new Button[size][];
for(int i=0;i<size;i++)
{
buttons[i] = new Button[size];
for(int j=0;j<size;j++)
{
buttons[i][j] = new Button();
panel.add(buttons[i][j]);
}
}
}
Don't use a null layout!
The point of using a layout manager is that the layout manager will determine the size of the panel.
Then you just use pack() on the frame and all the components will be displayed at their preferred size.
Also, don't use Button, that is an AWT component. Swing components start with "J" so you should be using JButton.

Why are the contents of my JFrame not displaying correctly?

For the sake of less code, I am taking out code that is unrelevant to the problem, such as addActionListener(); etc.
My main class is public class TF2_Account_Chief
I have my main Jframe f; and its contents:
private static JFrame f = new JFrame("TF2 Account C.H.I.E.F.");
private JLabel runnableTogetherLabel = new JLabel("How many idlers would you like to run at a time?");
private static JTextField runnableTogetherInput = new JTextField();
private JButton runButton = new JButton("Run!");
private JButton stopButton = new JButton("Stop!");
private JButton resetButton = new JButton("Reset!");
private JButton exitButton = new JButton("Exit!");
and I set the properties of all the contents:
public void launchFrame() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
f.add(runnableTogetherInput);
f.add(runnableTogetherLabel);
f.add(runButton);
f.add(stopButton);
f.add(resetButton);
f.add(exitButton);
f.setSize(625, 500);
runnableTogetherInput.setSize(35, 20);
runnableTogetherLabel.setSize(275, 25);
runButton.setSize(60, 25);
stopButton.setSize(65, 25);
resetButton.setSize(70, 25);
exitButton.setSize(60, 25);
f.setLocation(0, 0);
runnableTogetherInput.setLocation(285, 3);
runnableTogetherLabel.setLocation(5, 0);
runButton.setLocation(330, 0);
stopButton.setLocation(395, 0);
resetButton.setLocation(465, 0);
exitButton.setLocation(540, 0);
}
then I have my main() method:
public static void main(String[] args) throws IOException {
TF2_Account_Chief gui = new TF2_Account_Chief();
gui.launchFrame();
Container contentPane = f.getContentPane();
contentPane.add(new TF2_Account_Chief());
}
And then I have my second JFrame iF which is not displaying the contents correctly:
private void invalidInput() {
JFrame iF = new JFrame("Invalid Input!");
JLabel iL = new JLabel("The input you have entered is invalid!");
JButton iB = new JButton("Exit!");
Container contentPane2 = iF.getContentPane();
contentPane2.add(new TF2_Account_Chief());
iF.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
iF.pack();
iF.setVisible(true);
iF.add(iL);
iF.add(iB);
iF.setSize(500, 300);
iL.setSize(125, 25);
iB.setSize(60, 25);
iF.setLocation(0, 0);
iL.setLocation(0, 15);
iB.setLocation(0, 45);
}
Now, JFrame iF is launched when the invalidInput() method is called, but you can't see that because that part of the code is unrelevant to the problem. What does matter is that the JFrame iF is launched.
The new frame looks like this:
Any ideas on why the contents are not displaying properly?
(By improperly, I mean the JButton iB takes up the whole frame and the frame is a light blue instead of the normal grey.)
You are using absolute positions without using a null layout, that's why you see a large button.
To see every component, you have to use
iF.setLayout(null);
but it's not a good practice, I'd suggest you to learn how to use Layouts and leave all the work to the layout manager
The default layout of JFrame is BorderLayout, in which there are "5" locations you can put your components to
CENTER
PAGE_START
PAGE_END
LINE_START
LINE_END
So, iF.add(component) will add the component to the CENTER, you can specify the location like this:
iF.add(component, BorderLayout.PAGE_END);
//You can also put PAGE_START, LINE_START, LINE_END, CENTER
Take my advice and read more about BorderLayout, because if you refuse to learn Layout Managers, you probably go to Absolute Positioning( null layout) which is not a good way and must not be used.

Categories