I have just finished a project and ran into a problem I could not find anywhere on the internet so far.
I have several JTextFields on a JPanel on a JFrame. When I open the frame, all text fields are in the right place. If I minimize the frame and open it again, all text fields are moved and smaller.
These are photos of my frame before and after I minimize it.
Before:
After:
panel = new JPanel();
panel.setBounds(0, 0, 400, 175);
panel.setVisible(true);
frame.add(panel);
field0 = new JTextField();
field0.setBounds(10, 55, 120, 20);
field0.setVisible(true);
Frame.panel.add(field0);
field1 = new JTextField();
field1.setBounds(250, 55, 125, 20);
field1.setVisible(true);
Frame.panel.add(field1);
field2 = new JTextField();
field2.setBounds(10, 105, 365, 20);
field2.setVisible(true);
Frame.panel.add(field2);
Swing was designed to be used with layout managers. The job of the layout manager is to set the "size" and "location" of each components based on the preferred size of each component and the rules of the layout manager.
In your code the setBounds(...) code is only temporary. When the frame is resized, the layout manager is invoked and the proper size/location is assigned to all components.
So the solution is to not attempt to set the bounds manually but to use layout managers effectively.
Read the section from the Swing tutorial on Layout Managers for more information and working examples to get you started.
Based on your example picture I would suggest you can use the GridBagLayout. It will allow you to create a GUI using row and columns. You can also have components span several columns. I see the you have 5 rows and 3 columns. Download the working demo code from the tutorial and modify it for your requirements.
all text fields are moved and smaller.
Each Swing component should determine its own preferred size.
When you use:
field0 = new JTextField();
the preferred size is what you see.
The better way to create the text field is to use:
field0 = new JTextField(10);
Now the "10" will allow the text field to determines its preferred size to hold 10 "W" characters.
Also, Swing components are visible by default, so you need need to use setVisible(true) for every component.
Related
I am trying to create a JPanel with 3 text fields. Everything else including buttons is falling into place except for textArea3. The final panel is something like this. As you can see in picture, textArea3 uses entire JFrame instead of following setBounds method.
//Text Area 1
JTextArea textArea = new JTextArea();
JScrollPane jScrollPane1 = new JScrollPane(textArea);
jScrollPane1.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
textArea.setFont(new Font("Consolas", Font.LAYOUT_LEFT_TO_RIGHT, 20));
JTextArea textArea2 = new JTextArea();
JScrollPane jScrollPane2 = new JScrollPane(textArea2);
jScrollPane2.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
textArea2.setWrapStyleWord(true);
textArea2.setLineWrap(true);
textArea2.setFont(new Font("Consolas", Font.LAYOUT_LEFT_TO_RIGHT, 20));
//Text Area 3
JTextField textArea3 = new JTextField();
textArea3.setFont(new Font("Consolas", Font.LAYOUT_LEFT_TO_RIGHT, 20));
jScrollPane1.setBounds(30,30,300,300);
jScrollPane2.setBounds(30,400,200,200);
//textArea3 is not working
textArea3.setBounds(600,800,100,50);
button2.setBounds(350,30,80,30);
button1.setBounds(350,400,80,30);
frame.add(button1);
frame.add(button2);
frame.add(jScrollPane2);
frame.add(jScrollPane1);
frame.add(textArea3);
frame.setVisible(true);
EDIT: So this was a bug within the JDK probably. I made another class called class frame and set methods to produce text area etc.
As you can see in picture, textArea3 uses entire JFrame instead of following setBounds method.
No I can't see. I see 5 components. I don't see any component that uses the entire frame.
If in fact you do see the text area take up the whole frame that is because:
the default layout manager for a JFrame is the BorderLayout
when you add components to a BorderLayout and don't specify a constraint, the CENTER is assumed.
however only a single component can be displayed in the CENTER so the layout manager will only give a size/location to the last component added, which happens to be textArea3.
The other components only happen to appear because you manually set the bounds of each component.
You should NOT be attempting to set the bounds of a component. It is the job of the layout manager to set the size and location of each component.
So the solution is to get rid of all the setBounds() statement and use layout managers.
Read the section from the Swing tutorial on Layout Managers for more information. It appears you are tying to use a grid so you can probably use a GridBagLayout.
Also when you create a JTextArea you should use something like:
JTextArea textArea = new JTextArea(15, 20);
This will allow the text area to calculate its size so that 15 rows will display with about 20 characters in each row. The size will be calculated based on the Font used.
I need a vertical scrollbar in my JTextArea to only appear when it's needed, and for that I know I need to use Vertical Scrollbar As Needed. But the scrollbar keeps showing up, like this:
enter image description here
even when it's clearly not needed. What am I doing wrong?
// make top panel where output from the menu selections will appear
topP = new JPanel(new BorderLayout());
topP.setSize(new Dimension(500,150));
// make default text message to be displayed in top panel
output = new JTextArea("Output printed here...", 20, 20);
// styles the text in the textarea
output.setForeground(Color.BLUE);
output.setFont(new Font("Times New Roman", Font.BOLD, 20));
topP.add(output, BorderLayout.NORTH); // add default text to the top panel
right.add(output);
// here's the scrollbar guys
top = new JScrollPane(output); // applies to the textarea
top.setPreferredSize(new Dimension(500,150));
top.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
top.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
topP.add(top, BorderLayout.NORTH);
Take a look at the documentation for JTextArea. If you scroll down to the constructor summary section, you'll see the following:
JTextArea​(String text, int rows, int columns)
Constructs a new TextArea with the specified text and number of rows and columns.
This is the same as the constructor you're using:
output = new JTextArea("Output printed here...", 20, 20);
By specifying rows and columns, you're effectively telling the JTextArea that it has to be a certain size, and the scrollpane is just responding to your specifications by showing scroll controls. Those scroll controls are displayed based on the number of rows and columns you asked for, as opposed to the amount of visible text within the text area.
If you construct a JTextArea without specifying rows and columns, there won't be any scrollbars. Since you're setting the size of the text area, specifying rows and columns is redundant anyhow. Just don't do it.
Note: You should avoid setting the absolute size of Swing components. Set a preferred size only, and when you call pack(), Swing will try to accommodate your specification as much as possible. When you specify absolute sizes, your UI can look really bad on different platforms or when a user resizes the frame.
I am extremely new to Java Swing, and I'm having quite a bit of issues getting a nice layout going. I have checked out google, and even other answers on this website, but no information I find seems to solve the issue. Here is the result of my efforts:
As you can see, the label, text field, and button are all out of alignment. It is my goal for all of them to have the same left-hand border, and for the button and text field to have the same right-hand border, with these left and right hand borders being each the same distance from the left and righthand sides of my window.
Here are the important parts of my code:
public void run()
{
JFrame frame = new JFrame("Arduino Server");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
InstancePanel = new ServerGUIPanel();
frame.getContentPane().add(InstancePanel);
frame.pack();
frame.setVisible(true);
}
And, in ServerGUIPanel.java:
public ServerGUIPanel()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setPreferredSize(new Dimension(500, 500));
setBorder(new EmptyBorder(10, 10, 10, 10));
StatusLabel = new JLabel("STATUS: BOOTUP");
add(StatusLabel);
PortField = new JTextField();
PortField.setPreferredSize(new Dimension(5000, 20));
PortField.setMaximumSize(PortField.getPreferredSize());
PortField.setActionCommand("PortChanged");
add(PortField);
ConnectionButton = new JButton();
ConnectionButton.setPreferredSize(new Dimension(5000, 20));
ConnectionButton.setMaximumSize(ConnectionButton.getPreferredSize());
ConnectionButton.setActionCommand("ConnectionClicked");
add(ConnectionButton);
}
Does anyone have a simple solution to this? What am I doing wrong here?
Thank you very much!
--Georges Oates Larsen
Read the section from the Swing tutorial on How to Use BoxLayout for the basics of using a BoxLayout as well as a section on alignment issues.
Basically you need to make sure the alignmentX value of all components is set to be left aligned.
Also:
Don't use setPreferredSize() to set the size of a component. Each Swing component will determine its own preferred size.
Use Java naming conventions. Variable names should NOT start with an upper case character.
I would not recommend using setPreferredSize() AND setMaximumSize(). The latter will cause problems when stretching your main frame. [Your components will likely not want resize]
You should be using layout managers to handle all the alignments itself. I would stay away from using BoxLayout in this case, as different components want to size differently, and that will sway the alignment when added into your BoxLayout panel.
Moreover, you might want to give your main frame a layout as well.
Can you post how you used your GridBagLayout?
Hi i am trying to make java desktop application where i am having 4 jbutton i want to set them bottom left corner one by one i am using null layout for setting them but i dont want to use null layout so
how can i achieve this ?
Thanks in advance
ok = new JButton(s);
ok.setBounds(800, 725, 100, 40);
ok.setBackground(Color.red);
ok.setOpaque(true);
ok.setForeground(Color.BLACK);
c.add(ok);
print = new JButton("Print");
print.setBounds(925, 725, 100, 40);
print.setBackground(Color.red);
print.setOpaque(true);
print.setForeground(Color.BLACK);
c.add(print);
next = new JButton("next");
next.setBounds(400, 725, 100, 40);
next.setBackground(Color.red);
next.setOpaque(true);
next.setForeground(Color.BLACK);
c.add(next);
home = new JButton("home");
home.setBounds(500, 725, 100, 40);
home.setForeground(Color.BLACK);
home.setBackground(Color.red);
home.setOpaque(true);
c.add(home);
Sort answer, use a layout manager.
Long answer, pixel perfect layouts are an illusion in modern user interface design. You can't possible predict the combination of hardware and software that is used to render content to the screen and what effect that will have on your components.
Each system could be using different fonts, rendering pipelines, DPI, hardware...and much more, all of which will change the size of the text and other elements on your UI.
Swing was designed to work around the use of layout managers, trying to do with out greatly increases your work load, as you now need to do the work that the layer manager was as well as be able to detect changes that occur around you and the parent components that you've been added to...
Looking at your code, I could suggest FlowLayout or GridBagLayout as a possible starting point
As #MadProgrammer said you really should use layout managers.
But if you insist on working like this use:
c.setLayout(null);
I am using Left-To-Right (LTR) as default Component Orientation for laying out the swing components in JPanels. Now I need to mirrorize all the components in the panel and display them from Right-To-Left(RTL). This will be used for Arabic Locale.
For example the order of components: "label-textbox-button" must turn the new order: "button-textbox-label" without changing their vertical positions.
setComponentOrientation and applyComponentOrientation methods are not working because the layout managers I used, does not support these methods. These methods are supported by FlowLayout, GridLayout etc. I'm using absolute coordinates like this :
JPanel panel = new JPanel();
panel.setBounds(0, 50, 800, 100);
JButton button1 = new JButton("Cancel");
button1.setBounds(100, 60, 100, 120);
panel.add(button1);
when mirrorize, bounds of button will be : (600, 60, 100, 120);
Here is a clear sample about what I want but that is JavaFX version of it. I also do not want to recreate components screens. I just want to repaint and redisplay them according to Locale. So looking for any Java API or open library, if there are any. Thanks for your suggestions and help about where to find it if possible.