-1

I have a loop that generates some Titles and Description which are String values and I made Labels to contains theses two strings, I want to add these to a JScrollPane, but for some reason my code isn't working, I'm not getting any error now, no item is being added to the scroll pane, here's my code:

package testa;

import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class test extends JFrame {

    JLabel[] titles;
    JLabel[] descriptions;
    JPanel[] panels;
    JScrollPane jScrollPane1 = new JScrollPane();
    JPanel bigPanel = new JPanel();

    public test() {
        this.setLocationRelativeTo(null);
        this.setSize(1000, 500);
        this.jScrollPane1.setSize(1000, 500);

        this.getContentPane().add(this.jScrollPane1);

        this.setVisible(true);
        requetezQuery();
    }

    public void requetezQuery() {
        int resultsList = 10;
        this.titles = new JLabel[resultsList];
        this.descriptions = new JLabel[resultsList];
        this.panels = new JPanel[resultsList];
        for (int i = 0; i < resultsList; i++) {

            String title = "Test Title " + i;
            String resume = "Test Resume " + i;

            this.titles[i] = new JLabel();
            this.descriptions[i] = new JLabel();
            this.panels[i] = new JPanel();
            this.panels[i].setLayout(new FlowLayout());
            this.titles[i].setText(title);
            this.descriptions[i].setText(resume);
            this.titles[i].setForeground(Color.red);
            this.descriptions[i].setForeground(Color.red);
            this.panels[i].add(this.titles[i]);
            this.panels[i].add(this.descriptions[i]);
            this.bigPanel.add(panels[i]);
        }
        this.jScrollPane1.add(this.bigPanel);
    }

    public static void main(String args[]) {
        test a = new test();
    }
}

I tried to System.out.println the titles and resume variables and its working, so the problem isn't from them.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Fragan
  • 792
  • 10
  • 29
  • to post a complete answer, we need a complete question including a [mcve]. You're likely making a very basic error besides what I've mentioned below, an error in code not shown. – Hovercraft Full Of Eels May 19 '18 at 02:24
  • I edited code again, i made a Jpanel that contains the JPanels, then the JScrollPane will contain than one Big JPanel, but it still not working – Fragan May 19 '18 at 03:18
  • You're still calling `jScrollPane1.add(...)` on the JScrollPane. As mentioned several times, you should never do this. – Hovercraft Full Of Eels May 19 '18 at 03:22
  • 1
    1) Use a logical and consistent form of indenting code lines and blocks. The indentation is intended to make the flow of the code easier to follow! 2) A single blank line of white space in source code is all that is *ever* needed. Blank lines after `{` or before `}` are also typically redundant. 3) Please learn common Java nomenclature (naming conventions - e.g. `EachWordUpperCaseClass`, `firstWordLowerCaseMethod()`, `firstWordLowerCaseAttribute` unless it is an `UPPER_CASE_CONSTANT`) and use it consistently. – Andrew Thompson May 19 '18 at 07:29

2 Answers2

1

One problem is that you're trying to add components directly to the JScrollPane which is not where the components are supposed to go. Instead these components belong within the viewport's view, the component that the JScrollPane is displaying.

Suggestions:

  • create a JPanel that represents this view, and add this to the JScrollPane's viewport.
  • Give this JPanel a decent layout so that it will be able to display components added to it correctly
  • In your code above, add your components to this JPanel, then revalidate and repaint it so that its layout managers layout the components and paint them correctly.
  • Or perhaps better still and much cleaner, add your tabular data to a JTable that is held by the JScrollPane

For example, the code below adds a pair of JLabels to an innerPanel JPanel, one which uses a BorderLayout to place one label to the left and the other center. It then places this innerPanel into another JPanel, viewportViewPanel, which uses a GridLayout to place the innerPanel in a single column multiple row grid. The viewportViewPanel is placed within a JScrollPane's viewport by passing it into the JScrollPane's constructor. Note that we never call .add(...) on the JScrollPane:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;

public class MyTest extends JPanel {
    private static final int COUNT = 400;
    private JPanel viewportViewPanel = new JPanel();
    private JScrollPane scrollPane = new JScrollPane(viewportViewPanel);

    public MyTest() {
        setPreferredSize(new Dimension(800, 500));
        viewportViewPanel.setLayout(new GridLayout(0, 1));
        for (int i = 0; i < COUNT; i++) {
            String text = "abcd efgh ijkl mnop qrst uvwx";
            text = String.format("%s %s %s", text, text, text);
            JPanel innerPanel = new JPanel();
            innerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
            innerPanel.setLayout(new BorderLayout());
            innerPanel.add(new JLabel("Test Title:"), BorderLayout.LINE_START);
            innerPanel.add(new JLabel(text, SwingConstants.CENTER));
            viewportViewPanel.add(innerPanel);
        }

        setLayout(new BorderLayout());
        add(scrollPane);
    }

