JScrollPane not appearing on JTextArea - java

I'm trying to add the JScrollPane to my JTextArea, but somehow, it won't appear.
I've tried resizing it according to the dimension of the JTextArea, but it doesn't seem to work. Also, notice that I'm using the null layout because I want the full-on flexibility of displaying certain buttons and panels at a pinpoint location.
import java.awt.Dimension;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.JTextArea;
public class PaneTester{
private static JFrame frame;
private static JPanel panel;
private static JScrollPane scrollPane;
private static JTextArea notificationBox;
public static void main (String [] args){
stage1();
stage2();
}
private static void stage1(){
createFrame();
createPanel();
frame.getContentPane().add(panel);
panel.setVisible(true);
frame.setVisible(true);
}
private static void stage2(){
generateNotificationBox();
}
private static void createFrame(){
frame = new JFrame();
frame.setSize(new Dimension(900,700));
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
}
private static void createPanel(){
panel = new JPanel();
panel.setLayout(null);
generateGridButtons();
}
private static void generateGridButtons(){
short y = 0;
for(short i=0;i<4;i++){
y += 60;
short x = 500;
for(short j=0;j<5;j++){
JButton gridButton = new JButton();
gridButton.setBounds(x, y,120,60);
panel.add(gridButton);
x += 140;
}
}
}
public static void generateNotificationBox(){
notificationBox = new JTextArea(10,10);
notificationBox.setBounds(25, 25, 200, 400);
scrollPane = new JScrollPane(notificationBox, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS );
Dimension d = new Dimension(notificationBox.getPreferredSize());
scrollPane.getViewport().setPreferredSize(d);
scrollPane.getViewport().add(notificationBox);
panel.add(notificationBox);
panel.repaint();
}
}

Stop mucking with setBounds and setPreferredSize, you're just making live more difficult for your self.
If you want to affect the size of JTextArea (and the viewable area of the JScrollPane) have a look at the JTextArea constructor JTextArea(int rows, int columns), which will allow you to specify the number of rows/columns you want the JTextArea to default to, and which will allow the JTextArea to calculate it's preferredSize based on the current font's metrics in more stable cross platform way
Your core problem, however, is right here...
scrollPane.getViewport().add(notificationBox);
panel.add(notificationBox);
You add the notificationBox to the JScrollPanes JViewport, which is good, but then you add notificationBox to the panel, which will remove it from the JScrollPane's JViewport, which is bad
Instead, add the JScrollPane to the panel
scrollPane.getViewport().add(notificationBox);
panel.add(scrollPane);
You're also making overuse of static. I'd highly recommend you take the time to reduce static down to it's absolute minimum required usage, this will probably mean that rather then constructing the UI in the main method, you have a "main" class which you can insatiate (from main) which will perform the initial setup - IMHO
I've tried that. I think someone else suggested that from another post, but when I tried that, it just took away the JTextArea completely from the panel
Get rid of panel.setLayout(null); and start making use of appropriate layout managers and compound layouts. Start by having look at Laying Out Components Within a Container for more details

Related

After changing JLabel text it will not reposition

