Here, My Jscrollpane isn't working. I have added the scrollpane and list both on main Jpanel. The Jlist is working, But it seems, JScrollpane Not working in this code.
my main class extends Jframe, so from main class i just pass the main panel, and working on the same panel.
and here i'm using absolute layout.
public class ExternalsLinks extends JPanel {
///Links List
private JList mainList;
///List Custom Border
Border lineBorder = BorderFactory.createLineBorder(Color.BLACK, 5);
///Main Jpanel
private JPanel mainPanel;
///Scroll Pane for Lists
private JScrollPane mainListScrollPane;
/// Lebels
private JLabel lblExternalLinks;
///Buttons
private Button btnBackCredits = new Button("Back");
///Button Properties
private final int BUTTON_X = 220; private final int BUTTON_Y = 450;
private final int BUTTON_X_LENGTH = 350; private final int BUTTON_Y_LENGTH = 50;
///List Options
private String [] listMenu = {"Searching", "Sorting"};
///Constructors
public ExternalsLinks(JPanel mainPanel) {
this.mainPanel = mainPanel;
this.mainPanel.setLayout(null);
mainPanel.setBackground(Color.WHITE);
initialize_All();
}
/// Initialize method to initialize all components to JFrame
private void initialize_All() {
///Main Panel Components
lblExternalLinks = new JLabel("\"External Links\"");
lblExternalLinks.setBounds(290, 0, 400, 100);
lblExternalLinks.setFont(new Font("courier", Font.BOLD, 30));
mainPanel.add(lblExternalLinks);
mainList = new JList(listMenu);
mainList.setBackground(Color.CYAN);
mainList.setForeground(Color.BLACK);
mainList.setFont(new Font("Calibiri", Font.BOLD, 25));
mainList.setVisibleRowCount(2);
mainList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
mainList.setBorder(lineBorder);
mainList.setBounds(50, 80, 300, 350);
mainListScrollPane = new JScrollPane();
mainPanel.add(mainListScrollPane);
mainPanel.add(mainList);
///Buttons
btnBackCredits.setBounds(BUTTON_X, BUTTON_Y, BUTTON_X_LENGTH, BUTTON_Y_LENGTH);
mainPanel.add(btnBackCredits);
btnBackCredits.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
mainList.setVisible(false);
mainPanel.removeAll();
new MainMenu(mainPanel);
}
});
}
}
I have added the scrollpane and list both on main Jpanel.
That's a problem -- don't do that. You can only add a component to one container, and the JScrollPane counts as a container. So add your JList to the JScrollPane's viewport, and then only add the JScrollPane to the GUI.
i'm using absolute layout
And that's another serious problem. Don't use null layouts and setBounds(...). For instance calling setBounds on your list will prevent the scrollpane from being able to work since the list can't expand inside the JScrollPane as it should. Learn and use the layout managers.
Also, you never add the JList to the JScrollPane's viewport!
You need JScrollPane scrollPane = new JScrollPane(myList); or something similar, with whatever your variable names are. Please go through the tutorials as this is all fully explained there.
JScrollPane tutorial link
Swing Info link to tutorials and Swing resources
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import javax.swing.*;
#SuppressWarnings("serial")
public class ExternalsLinks2 extends JPanel {
// constants
private static final String[] LIST_DATA = {"Searching", "Sorting"};
private static final Font LIST_FONT = new Font("Calibiri", Font.BOLD, 25);
private static final Font LABEL_FONT = new Font("courier", Font.BOLD, 30);
private static final int LIST_VISIBLE_ROW_COUNT = 10;
private static final String TITLE_TEXT = "External Links";
private static final Color LIST_BG = Color.CYAN;
// JList field created with constant array data
private JList<String> jList = new JList<>(LIST_DATA);
public ExternalsLinks2() {
jList.setFont(LIST_FONT);
jList.setPrototypeCellValue("ABCDEFGHIJKLMNOP ABCDE");
jList.setVisibleRowCount(LIST_VISIBLE_ROW_COUNT);
jList.setBackground(LIST_BG);
JLabel titleLabel = new JLabel(TITLE_TEXT, SwingConstants.CENTER);
titleLabel.setFont(LABEL_FONT);
JButton backButton = new JButton("Back");
// add ActionListener or AbstractAction here
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5)); // use BorderLayout
add(titleLabel, BorderLayout.PAGE_START); // JLabel at top
add(new JScrollPane(jList), BorderLayout.CENTER); // JList inside of JScrollPane in center
add(backButton, BorderLayout.PAGE_END); // JButton at bottom
}
private static void createAndShowGui() {
JFrame frame = new JFrame("External Links");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ExternalsLinks2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Which displays as:
Related
I'm trying to add two JPanels to a Jframe, but it seems that they look like one. I'm trying tow stack them on top of each other like this image.
I thinking I may need to look at layout managers? I just need a little nudge in the right direction.
package projectTwo;
import javax.swing.*;
public class checkFrame
{
public static void main (String[] args)
{
JFrame frame = new JFrame("Compose Message");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
checkPanel bob = new checkPanel();
//frame.add(bob);
frame.getContentPane().add(bob);
frame.setResizable(false);
frame.setSize(750, 500);
frame.setVisible(true);
}
}
package projectTwo;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class checkPanel extends JPanel implements ActionListener
{
private JPanel entry, display;
private JLabel name, checkAmount, payOrderOf, numPrint, numWords;
private JTextField nameT, checkAmountT;
private JButton Submit;
public checkPanel()
{
entryComponents();
checkDisplay();
}
private void entryComponents(){
name = new JLabel("Name:");
checkAmount = new JLabel("Check Amount:");
nameT = new JTextField(20);
nameT.addActionListener(this);
checkAmountT = new JTextField(20);
checkAmountT.addActionListener(this);
Submit = new JButton("Submit");
Submit.addActionListener(this);
add(name);
add(nameT);
add(checkAmount);
add(checkAmountT);
add(Submit);
setPreferredSize(new Dimension(750, 75));
setBackground(new Color(200,200,200));
}
private void checkDisplay(){
payOrderOf = new JLabel("Pay to the Order of: ");
add(payOrderOf);
setBackground(new Color(220,255,225));
}
public void actionPerformed (ActionEvent event)
{
}
}
You should definitely take a look at layout managers. At the moment you are simply adding JPanels to each other without any specification on where they should be.
You have a few options in this case. You could use a GridLayout, but that leads to all the panels being the same size. If you just want two panels below each other, I would suggest using a BorderLayout. I've adjusted your code as follows:
public class checkPanel extends JPanel implements ActionListener
{
private JPanel entry, display;
private JLabel name, checkAmount, payOrderOf, numPrint, numWords;
private JTextField nameT, checkAmountT;
private JButton Submit;
public checkPanel()
{
this.setPreferredSize(new Dimension(750, 75));
entryComponents();
checkDisplay();
this.setLayout(new BorderLayout());
this.add(entry, BorderLayout.NORTH);
this.add(display, BorderLayout.CENTER);
}
private void entryComponents(){
entry = new JPanel();
// You should specify entry's layout as well FlowLayout are used by default
name = new JLabel("Name:");
checkAmount = new JLabel("Check Amount:");
nameT = new JTextField(20);
nameT.addActionListener(this);
checkAmountT = new JTextField(20);
checkAmountT.addActionListener(this);
Submit = new JButton("Submit");
Submit.addActionListener(this);
entry.add(name);
entry.add(nameT);
entry.add(checkAmount);
entry.add(checkAmountT);
entry.add(Submit);
entry.setBackground(new Color(200,200,200));
}
private void checkDisplay(){
display = new JPanel();
// You should specify display's layout as well FlowLayout are used by default
payOrderOf = new JLabel("Pay to the Order of: ");
display.add(payOrderOf);
display.setBackground(new Color(220,255,225));
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
It is in general a good idea to assign a layout to each JPanel you create. The choice of layout depends on how the panel should function.
using Gridbag Layout can help you a lot I would put a separator between panels as well
I have a JPanel inside of a JScrollPane inside of a GridBagLayout
that is not scrolling properly. What should happen is that every time the
xxx button is pressed, a new line is added inside of the scrolling pane.
What actually happens is that if xxx is pressed, say 10 times, only the
first seven lines show up and the rest can't be scrolled to. Can anyone
suggest changes to the source code below that will make scrolling behave
properly? I have spent hours on this with no success, trying strategies all
over the Web.
Notes:
The text is split in paintComponent because drawString does
not handle end-of-line characters.
The JPanel inside of JScrollPane inside of GridBagLayout configuration is a necessary part of a much larger
piece of software with the same problem, so I have kept it here.
Thanks.
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class question {
public static void main(String[] args) {
new DrawingGUI();
}
private static class ScrollingPane extends JPanel {
private static final long serialVersionUID = 1L;
String text;
public ScrollingPane() {
setPreferredSize(new Dimension(300, 100));
text = "";
}
public void SetText(String text_x) {text = text + System.lineSeparator() + text_x;}
public void paintComponent(Graphics g) {
super.paintComponent(g);
FontMetrics fm = g.getFontMetrics();
int y = -fm.getHeight();
for (String text : text.split("\n"))
g.drawString(text, 0, y += fm.getHeight());
}
}
static class DrawingGUI extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
JPanel jp;
JScrollPane js;
ScrollingPane sp;
int LineNum;
DrawingGUI() {
LineNum = 0;
JFrame frame = new JFrame("xxx");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
addComponentsToPane(frame.getContentPane());
frame.setSize(800,800);
frame.setVisible(true);
}
public void addComponentsToPane(Container pane) {
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JButton button = new JButton("xxx");
button.setActionCommand("add_text");
button.addActionListener(this);
c.gridx = 0;
c.gridy = 0;
pane.add(button, c);
jp = new JPanel();
c.gridx = 0;
c.gridy = 1;
c.ipadx = 600;
c.ipady = 450;
pane.add(jp, c);
sp = new ScrollingPane();
js = new JScrollPane(sp);
js.getViewport().setPreferredSize(new Dimension(300,100));
c.gridx = 0;
c.gridy = 2;
c.ipady = 50;
pane.add(js, c);
}
public void actionPerformed(ActionEvent e) {
if ("add_text".equals(e.getActionCommand())) {
LineNum++;
sp.SetText("LineNum = " + LineNum);
sp.revalidate();
sp.repaint();
}
}
}
}
You're short circuiting the ability of your ScrollingPane JPanel from correctly sizing itself with this line:
setPreferredSize(new Dimension(300, 100));
This will fix the size of the ScrollingPane JPanel. I see that you have several possible solutions:
Difficult: override getPreferredSize() for the ScrollingPane JPanel, and calculate the appropriate preferred size based on the size of the text it holds and draws using FontMetrics.
Easier: Don't add text as you're doing, but rather have ScrollingPane use a GridLayout(0, 1) (one column, variable number of rows), and add JLabels to the ScrollingPane when new text is needed to be added. Then call revalidate() and repaint() on it.
Easier still: Don't use a ScrollingPane JPanel but rather a JTextArea, that looks like a JPanel and that can't be edited. Add that to the JScrollPane, and again, do not restrict its size
Easiest: Just use a JList as that's the functionality you are using here.
For instance, either of these would work and would look similar:
private static class ScrollingPane2 extends JPanel {
private static final long serialVersionUID = 1L;
private JTextArea textArea = new JTextArea(6, 20);
public ScrollingPane2() {
setLayout(new BorderLayout());
add(textArea, BorderLayout.CENTER);
textArea.setEditable(false);
textArea.setFocusable(false);
textArea.setBackground(null);
}
public void SetText(String text_x) {
textArea.append(text_x + "\n");
}
}
private static class ScrollingPane3 extends JPanel {
private static final long serialVersionUID = 1L;
private DefaultListModel<String> listModel = new DefaultListModel<>();
private JList<String> jList = new JList<>(listModel);
public ScrollingPane3() {
setLayout(new BorderLayout());
add(jList, BorderLayout.CENTER);
jList.setBackground(null);
}
public void SetText(String text_x) {
listModel.addElement(text_x);
}
}
Why does my Inner JPanel not display my JLabel text?
I have an outer JPanel, and an inner JPanel to display some text with the right dimensions. However I don't understand why it won't show?
JPanel jp = new JPanel();
jp.setBackground(Color.decode("#ffffff"));
jp.setBounds(0, 35, 400, 315);
JPanel mostInner = new JPanel();
mostInner.setForeground(Color.black);
mostInner.setBounds(207, 5, 190, 240);
jp.add(mostInner);
JLabel jltxt = new JLabel();
jltxt.setText("Test");
mostInner.add(jltxt);
Again, much better to avoid using null layouts and setBounds(...). 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 re-size 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.
For example, the following code creates this GUI:
This uses a GridLayout to place a JPanel in the right hand side of another JPanel. If I wanted to add more components in different relative locations, it would be easy to do by simply nesting JPanels, each using its own layout.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
public class WorkWithLayouts extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 400;
private static final int PREF_H = 315;
private static final String BG = "#ffffff";
public WorkWithLayouts() {
JPanel mostInner = new JPanel();
mostInner.setForeground(Color.black);
mostInner.setOpaque(false); // if you want the backing jpanel's background to show through
// add title temporarily just to show where mostInner panel is
mostInner.setBorder(BorderFactory.createTitledBorder("most inner")); // TODO: delete this
JLabel jltxt = new JLabel();
jltxt.setText("Test");
mostInner.add(jltxt);
setBackground(Color.decode(BG));
setLayout(new GridLayout(1, 2));
add(new JLabel()); // empty label
add(mostInner);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
} else {
return new Dimension(PREF_W, PREF_H);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
private static void createAndShowGui() {
WorkWithLayouts mainPanel = new WorkWithLayouts();
JFrame frame = new JFrame("Work With Layouts");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
As already mentioned by Hovercraft Full Of Eels, you can help us to help you by adding a small program to your question that shows your problem (see https://stackoverflow.com/help/mcve for more information). Then people can try to reproduce and solve the issue.
When I created a small program myself, it seemed to work fine:
import java.awt.*;
import javax.swing.*;
public class LabelNotVisible {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(() -> new LabelNotVisible().createAndShowGui());
}
private void createAndShowGui() {
JFrame frame = new JFrame("Stack Overflow");
frame.setBounds(100, 100, 800, 200);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel jp = new JPanel();
jp.setBackground(Color.decode("#ffffff"));
//jp.setBounds(0, 35, 400, 315);
JPanel mostInner = new JPanel();
mostInner.setForeground(Color.black);
//mostInner.setBounds(207, 5, 190, 240);
jp.add(mostInner);
JLabel jltxt = new JLabel();
jltxt.setText("Test");
mostInner.add(jltxt);
frame.getContentPane().add(jp);
frame.setVisible(true);
}
}
I have a JFrame which I add a custom JPanel class to. That JPanel class has two member variables, another JPanel and a JScrollPane.
I construct the JScrollPane using the child JPanel, I then try to add the JScrollPane to the parent JPanel in hopes I would have a scrollable custom JPanel.
I have a big thin white line infront of all my components and their is no scrolling. Any ideas?
public class CreateGamePanel extends JPanel
{
private JLabel pwLabel;
private JTextField password;
private JScrollPane jsp;
private JPanel area;
public CreateGamePanel()
{
area = new JPanel();
area.setLayout(new BoxLayout(area,BoxLayout.Y_AXIS));
jsp = new JScrollPane(area);
pwLabel = new JLabel("Password");
password = new JTextField();
for(int i=0;i<20;i++)
{
area.add(new JButton("Hello"));
}
area.add(pwLabel);
area.add(password);
add(jsp);
}
public static void main(String[] args)
{
JFrame f = new JFrame();
CreateGamePanel cp = new CreateGamePanel();
f.add(cp);
f.setSize(500,500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
The default policy of scroll bars in a JScrollPane is to only show up when the size of the child component doesn't fit inside the pane. What is happening in your code is that the JScrollPane's parent is the game panel and is automatically being resized to contain the entire JScrollPane and its child instead of being forced to fit in the available space in the JFrame. To do that you just have to be more specific on setting up your layouts.
Try this code, for example:
public class CreateGamePanel extends JPanel {
private JLabel pwLabel;
private JTextField password;
private JScrollPane jsp;
private JPanel area;
public CreateGamePanel()
{
area = new JPanel();
area.setLayout(new BoxLayout(area,BoxLayout.Y_AXIS));
jsp = new JScrollPane(area);
pwLabel = new JLabel("Password");
password = new JTextField();
for(int i=0;i<20;i++)
{
area.add(new JButton("Hello"));
}
area.add(pwLabel);
area.add(password);
setLayout(new BorderLayout()); // Change default LinearLayout to BorderLayout
add(jsp, BorderLayout.CENTER); // Add child to the central area of BorderLayout
}
public static void main(String[] args)
{
JFrame f = new JFrame();
CreateGamePanel cp = new CreateGamePanel();
f.add(cp, BorderLayout.CENTER); // Make sure the game panel will be resized to fit frame
f.setSize(500,500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
The trick here is that contents in the BorderLayout.CENTER part of the BorderLayout are resized to fit the available space in the parent.
I have been attempting to recreate this in Java: http://imgur.com/pjt7SMZ
This is the code I have so far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Display extends JFrame implements ActionListener {
private static final int FRAME_WIDTH = 400;
private static final int FRAME_HEIGHT = 350;
private static final int FRAME_X_ORIGIN = 100;
private static final int FRAME_Y_ORIGIN = 75;
private JButton readFileButton;
private JButton exitButton;
private JButton statsButton;
private JButton clearButton;
private JButton helpButton;
private JLabel headerLabel;
public Display() {
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setResizable(false);
setTitle("CSCE155A Course Offering Viewer");
setLocation(FRAME_X_ORIGIN, FRAME_Y_ORIGIN);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel header = new JPanel(new GridLayout(1, 1, 5, 5));
headerLabel = new JLabel("CSCE155A Course Offering Viewer");
header.add(headerLabel);
}
public static void main(String[] args) {
Display frame = new Display();
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
}
}
My problem is with JPanel. As we were instructed, we are suppose to use the BorderLayout with GridLayout inside, but nothing happens whenever I run the code. Is JPanel even the best way to do this? Right now I'm just trying to get the header to work.
According to your design, you should not add JLabel on JPanel. Add headerLabel on top of JFrame and align the text CENTER.
headerLabel = new JLabel("CSCE155A Course Offering Viewer",JLabel.CENTER);
add(headerLabel,BorderLayout.NORTH);// Add it with JFrame.