在循环内的 JscrollPane 内添加标签
Add labels inside JscrollPane inside loop
我有一个循环生成一些标题和描述,它们是字符串值,我制作标签以包含这两个字符串,我想将它们添加到 JScrollPane
,但出于某种原因我的代码是'不工作,我现在没有收到任何错误,没有项目被添加到滚动窗格,这是我的代码:
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();
}
}
我尝试 System.out.println
标题和恢复变量及其工作,所以问题不在于它们。
一个问题是您试图将组件直接添加到 JScrollPane,而这不是组件应该去的地方。相反,这些组件属于视口的视图,即 JScrollPane 正在显示的组件。
建议:
- 创建一个表示此视图的 JPanel,并将其添加到 JScrollPane 的视口。
- 给这个 JPanel 一个合适的布局,这样它就能正确显示添加到它的组件
- 在上面的代码中,将您的组件添加到此 JPanel,然后重新验证并重新绘制它,以便其布局管理器布置组件并正确绘制它们。
- 或者可能更好更简洁,将表格数据添加到 JScrollPane 持有的 JTable
例如,下面的代码将一对 JLabel 添加到 innerPanel JPanel,其中一个使用 BorderLayout 将一个标签放置在左侧,另一个放置在中间。
然后将此 innerPanel 放入另一个 JPanel,即 viewportViewPanel,后者使用 GridLayout 将 innerPanel 放置在单列多行网格中。通过将 viewportViewPanel 传递到 JScrollPane 的构造函数,将其放置在 JScrollPane 的视口中。请注意,我们从不 在 JScrollPane 上调用 .add(...)
:
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());
}
}
更好的是,如果您希望显示标题和说明,请考虑在 JList 中仅显示标题,并在 JTextArea 中显示所选 JList 项目的说明。像这样:
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());
}
}
我做了一些更正以使您的代码正常工作,并添加了注释来解释需要完成的工作:
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
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();
}
}
代码可以进一步改进。我尽量减少更改,希望它能让您更容易看到更改。
如果需要,请不要犹豫,要求澄清。
我有一个循环生成一些标题和描述,它们是字符串值,我制作标签以包含这两个字符串,我想将它们添加到 JScrollPane
,但出于某种原因我的代码是'不工作,我现在没有收到任何错误,没有项目被添加到滚动窗格,这是我的代码:
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();
}
}
我尝试 System.out.println
标题和恢复变量及其工作,所以问题不在于它们。
一个问题是您试图将组件直接添加到 JScrollPane,而这不是组件应该去的地方。相反,这些组件属于视口的视图,即 JScrollPane 正在显示的组件。
建议:
- 创建一个表示此视图的 JPanel,并将其添加到 JScrollPane 的视口。
- 给这个 JPanel 一个合适的布局,这样它就能正确显示添加到它的组件
- 在上面的代码中,将您的组件添加到此 JPanel,然后重新验证并重新绘制它,以便其布局管理器布置组件并正确绘制它们。
- 或者可能更好更简洁,将表格数据添加到 JScrollPane 持有的 JTable
例如,下面的代码将一对 JLabel 添加到 innerPanel JPanel,其中一个使用 BorderLayout 将一个标签放置在左侧,另一个放置在中间。
然后将此 innerPanel 放入另一个 JPanel,即 viewportViewPanel,后者使用 GridLayout 将 innerPanel 放置在单列多行网格中。通过将 viewportViewPanel 传递到 JScrollPane 的构造函数,将其放置在 JScrollPane 的视口中。请注意,我们从不 在 JScrollPane 上调用 .add(...)
:
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());
}
}
更好的是,如果您希望显示标题和说明,请考虑在 JList 中仅显示标题,并在 JTextArea 中显示所选 JList 项目的说明。像这样:
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());
}
}
我做了一些更正以使您的代码正常工作,并添加了注释来解释需要完成的工作:
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
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();
}
}
代码可以进一步改进。我尽量减少更改,希望它能让您更容易看到更改。
如果需要,请不要犹豫,要求澄清。