How to make a Jframe containing a Jpanel scrollable? - java

So I have this JFrame that contains a JPanel and in there I add JLabels with information I want but since I'll be adding labels all the time at some point the text is too long to appear so I want to add a scrollbar. Basically I want to make my JFrame with a JPanel in it scrollable. I have this code but my problem is that even though the scrollbar appears but it doesnt move and doesn't really work when the text is a lot, meaning the text still gets cut out and the scrollbar is there not moving. Does anyone know how to fix this?
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class Bar {
JFrame info = new JFrame("Information");
JLabel ballinf = new JLabel();
JPanel contentPane = new JPanel();
JScrollPane scrolling = new JScrollPane();
public Bar(){
contentPane.setOpaque(true);
contentPane.setBackground(Color.WHITE);
contentPane.setLayout(null);
scrolling = new JScrollPane(contentPane,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
info.add(scrolling);
info.setSize(750, 600);
info.setLocationByPlatform(true);
info.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
info.setVisible(true);
}
public void adding(int pos){
ballinf = new JLabel("Something ",JLabel.CENTER);//assume the text will be bigger here and have more info
ballinf.setSize(700, 30);
ballinf.setForeground(Color.green);
ballinf.setLocation(5, 5+pos);
contentPane.add(ballinf);
info.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
info.setVisible(true);
}
public static void main(String[] args){
Bar stats = new Bar();
stats.adding(0);
stats.adding(20);//this will be done in a for loop for more than 2 times so the text ends up to be a lot
}
}

contentPane.setLayout(null);
Don't use a null layout!!!
You need to use an appropriate layout manager. Read the section from the Swing tutorial on Layout Managers for more information and working examples. The layout manager will then determine the preferred size of the panel as you add components to the panel.
The scrollpane will then display the scrollbars when necessary.
If you dynamically add components to the panel (after the GUI is visible) then the code should be something like:
panel.add(...);
panel.revalidate();
panel.repaint();

Related

Java cannot display the JPanel, but can display JLabel?

The question is that I cannot add JPanel and JLabel in the Frame at the same time.
When i using following code, only MyPanel will be visible. myFrame.add(myLabel);myFrame.add(myPanel);myFrame.setVisible(true);
when I execute: myFrame.add(myLabel);myFrame.setVisible(true);myFrame.add(myPanel);
only myLabel will be visible.
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
MyLabel myLabel = new MyLabel();
MyPanel myPanel = new MyPanel();
myFrame.add(myLabel);
myFrame.add(myPanel);
myFrame.setVisible(true);
}
}
public class MyFrame extends JFrame {
MyFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //exit out of application.
//https://docs.oracle.com/javase/7/docs/api/javax/swing/JFrame.html#setDefaultCloseOperation%28int%29
this.setSize(750, 750); //set the size.
this.setResizable(true);//resize the frame.
this.setTitle("Welocme to new world."); //set the Title.
ImageIcon imageIcon = new ImageIcon("logo.png");
this.setIconImage(imageIcon.getImage());
this.getContentPane().setBackground(new Color(217, 217, 217));
this.setBackground(Color.YELLOW);//this.setVisible(true);//Make the frame visible.
}}
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel {
MyPanel() {
this.setBackground(Color.white);
this.setBounds(2,2,25,25);
}}
import javax.swing.*;
import java.awt.*;
public class MyLabel extends JLabel {
MyLabel(){
this.setText("<html>Heaven <br/>Heaven's body\"<br/> Whirl around me <br/>Make me wonder</html>");
//,SwingConstants.CENTER);
//https://stackoverflow.com/questions/1090098/newline-in-jlabel
//How to print multi line in java
ImageIcon image = new ImageIcon("Cosmogony_Björk_Cover.jpg");
this.setIcon(image);
//jLabel.setForeground(new Color(217,217,217));
this.setForeground(Color.BLACK);
this.setFont(new Font("helvetica",Font.PLAIN,18));
this.setBackground(Color.gray);
this.setOpaque(true);
//jLabel.setVerticalTextPosition(JLabel.TOP); Set the relative text position of the label.
//jLabel.setBorder();
this.setVerticalAlignment(JLabel.CENTER);
this.setHorizontalAlignment(JLabel.CENTER);
}}
The default Layout Manager of JFrame is the BorderLayout.
Since you did not change the layout manager of your JFrame this is also the current layout manager used in your snippet.
Usually, when using the BorderLayout, you specify which area of the BorderLayout should be populated when adding a component. This is usually done via
frame.add(component, BorderLayout.CENTER);
Notice the area specification in the add() method, which tells the BorderLayout where to place the component.
Here is the issue however. If you use the add() method in combination with the BorderLayout without specifying the placement of the component, it will always place the component in BorderLayout.CENTER. (Causing the component which is currently there to be replaced)
To work around this, do one of the following things:
Specify the placement explicitly, so both components will show up:
frame.add(component1, BorderLayout.PAGE_START);
frame.add(component2, BorderLayout.CENTER);
Or use a different Layout Manager, which will take care of the placement for you. E.g. FlowLayout
JPanel contentPanel = new JPanel(); // JPanel uses flowlayout by default!
contentPanel.add(component1);
contentPanel.add(component2);
myFrame.setContentPane(contentPanel);
You could also explicitly set the layout:
Container contentPane = myFrame.getContentPane();
// creates new FlowLayout and sets on content pane
contentPane.setLayout(new FlowLayout());
contentPane.add(component1);
contentPane.add(component2);
Sidenotes:
Look through the Laying out components within a container Oracle tutorial, which will give you more information on which layout managers there are and how to work with them.
When building your GUI, setVisible() on the JFrame should be the last thing you are doing after adding all components. Because if you add components after setting the frame visible, the changes will not immediately take effect without you telling swing that something changed.
When correctly working with the Swing Layout Managers, there should be no need to use things like setBounds(...) or setSize(). After adding all components, calling pack() on the JFrame is the preferred way to go. This will size the JFrame according to the preferred size of the components inside.

