This question is very similiar to this: JScrollPane doesn't top align when there is more than enough space to show the content I tried this solution, but it does not work.
When I add a jlabel to jscrollpane, when the jlabel is small, the label becomes centered. It works normally when the scrollbar shows. Setting boxlayout does not change anything. I feel like this isn't working properly because I'm setting a perferred size to the panel? But if I remove the line panel.setPreferredSize(new Dimension((int)(screenSize.width*0.7 - 50), screenSize.height-150)); The label becomes small when there is no text, and grows to accomdate text, which I don't want. If I add the panel instead of the label, it makes the screen scrollable even though there isn't text?
This is my code:
public class Test {
// JFrame
static JFrame frame = new JFrame("Test");
//panel 1
static JPanel panel = new JPanel(new BorderLayout());
// label to display text
static JLabel label = new JLabel();
//scroll panel in main method
public static void main(String[] args) throws Exception {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
label.setBorder(new EmptyBorder(5, 5, 5, 20));
label.setText("any text makes it centered beyond 40 lines");
//create panel
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(label, BorderLayout.NORTH);
panel.add(Box.createVerticalGlue());
panel.setPreferredSize(new Dimension((int)(screenSize.width*0.7 - 50), screenSize.height-150));
panel.setBorder(new EmptyBorder(5, 5, 5, 10));
JScrollPane jspanel = new JScrollPane(label, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
//jspanel.add(label, BorderLayout.CENTER);
jspanel.setPreferredSize(new Dimension((int)(screenSize.width*0.7 - 70), screenSize.height-180));
jspanel.getVerticalScrollBar().setUnitIncrement(20);
jspanel.setBorder(BorderFactory.createEmptyBorder());
jspanel.setAlignmentX(JScrollPane.LEFT_ALIGNMENT);
jspanel.setAlignmentY(JScrollPane.TOP_ALIGNMENT);
//panel.setPreferredSize(new Dimension(640, 480));
//frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(jspanel);
frame.setSize((int)(screenSize.width*0.7), screenSize.height - 50);
frame.revalidate();
frame.pack();
frame.setVisible(true);
}
}
jspanel.setAlignmentX(JScrollPane.LEFT_ALIGNMENT);
jspanel.setAlignmentY(JScrollPane.TOP_ALIGNMENT);
That will align the scrollpane in its parent container, depending on the layout manager being used. It does not affect the alignment of any component added to the scrollpane. It is not needed.
the label becomes centered
The label is sized to fill the entire space available, so you need to customize how the text of the label is painted.
If you don't want it centered then you can place it at the top using:
label.setVerticalAlignment( SwingConstants.TOP );
After reworking your code, I came up with the following GUI.
I added a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
I eliminated all static references, except for the main method.
I reworked your code into methods so I could focus on one part of the GUI at a time.
Here's the complete runnable example. This is a minimal reproducible example.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class JScrollPaneTestGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JScrollPaneTestGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("JScrollPane Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane jspanel = createJScrollPane();
frame.add(jspanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JScrollPane createJScrollPane() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(Color.YELLOW);
panel.setPreferredSize(new Dimension(400, 300));
JLabel label = new JLabel();
label.setBorder(new EmptyBorder(5, 5, 5, 20));
label.setText("any text makes it centered beyond 40 lines");
//create panel
panel.add(label, BorderLayout.NORTH);
JScrollPane jspanel = new JScrollPane(panel);
return jspanel;
}
}
Related
I need the following UI on JFrame. Two Jlabel Vertically Left aligned. Two button horizontally below the Jlabel. I tried below code but it is coming in one row.
Label should be left and vertically aligned.
Button should cover all the width of Jframe.
import javax.swing.*;
import java.awt.*;
public class CustomPanel {
private JFrame frame = new JFrame();
private JPanel basePanel= new JPanel();
public static void main(String []args){
CustomPanel cp= new CustomPanel();
cp.showUI();
}
private void addui(){
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new GridBagLayout());
JLabel label11 = new JLabel("I am here to test");
JLabel label12 = new JLabel("I am here to test row");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
labelPanel.add(label11, gbc);
gbc.gridy++;
gbc.gridwidth = 2;
labelPanel.add(label12, gbc);
basePanel.add(labelPanel);
/////////////// button panel//////////
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 2, 5, 5));
panel.add(new JButton("Click me"));
panel.add(new JButton("Click me22"));
basePanel.add(panel);
}
private void showUI(){
JFrame.setDefaultLookAndFeelDecorated(true);
addui();
frame.setAlwaysOnTop(true);
frame.setType(Window.Type.UTILITY);
frame.setResizable(true);
frame.getContentPane().setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(basePanel);
scrollPane.setPreferredSize(new Dimension(400, 250));
frame.getContentPane().add(scrollPane);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(500, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.
When creating a Swing GUI, you can break up a complex JPanel layout into more than one simpler JPanels. I created three JPanels for this GUI; the main JPanel, the label JPanel, and the button JPanel.
A Swing application must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created the JFrame and the three JPanels in separate methods. This allows me to focus on one part of the GUI at a time and makes the code much easier to read and follow. This also allows me to experiment with different Swing layout managers to see which one is appropriate for the GUI.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CustomPanel implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CustomPanel());
}
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.add(createLabelPanel(), BorderLayout.NORTH);
panel.add(createButtonPanel(), BorderLayout.SOUTH);
return panel;
}
private JPanel createLabelPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JLabel label11 = new JLabel("I am here to test");
panel.add(label11, BorderLayout.NORTH);
JLabel label12 = new JLabel("I am here to test row");
panel.add(label12, BorderLayout.SOUTH);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JButton button = new JButton("Click me");
panel.add(button);
button = new JButton("Click me22");
panel.add(button);
return panel;
}
}
I need to define a layout for a Jframe Window, as in the picture above.
Below is my approach.
A Picture from my resources folder (/resources/...jpg) embed inside the middle(main).
Top, Bottom, Left and Right divided in four parts, whereas their content is a labeled button stretched, so I can map some methods on it later, that change the picture inside the main container.
I tried to display the picture, but I get the result you see in my screenshot. I can't see it inside my main container and I receive no error message.
I don't know if this is because of my wrong approach of using JFrame.
Below you can see my code, I'd be happy if you could help me solving my wrong design layout pattern too.
MyFrame.java
package ms0.gui;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class MyFrame extends JFrame {
public MyFrame () {
setTitle("This is an example title");
setSize(600,600);
setLocation(750,640);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//Main Container
Container mainContainer = this.getContentPane();
mainContainer.setLayout(new BorderLayout(8,6));
mainContainer.setBackground(Color.BLUE);
this.getRootPane().setBorder(BorderFactory.createMatteBorder(4, 4, 4, 4, Color.green));
//JButton Positions
JButton topButton = new JButton("Oben");
JButton bottomButton = new JButton("Unten");
JButton leftButton = new JButton("Links");
JButton rightButton = new JButton("Rechts");
//Panel Top
JPanel topPanel = new JPanel();
topPanel.setBorder(new LineBorder(Color.BLACK, 3));
topPanel.setBackground(Color.ORANGE);
topPanel.setLayout(new FlowLayout(5));
topPanel.add(topButton);
mainContainer.add(topPanel, BorderLayout.NORTH);
//Panel Middle
JPanel middlePanel = new JPanel();
middlePanel.setBorder(new LineBorder(Color.black, 3));
middlePanel.setLayout(new FlowLayout(4,4,4));
middlePanel.setBackground(Color.cyan);
//Grid Panel Right
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new FlowLayout(4,4,4));
rightPanel.setBorder(new LineBorder(Color.black, 3));
rightPanel.setBackground(Color.GREEN);
rightPanel.add(rightButton);
//Grid Panel Left
JPanel gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(4,1,5,5));
gridPanel.setBorder(new LineBorder(Color.black, 3));
gridPanel.setBackground(Color.red);
gridPanel.add(leftButton);
//Center Box
JLabel label = new JLabel("Center Box", SwingConstants.CENTER);
label.setOpaque(true);
label.setBorder(new LineBorder(Color.black,3));
middlePanel.add(gridPanel);
mainContainer.add(label);
mainContainer.add(middlePanel, BorderLayout.WEST);
mainContainer.add(rightPanel, BorderLayout.EAST);
//Panel Bottom
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout(3));
bottomPanel.add(bottomButton);
bottomPanel.setBackground(Color.magenta);
bottomPanel.setBorder(new LineBorder(Color.BLUE, 3));
mainContainer.add(bottomPanel, BorderLayout.SOUTH);
//Siegel
String filepath = "/resources/siegel.jpg";
int picWidth = 150;
int picHeight = 150;
ImageIcon image1 = new ImageIcon(getClass().getResource(filepath));
//Image scaledImage = img.getScaledInstance(picWidth, picHeight, Image.SCALE_DEFAULT);
//ImageIcon icon = new ImageIcon(scaledImage);
mainContainer.add(new JButton(image1));
}
}
So, as a very basic example, nothing but BorderLayout
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class MyFrame extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame = new MyFrame();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public MyFrame() {
setTitle("This is an example title");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(new JButton("Top button (stretched)"), BorderLayout.NORTH);
add(new JButton("Left button (stretched)"), BorderLayout.WEST);
add(new JButton("Right button (stretched)"), BorderLayout.EAST);
add(new JButton("Bottom button (stretched)"), BorderLayout.SOUTH);
JLabel label = new JLabel("Picture");
label.setBorder(new EmptyBorder(100, 100, 100, 100));
add(label);
}
}
Remember, simple is often best.
Now, if you absolutely, positively must have the label/picture in another container, you can simply make use of GridBagLayout, as it will centre the child component(s) by default, for example...
JLabel label = new JLabel("Picture");
label.setBorder(new EmptyBorder(100, 100, 100, 100));
// Automatic center position
JPanel mainPane = new JPanel(new GridBagLayout());
mainPane.add(label);
add(mainPane);
And you don't have to use EmptyBorder. GridBagLayout will allow to supply insets which will do the same thing
i am writing simple code with GUI that should have one text area which should be scrollable. So far so good.
I created my frame and the text area and i can write in it ok. Next I created my ScrollPane and added the TextArea in it, then added the ScrollPane to the frame but nothing shows.
Here is the code i have at this point:
JFrame frame = new JFrame();
frame.setBounds(100, 100, 325, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//textArea
JTextArea textArea = new JTextArea();
textArea.setEnabled(true);
textArea.setEditable(true);
JScrollPane scroll = new JScrollPane(textArea,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textArea.setBounds(10, 101, 272, 149);
textArea.setWrapStyleWord(true);
frame.getContentPane().add(scroll);
change
frame.getContentPane().setLayout(null);
to
frame.getContentPane().setLayout(new BorderLayout());
and you are done
You have to set the bounds to the component that is being added to the content pane of the frame. In this case, it should be: scroll.setBounds(10,101,271,149).
However, I strongly recommend to not use null layout. Use a layout manager of your choice, BorderLayout for instance. In this case you don't have to worry about the bounds, it will fit the frame size (it will resize when you change the size of the frame). Here's your example, tweaked a little bit:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setBounds(100, 100, 325, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
// textArea
JTextArea textArea = new JTextArea();
textArea.setEnabled(true);
textArea.setEditable(true);
JScrollPane scroll = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textArea.setWrapStyleWord(true);
frame.getContentPane().add(scroll, BorderLayout.CENTER);
frame.setVisible(true);
}
}
I'm still learning however by looking at this case.
I have couple of issues:
There is issue with setting bounds of textArea
Layout of frame/container should not be set to null.
I have removed this sentence, and I tried this code, it displays desired textArea.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/*
* Tester class
*/
public class GuiTester extends JFrame{
public static void main(String[] args) {
// create new instance of JFrame
GuiTester s = new GuiTester();
// set the frame to be visible
s.setVisible(true);
}
/**
* Tester constructor calling method which initialise all widgets.
*/
GuiTester() {
//
invokeWidget();
}
/*
* This code is yours, just removed setting up the values of container and did that straight on the frame.
*/
void invokeWidget() {
setBounds(100, 100, 325, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JTextArea textArea = new JTextArea();
textArea.setEnabled(true);
textArea.setEditable(true);
JScrollPane scroll = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textArea.setWrapStyleWord(true);
add(scroll);
}
}
This is the line that was causing issues, as well as setting layout Manager to null.
// textArea.setBounds(10, 101, 272, 149);
I hope I helped, and if I'm wrong please correct me as well.
I have the following code
JFrame frame = new JFrame("Organizer");
frame.setBounds(100, 100, 700, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
JButton testbutton = new JButton("testbutton");
testbutton.setBounds(0, 0, 55, 55);
JButton testbutton2 = new JButton("tdestbutton2");
testbutton2.setBounds(55, 0, 44, 44);
frame.add(testbutton2);
frame.add(testbutton);
and the result sometimes is correct and sometimes is this
what im doing wrong?
What am I doing wrong?
Don't use setBounds(); do use a layout manager.
Invoke setVisible() after adding components to the enclosing container.
Construct and manipulate Swing GUI objects only on the event dispatch thread.
The example below adds a panel having an empty border and a GridLayout that is padded to match. For such an application, also consider JToolBar for the buttons and CardLayout for the working screens.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see http://stackoverflow.com/a/37366846/230513
*/
public class Test {
private static final int PAD = 50;
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new GridLayout(0, 1, PAD, PAD));
p.setBorder(BorderFactory.createEmptyBorder(PAD, PAD, PAD, PAD));
p.add(new JButton("Test Button 1"));
p.add(new JButton("Test Button 2"));
f.add(p, BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Test()::display);
}
}
testbutton.setBounds(0, 0, 55, 55);
testbutton.setLocation(50, 50);
testbutton2.setBounds(55, 0, 44, 44);
testbutton2.setLocation(50, 100);
Get rid of those statement because then do nothing.
They do nothing because the default layout manager for the content pane of a JFrame is a BorderLayout. The BorderLayout will reset the size/location of each component.
The BorderLayout expects you to provide a "constraint", when you add the component to the frame. If you don't provide the constraint, then the "CENTER" is used. Only a single component can be added to the "CENTER" so only the last button added is displayed.
A simple solution to understand the basic concept of using a BorderLayout is to use:
//frame.add(testbutton2);
//frame.add(testbutton);
frame.add(testbutton2, BorderLayout.PAGE_START);
frame.add(testbutton, BorderLayout.PAGE_END);
This will display the button on two rows.
Read the Swing tutorial on Layout Managers for more information and examples. Download the demo code and modify that code will follow Swing conventions.
For example, you need to add components to the frame BEFORE you make the frame visible. So the order of the code should be:
frame.add(...);
frame.add(...);
frame.pack();
frame.setVisible(true);
The scroll bar doesn't show. I've tried most of the codes people replied with in previous questions like this one.
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea_2 = new JTextArea();
textArea_2.setRows(200);
textArea_2.setBounds(0, 22, 434, 120);
textArea_2.setEditable(false);
JScrollPane scrollv2 = new JScrollPane (textArea_2);
frame.add(scrollv2);
frame.getContentPane().add(textArea_2);
scrollv2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
frame.setVisible (true);
You are adding your JTextArea to your content pane where you should be actually adding your JScrollPane to the content pane of your JFrame. You should add the JTextArea to the content pane of the JScrollPane. Below is an example of the visible scroll bar in action:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class SimpleScrollBars extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SimpleScrollBars frame = new SimpleScrollBars();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public SimpleScrollBars() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
contentPane.add(scrollPane, BorderLayout.CENTER);
JTextArea textArea = new JTextArea(5, 15);
scrollPane.setViewportView(textArea);
pack();
}
}
The scrollbars will appear automatically when the preferred size of the text area is greater than the size of the scroll pane.
Your text area doesn't have any text to display, therefore its preferred size is (0, 0).
Also:
Don't use textArea_2.setBounds(...). This does nothing. The scrollpane has its own layout manager and will determine the appropriate size for the text area.
Don't use textArea_2.setRows(200). The 200 represents rows of text, not pixels. Your monitor can't display 200 rows of text. So use a reasonable value, like 10 or 20 depending on your application requirements.