I have a JDialog with a title written at the top. I call this JDialog for two different cases and if it is not the default I change the text to something else. This works fine but the position is then too far to the right.
I have tried numerous methods such as:
TitleText.setText("Edit Fuse");
TitleText.setAlignmentY(JLabel.CENTER_ALIGNMENT);
//TitleText.setHorizontalAlignment(JDialog.);
//TitleText.setLayout(new FlowLayout(FlowLayout.LEFT));
None of them even move the text. I am using a Free Design Layout for the entire JDialog. If I must I'll just create another JLable and hide/unhide but I thought this would be simple. Anyone know how to do this?
I am using a Free Design Layout for the entire JDialog
Don't do this if you want the title JLabel's text to be at the top and be centered. Instead have the JDialog's main JPanel use BorderLayout, and add the JLabel to it BorderLayout.PAGE_START, also known as BorderLayout.North.
The main JPanel can then hold the rest of your GUI, likely in its own JPanel, using its own layout manager, and other JPanels, in its BorderLayout.CENTER position.
Also, don't use JLabel.CENTER_ALIGNMENT, a float, but rather use JLabel.CENTER, an int, which is the appropriate parameter for the setHorizontalAlignment(...) method.
Finally, I must give you an unsolicitated side recommendation to be sure that your variable names begin with a lower-case letters and not upper case letters so that they comply with Java naming rules. This is important if you want others, such as folks here who'd like to help you, to rapidly understand your code.
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class LayoutExample extends JPanel {
private static final float SIZE = 32;
private static final int TIMER_DELAY = 2000;
private String[] TITLE_STRINGS = { "Title 1", "Title 2",
"Some Random Title", "Fubars Rule!", "Snafus Drool!" };
private int titleIndex = 0;
private JLabel titleLabel = new JLabel(TITLE_STRINGS[titleIndex],
JLabel.CENTER);
public LayoutExample() {
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, SIZE));
setLayout(new BorderLayout());
add(titleLabel, BorderLayout.PAGE_START);
// the rest of your GUI could be added below
add(Box.createRigidArea(new Dimension(500, 300)), BorderLayout.CENTER);
new Timer(TIMER_DELAY, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
titleIndex++;
titleIndex %= TITLE_STRINGS.length;
titleLabel.setText(TITLE_STRINGS[titleIndex]);
}
}).start();
}
private static void createAndShowGui() {
JFrame frame = new JFrame("LayoutExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new LayoutExample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Layout - Relative to screensize

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();
}

Last button in JFrame is set as background?

import javax.swing.JButton;
import javax.swing.JFrame;
public class Test extends JFrame {
private static final long serialVersionUID = 1L;
public Test() {
super("A test");
setSize(360,300);//Size of JFrame
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);//Sets if its visible.
JButton num1 = new JButton("1");//Set the JButton name
JButton num2 = new JButton("2");
JButton num3 = new JButton("3");
num1.setBounds(80,70,50,50);
num2.setBounds(130,70,50,50);
num3.setBounds(180,70,50,50);
add(num1);
add(num2);
add(num3);
}
public static void main (String[] args) {
new Test().setVisible(true);
}
}
Here the num3 button is set as the background, I want the buttons to be aligned. This might be a trivial mistake I'm not sure as I've just started working with JFrame. Thank you.
The Problem
Basically, there are three parts that are causing this problems...
JFrame uses a BorderLayout by default. This means that only the last component add to any one of the five available layout positions will be managed
You call setVisible(true) before adding anything to the frame
You call setBounds on the buttons.
Because the components are generally painted in z-order (in FIFO order generally) and because of the optimisation in the code, the last button is been controlled by the BorderLayout of the frame, but the other two maintain the bounds you set before
Really interesting problem
Solution(s)
Use an appropriate layout manager, maybe a FlowLayout or GridBagLayout
Call setVisible last where ever possible
Check out Laying Out Components Within a Container for details
This is because of Layout Manager. Please check the code below.
i use another JPanel to put all the buttons. i set the panel as it will have 1 row and 3 columns objects.
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test extends JFrame {
private static final long serialVersionUID = 1L;
JPanel buttonPanel;
public Test() {
super("A test");
setSize(360,300);//Size of JFrame
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);//Sets if its visible.
setLayout(null);
buttonPanel = new JPanel(new GridLayout(1, 3));
buttonPanel.setBounds(80, 70, 150, 50);
JButton num1 = new JButton("1");//Set the JButton name
JButton num2 = new JButton("2");
JButton num3 = new JButton("3");
buttonPanel.add(num1);
buttonPanel.add(num2);
buttonPanel.add(num3);
add(buttonPanel);
}
public static void main (String[] args) {
new Test().setVisible(true);
}
}
Well, never use raw placing and no Layout Manager.
This is your Bible
You can do that with some Layout tricks. For example this one:
First of all import the Layout classes.
import java.awt.GridLayout;
import java.awt.BorderLayout;
Make the frame a BorderLayout frame by copying this in the constructor of it.
setLayout(new BorderLayout());
Then make another JPanel and make it a GridLayout JPanel:
JPanel panel = new JPanel(new GridLayout(1,3));
panel.add(num1);
panel.add(num2);
panel.add(num3);
Arguments 1 and 3 mean "use exactly 1 row and 3 columns to place the widgets in this JPanel".
Finally add the last panel at the center of the frame:
add(panel,BorderLayout.CENTER);
This way you won't deal with dimensions or precise spots and still do what you want...
(to test it copy all the code in "Test" constructor)

JPanel filled with Buttons inside a JScrollPane