How to make a JButton that will create other buttons within a JPanel?

I am creating a user system to hold multiple details of multiple users. so i would like to create a button that would be able to create another button. when the second button is pressed a form will open for the user to fill. I have already created the form for the user to fill but i cannot manage to make the button to create more buttons to work. I have coded this but it does not show the button on the Jpanel.
I have created the following code:
private void mainButtonActionPerformed(java.awt.event.ActionEvent evt) {
JButton b=new JButton("Click Here");
b.setBounds(50,100,95,30);
jPanel3.add(b);
b.setVisible(true);
}
This doesn't seem to create a new button within jPanel3. Have I typed up the code incorrectly or is there an alternative correct way of doing this?
I would like 3 buttons in a row and then a new row of buttons.
Your code and question is missing too much information to be answered completely or well. About all I can say is
Always call jPanel3.revalidate() and jPanel3.repaint() on the container after adding or removing components from it as this tells the container's (here jPanel3) layout managers to re-layout all components and then re-draw them.
The container's layout manager is key for this to work well -- we have no idea what it is at the moment, and some layout managers will allow you to do this easily (e.g., FlowLayout, GridLayout) while others won't (e.g., GroupLayout).
There's no need for b.setVisible(true); since your newly created JComponent (JButton here) is already visible by default.
You appear to assume that it's using null layouts since you're calling setBounds(...), and this is a Bad Idea™. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
When asking such questions, try to create and post with the question a small but complete program that we can test and run, and that illustrates your problem, a minimal example program (please click on the link).
For example, my MCVE that shows how your code can work:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class AddButton extends JPanel {
private JPanel jPanel3 = new JPanel(); // panel to hold buttons
public AddButton() {
// create JButton that will add new buttons to jPanel3
JButton addMoreButtonsBtn = new JButton("Add More Buttons");
// give it an ActionListener
addMoreButtonsBtn.addActionListener(e -> {
final JButton newButton = new JButton("Click Here");
// when you click it, it removes itself (just for grins)
newButton.addActionListener(e2 -> {
jPanel3.remove(newButton);
// again revalidate and repaint
jPanel3.revalidate();
jPanel3.repaint();
});
// add to jPanel3, the "container"
jPanel3.add(newButton);
// revalidate and repaint the container
jPanel3.revalidate();
jPanel3.repaint();
});
// create a JPanel and put the add more buttons button to it
JPanel bottomPanel = new JPanel();
bottomPanel.add(addMoreButtonsBtn);
// give jPanel3 a layout that can handle new buttons
// a gridlayout with 1 column and any number of rows
jPanel3.setLayout(new GridLayout(0, 1));
// add it to the top of another JPanel that uses BorderLayout
JPanel borderLayoutPanel = new JPanel(new BorderLayout());
borderLayoutPanel.add(jPanel3, BorderLayout.PAGE_START);
// and add that to a JScrollPane, so we can add many buttons and scroll
JScrollPane scrollPane = new JScrollPane(borderLayoutPanel);
// make the vert scrollbar always visible
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// force GUI to be larger
setPreferredSize(new Dimension(400, 200));
// give the main JPanel a BorderLayout
setLayout(new BorderLayout());
// and add scrollpane to center
add(scrollPane, BorderLayout.CENTER);
// add bottom panel to the bottom
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
AddButton mainPanel = new AddButton();
JFrame frame = new JFrame("AddButton");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

Aligning JButton

I have to align a button on my program to the exact middle, the current code I have runs it but displays the button as large as the program, I am wanting a center button that is a specific size, here is what I tried
/**
* Created by Timk9 on 11/04/2016.
*/
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
{
JFrame window = new JFrame("Test");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(true);
window.setSize(600, 600);
window.setVisible(true);
window.setLocationRelativeTo(null);
JPanel p = new JPanel(new GridBagLayout());
//Button does not appear until I resize the program?
JButton b1 = new JButton("Click here");
GridBagConstraints c = new GridBagConstraints();
p.add(b1);
window.add(p);
}
public static void main(String[] args) {
new Test();
}
}
JPanel p = new JPanel(new GridBagLayout());
You create a panel with a GridBagLayout which is a good layout manager to use to center the component.
p.add(b1);
But then you add the button to the panel without using any contraints.
The code should be:
p.add(b1, c);
//Button does not appear until I resize the program?
All components should be added to the frame BEFORE the frame is made visible. The setVisible(...) statement should be the last statement of the constructor.
Also could you point out which part is an instance initializer block, I thought I was using a constructor
See the FrameDemo example from the Swing tutorial on How to Make Frames for a better way to structure your code so you follow Swing conventions. Start with the working code and make the changes to add your panel containing the button, instead of using the JLabel. Note you no longer need to use the getContentPane() method, you can just add the panel directly to the frame.
It is the LayoutManager that defines how components are layed out where and how big. GridLayout which you are using e. g. divides the available space in equal grid fields and makes the components completely fill this space which is why your button is as big as your application. See here for more info about LayoutManagers: https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
Btw. your code is not compilable: new JButton("he"),JButton.ALIGN_CENTER)

