I have a problem with a JPanel inside another one. I don't know why, but the result is a simple square, but the dimensions aren't correct. Why is that?
import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class jj extends JFrame {
private JPanel painel3;
private JPanel painel5;
private Container container;
public jj() {
container = getContentPane();
container.setLayout(null);
painel5 = new JPanel();
painel5.setBackground(Color.red);
painel5.setBounds(120, 110, 100, 120);
painel3 = new JPanel();
painel3.setBackground(Color.white);
painel3.add(painel5);
painel3.setBounds(50, 50, 290, 220);
container.add(painel3);
// frame
setSize(1000, 900);
setLocation(200, 50);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new jj();
}
}
You need to set the layout for panel3 also to null otherwise the default FlowLayout is used:
panel3.setLayout(null);
A couple of additional recommendation. Learn to use LayoutManagers. They might have a slight learning curve but it will definitely be worth it. Nice tutorial: http://download.oracle.com/javase/tutorial/uiswing/layout/using.html
Also according to the Java Standards, class names should start with a capital letter. Doing this will help others read your code better.
Even better though is to avoid use of null layouts and setBounds/setSize but rather let layout managers help you in laying out your GUI. You can read up on them here: Laying out components in a container
Set the layout of painel3 to null before adding the painel5 panel.
painel3.setLayout(null);
painel3.add(painel5);
I recommend to use LayoutManagers.
Related
How do I use multiple JPanel containers to make this code look like this?
This is the image of what my code is supposed to be like but I cant figure it out.
I can only use GridLayout, BorderLayout and FlowLayout. As a beginner, We've only been over basic concepts but I need more help.
I am also not permitted to use GridBagLayout. I appreciate all the help.
A common strategy to solve complex computing tasks, is to break them into small, well defined manageable tasks. Divide and conquer.
This also applies to gui: break the design into small, easy to layout containers.
In this case, consider dividing the design into 3 areas (JPanels) nested in a main JPanel:
If you can't use GridBagLayout you can implement bottom panel using BoxLayout.
BoxLayout is a valid option also for main panel, to allow for different child panels (top, center, bottom) height.
Demo:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Lab1 extends JFrame
{
public Lab1() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel main = new JPanel(new GridLayout(3,1));
//to allow different child-panels height use BoxLayout
//BoxLayout boxLayout = new BoxLayout(main, BoxLayout.Y_AXIS);
add(main);
JPanel top = new JPanel(new GridLayout(1,3));
main.add(top);
top.add(getPanel(Color.RED));
top.add(getPanel(Color.GREEN));
top.add(getPanel(Color.BLUE));
JPanel center = new JPanel(new GridLayout(1,4));
main.add(center);
center.add(getPanel(Color.YELLOW));
center.add(getPanel(Color.CYAN));
center.add(getPanel(Color.BLACK));
center.add(getPanel(Color.LIGHT_GRAY));
JPanel bottom = new JPanel();
bottom.setLayout(new BoxLayout(bottom, BoxLayout.LINE_AXIS));
main.add(bottom);
bottom.add(getPanel(Color.PINK));
JPanel rightPane = getPanel(Color.MAGENTA);
rightPane.setPreferredSize(new Dimension(900, 200));
bottom.add(rightPane);
pack();
setVisible(true);
}
private JPanel getPanel(Color color) {
JPanel panel = new JPanel();
panel.setBackground(color);
panel.setPreferredSize(new Dimension(300, 200));
return panel;
}
public static void main(String args[])
{
new Lab1();
}
}
I'm trying to get away from using NetBeans to create simple Swing GUIs and hence trying to get a better understanding of the whole container/layout mechanism. I'v been reading various things inline, especially https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html.
In the example code below, I can see advantages to the second form, DialogJPanel(). For just one example, the JPanel can be given a border. My understanding is that the JPanel is actually getting added to the JDialog's content pane.
In the only "formal education" I had involving Java (3 years ago), we were taught to use the 3rd form, DialogBoth().
Is there an advantage to doing so? Perhaps in some cases where the content pane needs to be manipulated in some way? If so, what are those cases?
Or is the "both" form just to make clear to a reader of the code that the JPanel is really going onto the content pane of the JDialog?
And then there's the possibility of using setContentPane(jPanelOuter). Does that have some special purpose, in a practical sense?
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class DialogTest {
public static void main(String[] args) {
DialogContentPane dlgC = new DialogContentPane();
display(dlgC, "ContentPane");
DialogJPanel dlgP = new DialogJPanel();
display(dlgP, "JPanel");
DialogBoth dlgB = new DialogBoth();
display(dlgB, "Both");
}
public static class DialogContentPane extends JDialog {
public DialogContentPane() {
Container contentPane = this.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
JRadioButton jRadioButton1 = new JRadioButton("My Radio Button, which does nothing");
jRadioButton1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentPane.add(jRadioButton1);
JCheckBox jCheckBox1 = new JCheckBox("My Check Box, which does nothing either");
jCheckBox1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentPane.add(jCheckBox1);
}
}
public static class DialogJPanel extends JDialog {
public DialogJPanel() {
JPanel jPanelOuter = new JPanel();
jPanelOuter.setLayout(new BoxLayout(jPanelOuter, BoxLayout.Y_AXIS));
JRadioButton jRadioButton1 = new JRadioButton("My Radio Button, which does nothing");
jRadioButton1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jRadioButton1);
JCheckBox jCheckBox1 = new JCheckBox("My Check Box, which does nothing either");
jCheckBox1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jCheckBox1);
this.add(jPanelOuter);
}
}
public static class DialogBoth extends JDialog {
public DialogBoth() {
Container contentPane = this.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
JPanel jPanelOuter = new JPanel();
jPanelOuter.setLayout(new BoxLayout(jPanelOuter, BoxLayout.Y_AXIS));
JRadioButton jRadioButton1 = new JRadioButton("My Radio Button, which does nothing");
jRadioButton1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jRadioButton1);
JCheckBox jCheckBox1 = new JCheckBox("My Check Box, which does nothing either");
jCheckBox1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
jPanelOuter.add(jCheckBox1);
contentPane.add(jPanelOuter);
}
}
public static void display(JDialog dlg, String title) {
Toolkit tk;
Dimension screenDims;
dlg.setTitle(title);
tk = Toolkit.getDefaultToolkit();
screenDims = tk.getScreenSize();
dlg.setLocation((screenDims.width - dlg.getWidth()) / 2, (screenDims.height - dlg.getHeight()) / 2);
dlg.pack();
dlg.setModalityType(JDialog.DEFAULT_MODALITY_TYPE);
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setVisible(true);
}
}
There's no "immediate" advantage or disadvantaged other then the amount of code you need to type. Since Java 1.5 (I think) calls to things like add and setLayout on top level containers are automatically routed to the contentPane, this is why you may still see code which either uses getContentPane or setContentPane
To better understand what's happening, you need a better understanding of how a JFrame works...
A JFrame is composite component, made up of a series of layers. When Swing was first released, it was a requirement to use the contentPane directly in order to add components to it. This is eventually fixed (?) to allow you to add/remove components to the contentPane via the frame directly.
Just beware, removeAll, isn't routed to the contentPane and will remove the JRootPane, which is messy.
Some people prefer the "old" way, as it's obvious what's been done, some (like me, are lazy) and just prefer to get stuff done
I think, that you can center a Component (for Example a JButton) in a JPanel, using the BorderLayout:
panel.setLayout(new BorderLayout());
panel.add(button, BorderLayout.CENTER);
But than the JButton takes up all the space in the JPanel.
Is it for example possible to use another LayoutManager, or is there an even easyer way to do center the JButton?
I think, button.setAlignmentX(JButton.CENTER_ALIGNMENT) doesn't work.
I guess with most tasks it's just a matter of personal choice/your boss's order if you're using a Layout manager rather than the others. There are some Layout managers that can accomplish quite every requirement, such as GridBadLayout, but i personally think that in most situation they're not the best choice since they might end up overcomplicating things. For this specific task i would go with a BoxLayout https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
And would code something like:
import java.awt.*;
import javax.swing.*;
public class CenteredButton extends JFrame {
public CenteredButton() {
Container pane = getContentPane();
pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
JPanel panel = new JPanel();
JButton button = new JButton("Button1");
button.setPreferredSize(new Dimension(100, 50));
panel.add(button);
pane.add(panel);
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new CenteredButton();
}
}
As you may notice, resizing the button's dimension will not change the fact that it sticks in the middle of the frame.
PS: developers opinions are mostly enthusiastic about http://www.miglayout.com/ and https://tips4java.wordpress.com/2008/11/02/relative-layout/. Both of these, in my opinion, are easier to manage than GridBagLayout
So I am a computer science student and I've finished my first year. I wanted to create a simple program and I realized that I am so tired of using no layout;
this.setLayout(null);
It is so tiresome to add bounds to every single component. Well, I have been using JPanel components and GridLayout a lot, which have made my work a bit easier. But I am tired of it.
I care very much about the look of the GUI I make and use almost half the time programming to make the GUI look good before I start adding the functionality of the code. By not using a layout and adding bounds I am forced to setResizable(false) because it looks bad if I change the size of the JFrame.
I've been searching a bit, and I know of BorderLayout, and FlowLayout, but I don't like them. Is there any Layout that keeps the relative size of the components with respect to the size of the window?
For example I want to make a simple program that looks like this: (Quick sketch in Photoshop)
I can easily make this with 3 panels, but as I said, if I change the size of the frame everything stays in place instead of being relative to the window-size.
Can you guys help me?
This design looks for me to fit the BorderLayout, where in the NORTH you have the values that changes the CENTER you have the main part, and the SOUTH you have the buttons.
Link to the Oracle Border Layout
You can apply this BorderLayout to the JFrame, then create 3 JPanels for each of the NORTH,CENTER and SOUTH sections. If you want to use responsive design for the components and panels, take a look at GridBagLayout which is much more flexible than the GridLayout
Layout management is a very complex problem, I don't think people really appreciate just how complex it really is.
No one layout is ever going to achieve everything your want, in most cases, you will need to resort to two or more layouts, especially as your requirements become more complex.
For example, the following is simply a BorderLayout at the base and the buttons on a JPanel using a FlowLayout
Which is achieved by using
JList listOfThings = new JList(...);
JTextField tf = new JTextField();
JButton add = new JButton("Add");
JButton delete = new JButton("Delete");
JButton go = new JButton("Go...");
JPanel buttons = new JPanel();
buttons.add(add);
buttons.add(delete);
buttons.add(go);
add(new BorderLayout());
add(tf, BorderLayout.NORTH);
add(new JScrollPane(listOfThings));
add(buttons, BorderLayout.SOUTH);
For more complex layouts, I would consider using something like GridBagLayout. You may also want to consider MigLayout as an alternative
Take a look at Laying Out Components Within a Container for more details about using layout managers
I'd like to use the combination of BorderLayout and BoxLayout. BorderLayout let me put the component based on their relative location's relation and BoxLayout let me manage the subtle distance ( create some white space). You can use component.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); to achieve this goal too.
Here is a demo and hope it can help you.
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class LayoutTest{
private JTextField jTextField;
public void createUI(){
JFrame frame = new JFrame("Layout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(new TextFieldPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ListPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ButtonPanel());
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
LayoutTest layoutTest = new LayoutTest();
layoutTest.createUI();
}
#SuppressWarnings("serial")
class TextFieldPanel extends JPanel{
public TextFieldPanel(){
setLayout(new BorderLayout());
jTextField = new JTextField();
jTextField.setEditable(false);
add(jTextField,BorderLayout.CENTER);
}
}
#SuppressWarnings("serial")
class ListPanel extends JPanel implements ListSelectionListener{
private JList<String> list;
public ListPanel(){
setLayout(new BorderLayout());
String stringArr[] = new String[30];
for (int i = 0; i < 30; i++) {
stringArr[i] = "JList :This line is item" + i;
}
list = new JList<String>(stringArr);
JScrollPane scrollPane = new JScrollPane(list);
add(scrollPane,BorderLayout.CENTER);
setBackground(new Color(211,211,211));
list.addListSelectionListener(this);
}
#Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
jTextField.setText(list.getSelectedValue());
}
}
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BorderLayout());
add(button1,BorderLayout.WEST);
add(button2,BorderLayout.CENTER);
add(button3,BorderLayout.EAST);
}
}
}
Here is the effect:
You can use BoxLayout for ButtonPanel if you don't want to let the button's size change.
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(button1);
add(Box.createHorizontalStrut(8));
add(button2);
add(Box.createHorizontalStrut(8));
add(button3);
}
}
And the effect is like this:
For more infomation about using BoxLayout to generate whitespace, you can refer to https://stackoverflow.com/a/22525005/3378204
Try GridBagLayout.
Your sketch is actually quite close to the one of the examples in the official tutorial.
HVLayout keeps the relative size of the components with respect to the size of the window, that is, if you configure components to have a relative size (e.g. buttons usually do not grow or shrink - they stick to their preferred size). This SO question was one of the motivations for me to push HVLayout to a release and a screenshot is included (showing big window size, smalll size and preferred "default" size):
Source code for the window is in RelativeToWindowSize.java
A number of helper-classes from HVLayout are used to build the window, so I don't think it will be of much use here, but to get an impression, the "build window" part shown below:
public RelativeToWindowSize build() {
CSize cs = new CSize();
CForm form = new CForm(new VBox(new Insets(2, 4, 2, 4)), cs);
addTitledBorder(form.get(), "Vertical box", Color.BLACK);
form.add(new JScrollPane(
tfield = new JTextArea("Value that changes with value choosen from list.\nhttp://stackoverflow.com/questions/24462297/layout-relative-to-screensize/")
)).csize().setAreaSize(1.0f, 2.5f).fixedMinHeight().setMaxHeight(4.0f);
// tfield shows mono-spaced font by default.
tfield.setFont(SwingUtils.getUIFont());
form.add(new JScrollPane(vlist = new JList<String>(getListValues())))
.csize().setAreaSize(1.0f, 5.0f);
form.addChild(new HBox());
addTitledBorder(form.get(), "Horizontal box", Color.RED);
form.addChild(new HBox(SwingConstants.CENTER));
addTitledBorder(form.get(), "Centered box.", Color.BLUE);
form.add(createButton(cs, "Add"));
form.add(createButton(cs, "Modify"));
form.up();
form.addChild(new HBox(SwingConstants.TRAILING));
addTitledBorder(form.get(), "Trailing box", Color.GREEN);
form.add(createButton(cs, "Delete"));
setContentPane(form.getRoot());
pack();
setLocationByPlatform(true);
//applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
vlist.addListSelectionListener(this);
log.debug(getClass().getName() + " build.");
return this;
}
private Component createButton(CSize cs, String text) {
// For purpose of demo, let button shrink in width.
return cs.set(new TButton(text)).setFixed().shrinkWidth(0.33f).get();
}
I started java programming yesterday, and have developed this. I have run into a problem, as the button will not resize. Please help if you can and thank you in advance.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
class BgPanel extends JPanel {
Image bg = new ImageIcon("C:\\Users\\********\\Pictures\\tiger.jpg").getImage();
#Override
public void paintComponent(Graphics g) {
g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
}
public class FrameTestBase extends JFrame {
public static void main(String args[]) {
JPanel bgPanel = new BgPanel();
bgPanel.setLayout(new BorderLayout());
final FrameTestBase t = new FrameTestBase();
ImageIcon img = new ImageIcon("C:\\Users\\********\\Pictures\\gear-icon.png");
t.setLayout(null);
t.setIconImage(img.getImage());
t.setTitle("Login");
t.setSize(600,600);
t.setLocationRelativeTo(null);
t.setContentPane(bgPanel);
t.setDefaultCloseOperation(EXIT_ON_CLOSE);
t.setVisible(true);
JButton registerButton = new JButton("register");
registerButton.setBounds(80, 80, 80, 80);
t.add(registerButton);
}
}
I have run into a problem, as the button will not resize. Please help
if you can and thank you in advance.
bgPanel.setLayout(new BorderLayout());
// --------- your other code
t.setLayout(null);
//--------------- your other code
t.setContentPane(bgPanel); // you are setting bgPanel which has BorderLayout
JButton registerButton = new JButton("register");
registerButton.setBounds(80, 80, 80, 80);
t.add(registerButton); // t is the JFrame, your main window
Any JFrame.add(component) will essentially add your component to the content pane of the JFrame. After setting layout to null you have added the bgPanel as content pane to the JFrame, which has BorderLayout as its layout manager. Adding your button to the content pane i.e.,bgPanel will add your registerButton with BorderLayout.Center constraint. That is why this button is expanding to the size of the screen.
As you are so eager to see an output do the following:
// registerButton.setBounds(80, 80, 80, 80); comment out this line
registerButton.setPreferedSize(new Dimension(80, 80));
t.add(registerButton, BorderLayout.PAGE_START)
Now, About using NULL Layout:
In your own example you have lost to find the reason why the Button is expanding to the window size. In near future you will see that one of your component has head but lost its tail by going outside of the window border. You will see that one of your component is going to jump over the other without no reason. You will see that you have changed a position of component with relative to another component, but it will make relation with other component. Well you will be able to find the issues wasting lost of time and get fixed by setting xxxSize, setLocation, setBounds etc but....
people can be rich in money, they can't be rich in time.
Start learning LayoutManager: Lesson: Laying Out Components Within a Container
Don't use a null layout!!!
Swing was designed to be used with layout managers. And don't forget to follow Mike's suggestion.
Try to use registerButton.setSize(new Dimension(width, height)) instead of setBounds.
Remember to replace width and height for new values
And I forget to say the same thing guys are telling you:
Don't use null layout.
The sooner you learn, the better.
Layouts are not difficult, they're actually easy.