I'm currently trying to fill a JPanel (using GridLayout) with Buttons. These Buttons should be squares having a set width.
The programm should be able to resize the playing field (n*m buttons). Problem is, the buttons are automatically stretched to completely fill the JScrollpane, completely ignoring the set height and width. Thus making the scrollbars unnecessary.
Here is my code:
Creating the panels:
panel_game = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane(panel_game);
Trying to resize the JPanel: (where x and y are the number of buttons and zoomlvl the size)
panel_game.setLayout(new java.awt.GridLayout(x, y));
panel_game.setBounds(panel_game.getX()+5,panel_game.getY()+5,x*zoomlvl-5,y*zoomlvl);
panel_game.setPreferredSize(new Dimension(x*zoomlvl,y*zoomlvl));
And adding the buttons: (f is my playfield, a 2D-Array)(buttons is a Arraylist, containing my buttons)
for(int i=0; i<f.getSize()[0]*f.getSize()[1];i++){
buttons.add(new JButton());
buttons.get(i).setSize(zoomlvl, zoomlvl);
buttons.get(i).setPreferredSize(new Dimension(zoomlvl,zoomlvl));
panel_game.add(buttons.get(i));
}
I have no clue how I can tell Java to stop resizing my buttons etc. automatically.
Help would be appreciated :)
GridLayout is built to fill the container that uses it with components. If the container holding the buttons is constrained in size, then the buttons will stretch or fill to fill that container as closely as possible. A solution may be to nest layout managers so that this does not occur, but I can't give more specific advice without more code, particularly a minimal example program. Images might help too.
If you want to prevent the "button grid panel" from stretching to fill the whole viewport area of the ScrollPane, you could place this grid panel into another panel (with FlowLayout).
In general, you should either
not set the preferred size of the panel_game OR
not set the preferred size of the buttons
because
when you set the preferred size of the buttons, then the preferred size of the panel will be computed from the preferred sizes of the buttons
when you set the preferred size of the panel, then the size of the buttons will be determined by the size of the panel, respectively
Maybe this is what you want to achieve:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ScrollButtonGrid
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int x = 5;
int y = 5;
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(x, y));
for(int i=0; i<x*y;i++){
JButton button = new JButton(String.valueOf(i));
button.setPreferredSize(new Dimension(100,100));
panel.add(button);
}
JPanel container = new JPanel(new FlowLayout(FlowLayout.CENTER, 0,0));
container.add(panel);
JScrollPane scrollPane = new JScrollPane(container);
f.getContentPane().add(scrollPane);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

JScrollPane usage

I have a JScrollPane and JPanel inside it(I want to draw on JPanel). Also I have a method that draws lines with parametre of length of the line. I want my JScrollPane to scroll if the length of the line is more then the size(height or width) of my JPanel that is on JScrollPane.
How can I do this?
P.S. I've tried jScrollPane.scrollRectToVisible but it doesn't work
Here is an example implementing what you want
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class DrawLine {
JFrame j;
JPanel p;
JScrollPane sp;
public DrawLine() {
j = new JFrame();
p = new JPanel() {
public void paintComponent(Graphics g) {
g.drawLine(20, 20, 250, 250);
}
};
p.setPreferredSize(new Dimension(300, 300));
sp = new JScrollPane(p);
j.getContentPane().add(sp);
j.setSize(300, 300);
j.setVisible(true);
}
public static void main(String[] args) {
new DrawLine();
}
}
Note the line p.setPreferredSize(new Dimension(300, 300)); which sets the preferred size of the panel.
You need to define the following method in the LinePanel class:
public Dimension getPreferredSize() {
return new Dimension(myLine.getWidth(), myLine.getHeight());
}
Make sure that myLine object is available to the above method. And, you will get the scrollbars as needed.
P.S.: I assume LinePanel extends JPanel and is the panel on which the line is drawn.
You need to associate the JScrollPanel with the JPanel that it is scrolling. That is, you need
JScrollPane lineScrollPane = new JScrollPane(linePanel);
This will create a JScrollPane that automatically sizes itself to scroll over whatever linePanel's size is.
It's important to make sure then, that the panel containing your line actually IS big enough to fit entire line. That is, you might have something like
linePanel.setSize(myLine.getWidth(), myLine.getHeight());
or whatever your associated line size is. Note that something like
lineScrollPanel.setSize(new Dimension(600, 400));
will resize the scroll panel but not the thing inside--that is, it will be a 600x400 scroll pane but the inside panel may be bigger smaller, and it will be scrolled.

Categories