How to reset or refresh Jframe with new values

I have a Jframe that the user enters new information through a Joptionpane, it is added to an array which is then appended and displayed to a contentpane.. the cycle then repeats till the user enters "STOP". Currently the program is outputting the new array under the old one. How would I clear away the old array in the content pane and only display the new values?
import java.awt.*;
import java.util.LinkedList;
import java.util.List;
public class Project1GUI {
static JFrame Frame;
static TextArea unsorted_words, sorted_words, linked_words;
public Project1GUI(String title){
//All this does is make an empty GUI FRAME.
Frame=new JFrame();//i made a new variable from the JFrame class
Frame.setSize(400,400);//Used the Variable from JFrame and used some of it functions. This function sets the hieght and width of the Frame
Frame.setLocation(200,200);//This sets where the Empty Frame should be
Frame.setTitle(title);//This puts a title up top of the Frame
Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//places an x box that closes when clicked on
Frame.setVisible(true);//This activates the JFram when is set true.
Frame.setLayout(new GridLayout(1,2));//This sets the layout of the Frame and since i want a Grid i used a GirdLayout
//Functions and placed it inside the setlayout functions. to get 2 grids i places 1 meaning 1 row and 2 for 2 cols
unsorted_words=new TextArea(); //From the TextArea class i made three variables
sorted_words= new TextArea();
linked_words= new TextArea();
Container panel=new Container();
panel=Frame.getContentPane();
panel.add(unsorted_words);
panel.add(sorted_words);
panel.add(linked_words);
}
public void add_unsorted(String words){
unsorted_words.append(words+"\n");//add words to GUI
}
public void add_sorted(String words){
sorted_words.append(words+"\n");
}
public void add_linked(List<String> linked_words2){
linked_words.append(linked_words2+"\n");
}
}
For a more definitive answer, post an MCVE
Seeing as you haven't posted any code, I'm guessing you are using a JLabel or a JList or something of that sort to display the array. No matter which one you are doing, you need to tell the component to update it's content, it doesn't just do it itself. To do that, you need to call the components .setText() or similar method.
If you have a JLabel or JTextArea it could look like this.
labelOrTextArea.setText("New Text");
If you are using a JList you should update the lists Default List Model like this
dlm.addElement("New Text");
UPDATE
I see a couple things wrong with your code. First off JFrame Frame = new JFrame conventionally, variables should start with a lower case letter and they should not contain underscores '_'. You are also using AWT Components instead of Swing components. You should be using the likes of JTextArea, JPanel (Theres no JContainer), JLabel etc.
You are also never adding the panel to the frame.
frame.add(panel);
You should also not be adding stuff to the frame or panels after you set its visibility to true. So you should setup your frame like this
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class Project1GUI
{
JTextArea unsorted_words, sorted_words, linked_words;
public Project1GUI()
{
JFrame frame = new JFrame("Title");
JPanel panel = new JPanel(new GridLayout(2, 1));
unsorted_words = new JTextArea();
sorted_words = new JTextArea();
linked_words = new JTextArea();
panel.add(unsorted_words);
panel.add(sorted_words);
panel.add(linked_words);
frame.add(panel);
frame.setSize(400,400);
frame.setLocation(200,200);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
You can then implement the methods you currently have and call them in an ActionListener or such.
Result:
On top of all of that, you should not rely on the use of static as it takes away from the main points of OOP.

Strange setBackground() error - Java Swing

import java.awt.*;
import javax.swing.*;
public class JFrameGUI extends JFrame
{
JLabel item1;
public JFrameGUI(int l, int b , String Title)
{
setTitle(Title);
setLayout(new FlowLayout());
setSize(l, b);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
item1 = new JLabel("This is a Sentence.");
item1.setToolTipText("This is gonna show up on hover.");
add(item1);
}
public static void main(String[] args)
{
JFrameGUI g = new JFrameGUI(1280,720,"The End Of The Line");
JPanel p = new JPanel();
p.setBackground(Color.BLUE);
g.add(p);
}
}
When I execute this , all i get is a tiny Blue square nest to the "This is a sentence" string . I've tried everything !
You need to set the layout of the frame to a layout that doesn't respect the preferred sizes of its children. FlowLayout does, and your JPanel has no preferred size without any components added to it, or specifying a preferred size.
A simple fix, set the layout of the frame to BorderLayout, or not set a layout at all, since JFrame already has a default BorderLayout. Note though that you probably want to add the JLabel to the JPanel and not the JFrame. Unless you do want to add it the JFrame and not the background JPanel, you need to specify a BorderLayout position for the one you don't want in the center.
You can see this answer to see which layout managers respect preferred sizes and which don't
See more at Layout out Components Withing a Container
Also, setVisible(true) shoul be the last thing you do after adding all components.

Categories

Resources