In my GUI class I have an array of textfields, which I initialized in this class constructor. The code is as follows
JTextField[] arrayOne= new JTextField [10];
for(int a = 0;a < 10;a++)
{
arrayOne[a] = new JTextField(String.valueOf(0));
arrayOne[a].setBounds(189 + a * 50, 156, 39, 23);
arrayOne[a].setVisible(true);
}
The problem is, that when I run my GUI, it does not show these text fields. Why not?
You should add the JTextField in the layout.
You should use add method of the container/or the class if you extend JFrame inside the for.
Read this.
Adding Components to a Container
When you add components to a panel or content pane, the arguments you
specify to the add method depend on the layout manager that the panel
or content pane is using. In fact, some layout managers do not even
require you to add the component explicitly; for example, GroupLayout.
For example, BorderLayout requires that you specify the area to which
the component should be added (using one of the constants defined in
BorderLayout) using code like this:
pane.add(aComponent, BorderLayout.PAGE_START); The how-to section for
each layout manager has details on what, if any, arguments you need to
specify to the add method. Some layout managers, such as GridBagLayout
and SpringLayout, require elaborate setup procedures. Many layout
managers, however, simply place components based on the order they
were added to their container.
Swing containers other than JPanel and content panes generally provide
API that you should use instead of the add method. For example,
instead of adding a component directly to a scroll pane (or, actually,
to its viewport), you either specify the component in the JScrollPane
constructor or use setViewportView. Because of specialized API like
this, you do not need to know which layout manager (if any) many Swing
containers use. (For the curious: scroll panes happen to use a layout
manager named ScrollPaneLayout.)
For information about how to add components to a specific container,
see the how-to page for the container. You can find the component
how-to pages using How to Use Various Components.
There is one more case for non visibility.
f.setVisible(true);
f.setSize(1000,1000);//Where f is the JFrame reference
Add the above statements after adding the JTextFields to the required Frame.
Related
I am trying to create a new JTextField in my Jframe. I want to play around with the positioning of the textfield. I tried using setBounds and setLocation to change the position of the text box but it doesn't change the location of the text box at all.
This is my code:
public class GUI_Tutorial extends JFrame {
public static void main(String[] args) {
GUI_Tutorial frame = new GUI_Tutorial();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setSize(1000, 800);
frame.setVisible(true);
frame.setTitle("Calculator");
frame.setLayout(new FlowLayout());
}
public GUI_Tutorial() {
//frame.setLayout(new FlowLayout());
JTextField num1;
num1 = new JTextField(10);
add(num1);
num1.setVisible(true);
num1.setLocation(5, 5);
}
}
May I know what am I doing wrong?
Your problem is one of layout managers. When you add a component to a container, the layout manager will dictate where the component will go. A JFrame's contentPane (the JFrame sub-container that holds its components) uses a BorderLayout by default, and items added to this container in a default manner will fill the central portion of the container, will fill it completely if nothing else is added to other BorderLayout locations.
Possible solutions for placing items:
The worst suggestion, use a null layout. You would do this by calling getContentPane().setLayout(null);. But when you do this, you the programmer are 100% responsible for the exact position and size of all components added. This leads to hard to maintain GUI's that might not even work on other platforms -- so don't do this.
Use a GUI builder to help build your program: this has definite advantages, one being that it shields you from having to directly understand the layout managers, but this also is a disadvantage, because once you run into edge cases (and you usually will and quickly) that knowledge is essential. My own view is to initially avoid using this so as to better understand the layout managers, and then once you're familiar with the managers, then sure use this as needed.
Better is to learn and experiment with the layout managers, and Borders, playing with placement of components. Remember that you can nest containers (usually JPanels) and each can be given its own layout manager, allowing for complex GUI's that are created easily and maintained easily.
Note that
(again) JFrames (actually their contentPanes), JDialogs, and other top-level windows use BorderLayout by default, that JPanels use FlowLayout by default, that JScrollPanes use their own specialty layout, one that you will likely never want to muck with, and that most other components/containers, such as JComponent, JLabel,... have null layouts by default.
Best resource is the tutorial: Lesson: Laying Out Components Within a Container
Borders can also be useful here, especially the EmptyBorder which can allow you to put a blank buffer zone around your components.
Start playing with the simpler layout managers, FlowLayout, BorderLayout, GridLayout, then BoxLayout, before moving to the more complex
Try removing frame.setLayout(new FlowLayout());. You'll then need to use num1.setBounds(x, y, width, height) rather than setLocation()
But, as other users have pointed out, you should be using a layout manager. Read up on the different layouts and choose the best one for your GUI.
Before I start, I'm aware that its a bad idea to not use a Layout Manager and usually I do use one, however, I also have all my components automatically re-size and relocate based on the size of the window. In addition the program I'm working on is only intended to run on 1 machine throughout its entire lifetime. Please don't downvote me just because of lack of layout manager, I found it to be what I need for this particular program.
To my issue, I found a similar post on stackoverflow but a solution was never achieved.
I'm adding a dynamic amount of JLabels to my JPanel, I've noticed that when not using a layout manager, the scroller doesn't work.
This is a simplified version of my initialization code.
JPanel mypanel = new JPanel();
mypanel.setLayout(null);
mypanel.setSize(800,450);
mypanel.setForeground(Color.WHITE);
mypanel.setBackground(Color.BLACK);
scrollablePanel = new JScrollPane(mypanel);
scrollablePanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollablePanel.setPreferredSize(new Dimension(800,300));
scrollablePanel.setSize(800,300);
scrollablePanel.setLocation(250,156);
myContainer.add(scrollablePanel);
where myContainer would be the container (also without a layout manager). The JLabels are added later on to the JPanel with:
enter code heremypanel.add(label1);
after some basic settings are set for the labels such as setForeground and setBackground.
Unfortunately when run, the scrollbar appears as if its not required (see image)
http://i.imgur.com/zp0QKGG.png
The table text seen in the image is made up of multiple JLabels.
If it's not possible to resolve the issue without using a Layout Manager I will switch to BoxLayout, I was just hoping there would be a solution.
The problem is JScrollPanel needs the preferred size of the view component to determine when the view exceeds the scroll pane's viewable area.
The preferred size of a component is normally determined via the layout manager. While you can use setPreferredSize, it is typically discouraged and you will simply run into the same problem as the content exceeds what ever value you decide to set.
A better solution would be to use a LayoutManager or compound layout (using multiple layout managers over multiple containers) to achieve the result you desired...or write your own...
Before I start, I'm aware that its a bad idea to not use a Layout Manager and usually I do use one, however, I also have all my components automatically re-size and relocate based on the size of the window. In addition the program I'm working on is only intended to run on 1 machine throughout its entire lifetime. Please don't downvote me just because of lack of layout manager, I found it to be what I need for this particular program.
To my issue, I found a similar post on stackoverflow but a solution was never achieved.
I'm adding a dynamic amount of JLabels to my JPanel, I've noticed that when not using a layout manager, the scroller doesn't work.
This is a simplified version of my initialization code.
JPanel mypanel = new JPanel();
mypanel.setLayout(null);
mypanel.setSize(800,450);
mypanel.setForeground(Color.WHITE);
mypanel.setBackground(Color.BLACK);
scrollablePanel = new JScrollPane(mypanel);
scrollablePanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollablePanel.setPreferredSize(new Dimension(800,300));
scrollablePanel.setSize(800,300);
scrollablePanel.setLocation(250,156);
myContainer.add(scrollablePanel);
where myContainer would be the container (also without a layout manager). The JLabels are added later on to the JPanel with:
enter code heremypanel.add(label1);
after some basic settings are set for the labels such as setForeground and setBackground.
Unfortunately when run, the scrollbar appears as if its not required (see image)
http://i.imgur.com/zp0QKGG.png
The table text seen in the image is made up of multiple JLabels.
If it's not possible to resolve the issue without using a Layout Manager I will switch to BoxLayout, I was just hoping there would be a solution.
The problem is JScrollPanel needs the preferred size of the view component to determine when the view exceeds the scroll pane's viewable area.
The preferred size of a component is normally determined via the layout manager. While you can use setPreferredSize, it is typically discouraged and you will simply run into the same problem as the content exceeds what ever value you decide to set.
A better solution would be to use a LayoutManager or compound layout (using multiple layout managers over multiple containers) to achieve the result you desired...or write your own...
Can anybody explain why circular reference is being set twice in the followig code?
//declare panel
this.cntnrPnl = new JPanel();
//define layout manager for the panel - but why circ ref?
this.cntnrPnl.setLayout(new BoxLayout(this.cntnrPnl, BoxLayout.Y_AXIS));
Why is it necessary to link the BoxLayout back to the JPanel container explicitly instead of JPanel.setLayout doing the setting itself behind the scene and using a setter from BoxLayout for code compactness?
E.g.:
this.cntnrPnl.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
//and then in JPanel.setLayout have something line
_layout.setContainer(this);
Because BoxLayout is a special layout that needs a reference to the target container it lays out. That's not the case of all the layout managers. It would be ugly to add a specific case for BoxLayout in the setLayout() method. And it would also mean that the BoxLayout would be in an unstable state after its construction, since it wouldn't have the mandatory target container yet.
The reverse could have been done though: having the BoxLayout constructor call setLayout(this) on the target container. But I don't know why it hasn't been done.
Why is it necessary to link the BoxLayout back to the JPanel container explicitly instead of JPanel.setLayout doing the setting itself behind the scene and using a setter from BoxLayout for code compactness?
What you call JPanel.setLayout is actually Container.setLayout:
public void setLayout(LayoutManager mgr)
You call call the method with a BoxLayout because it implements LayoutManager. But LayoutManager does not have a setContainer method, so it would not have worked without adding that method. But it seems that most layout managers don't care about a container so the method would not belong there.
Would it be possible for BoxLayout constructor to do the magic? Maybe not, though a BoxLayout is tied to a Container, the reverse is not necessarily true. Consider:
this.cntnrPnl = new JPanel();
BoxLayout bY = new BoxLayout(this.cntnrPnl, BoxLayout.Y_AXIS);
BoxLayout bX = new BoxLayout(this.cntnrPnl, BoxLayout.X_AXIS);
Now at different times you can call this.cntnrPnl.setLayout(bX) and this.cntnrPnl.setLayout(bY).
So looking at all options, it seems the current API is best, though of course all this is somewhat subjective.
By the way, please consider renaming cntnrPnl to containerPanel. You are not really saving much by stripping the vowels.
Because a JPanel is not the only available container in Swing. In particular, you might create your own container class and not know about those special requirements for BoxLayout. As a result, the layout manater would not work for your implementation.
Now one could ask why the BoxLayout needs a reference to the JPanel to begin with, but this is a different matter.
I need to pick a standard container (JPanel?) in Swing that I can use as a placeholder to which I can add another custom component that extends JPanel:
JPanel containerPanel;
// built by a library from a text file, automatically part of a nice layout
MyPanel componentPanel;
// something complicated that I can't integrate with the builder library
containerPanel = builder.getMyContainerPanel();
componentPanel = new MyPanel(...);
containerPanel.add(componentPanel);
Is there a way to somehow couple the two panel sizes so that resizing works properly? I'm not quite sure how resizing works in swing, but what I want is for the outer containerPanel to be a thin wrapper that is subservient to my componentPanel and the outer panel delegates as much as possible to the inner panel.
I don't want to do things this way but it seems like the best way to decouple the builder library from my custom component.
I'd simply use a GridLayout.
containerPanel.setLayout(new GridLayout(1, 1));
This has the advantage that you can just add the sub panel without any parameters and it is guaranteed to use the entire area:
containerPanel.add(componentPanel);
You can use a BorderLayout and add your delegate container in the BorderLayout.CENTER position.
Hmm. Well, I decided to rewrite my component, so instead of a class that extends JPanel (inheritance), it uses composition and is constructed with an empty JPanel as a parameter + it adds child components to the JPanel. So I can use the builder library to build the empty JPanel, then later I pass that into my own component's constructor, so now I have 1 JPanel instead of two of them that I have to keep coupled together.