    private static void createAndShowGui() {
        MyTest mainPanel = new MyTest();

        JFrame frame = new JFrame("MyTest");
        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());
    }
}

Better still, if your desire is to show a title and description, consider showing only the titles in a JList, and showing the selected JList item's description within a JTextArea. Something like so:

import java.awt.BorderLayout;

import javax.swing.*;

@SuppressWarnings("serial")
public class ShowTitleDescriptions extends JPanel {
    private static final int COUNT = 500;
    // nonsense text as a demo filler
    private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur "
            + "adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore "
            + "magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco "
            + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor "
            + "in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
            + "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa "
            + "qui officia deserunt mollit anim id est laborum.";
    private DefaultListModel<TitleDescription> listModel = new DefaultListModel<>();
    private JList<TitleDescription> titlesList = new JList<>(listModel);
    private JTextArea descriptionArea = new JTextArea(20, 60);

    public ShowTitleDescriptions() {
        titlesList.setVisibleRowCount(20);
        JScrollPane titleScroll = new JScrollPane(titlesList);

        descriptionArea.setLineWrap(true);
        descriptionArea.setWrapStyleWord(true);
        descriptionArea.setEditable(false);
        JScrollPane descriptionScroll = new JScrollPane(descriptionArea);

        for (int i = 0; i < COUNT; i++) {
            String title = "Title " + i;
            StringBuilder descriptionSb = new StringBuilder();

            // fill description with random text
            for (int j = 0; j < 40; j++) {
                descriptionSb.append(title + "\n");
                descriptionSb.append(LOREM_IPSUM + " ");
                descriptionSb.append(LOREM_IPSUM + " ");
                descriptionSb.append(LOREM_IPSUM);
                descriptionSb.append("\n\n");
            }
            TitleDescription titleDescr = new TitleDescription(title, descriptionSb.toString());
            listModel.addElement(titleDescr);
        }

        titlesList.addListSelectionListener(l -> {
            TitleDescription selection = titlesList.getSelectedValue();
            descriptionArea.setText(selection.getDescription());
        });
        titlesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        titlesList.setSelectedIndex(0);

        setLayout(new BorderLayout());
        add(descriptionScroll);
        add(titleScroll, BorderLayout.LINE_END);
    }

    // class to hold title and description together
    private static class TitleDescription {
        private String title;
        private String description;

        public TitleDescription(String title, String description) {
            this.title = title;
            this.description = description;
        }

        public String getTitle() {
            return title;
        }

        public String getDescription() {
            return description;
        }

        // JList uses this to decide what to display
        @Override
        public String toString() {
            return title;
        }

    }

    private static void createAndShowGui() {
        ShowTitleDescriptions mainPanel = new ShowTitleDescriptions();

        JFrame frame = new JFrame("ShowTitleDescriptions");
        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());
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
1

I made some corrections to make you code work, and added comments to explain what needs to be done:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout; 
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test extends JFrame{ //see https://www.javatpoint.com/java-naming-conventions

    private JLabel[] titles;
    private JLabel[] descriptions;
    private JPanel [] panels;
    private JScrollPane jScrollPane1;
    private JPanel bigPanel;
    private final static int NUM_OF_RESULTS =10;

    public Test() {

        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //this.setSize(1000,500);             no need to set size. use preferred sizes
        //jScrollPane1.setSize(1000, 500);    and layouts. see following comments

        bigPanel = new JPanel();
        //set layout to
        GridLayout layout = new GridLayout(NUM_OF_RESULTS, 0);
        bigPanel.setLayout(layout);
        jScrollPane1 = new JScrollPane(bigPanel);
        getContentPane().add(jScrollPane1);

        requetezQuery();
        pack(); //see https://stackoverflow.com/questions/22982295/what-does-pack-do
        setVisible(true); //set visible typically comes last
    }
    public void requetezQuery(){

        titles = new JLabel[NUM_OF_RESULTS];
        descriptions = new JLabel[NUM_OF_RESULTS];
        panels = new JPanel[NUM_OF_RESULTS];

        for(int i = 0; i<NUM_OF_RESULTS; i++){

            String title="Test Title "+i;
            String resume="Test Resume "+i;

            titles[i]= new JLabel();
            descriptions[i]= new JLabel();
            panels[i]= new JPanel();
            panels[i].setPreferredSize(new Dimension(250, 50));
            panels[i].setLayout(new FlowLayout()); //FlowLayout is default for JPanel
            titles[i].setText(title);
            descriptions[i].setText(resume);
            titles[i].setForeground(Color.red);
            descriptions[i].setForeground(Color.red);
            panels[i].add(titles[i]);
            panels[i].add(descriptions[i]);
            bigPanel.add(panels[i],i, 0);
        }
    }

    public static void main(String args[]){
        new Test();
    }
}

The code can be further improved. I tried to minimize changes hoping that it makes it easier for you to see the changes.
Don't hesitate to ask for clarifications as needed.

c0der
  • 18,467
  • 6
  • 33
  • 65