所以我有一个利用 JFrame 和 JPanel 等的程序。我有多个 JPanel,其中包含 JTextArea,就像一个列表。我正在尝试创建 JScrollPane,它允许我从上到下滚动所有 JPanel。为此,我试图获取所有 JPanel 的高度 + 之间的空格(即 55...像素?)。但是,当使用函数 JPanel.getHeight() 时,它会给出 JPanel 的高度,而无需额外的换行。这是为什么?
用户界面.java
package groupid;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.json.simple.JSONObject;
import org.junit.internal.TextListener;
public class UserInterface {
//Sort Options - Different Ways to Short Data
static String sortOptions[] = {"A - Z","Z - A","Recently Created","Oldest Created","Recently Modified"};
//Main Frame Components
static ImageIcon icon;
static JFrame mainFrame = new JFrame();
static JPanel mainPanel;
static JScrollPane mainScrollPane;
//Main Panel Components
static JPanel rightPanel;
static JPanel sidePanel;
//Right Panel Components
static JPanel topPanel;
static JPanel searchPanel;
static JLabel searchLabel;
static JTextField searchBar;
static String searchText;
static JPanel sortPanel;
static JLabel sortByLabel;
static JPanel bottomPanel;
static JPanel addButtonPanel;
static JButton addButton;
static JPanel flowPanel;
static JPanel footerPanel;
static JPanel titlePanel;
static JLabel titleLabel;
static JPanel heightPanel;
static JTextArea valueLabel;
static String clipboardString;
static Boolean pasteBool;
static Boolean startUp;
public static void main(String[] args) {
Database.startUp();
UserInterface.jFrameCreate();
}
static Action paste = new AbstractAction("Paste") {
@Override
public void actionPerformed(ActionEvent e) {
try {
clipboardString = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException | IOException e1) {
e1.printStackTrace();
}
pasteBool = true;
new AddToClippyBoard();
pasteBool = false;
}
};
public static void jFrameCreate(){
startUp = true;
mainFrame.setVisible(true);
mainFrame.setSize(1600, 900);
mainFrame.setTitle("ClippyBoards");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setResizable(true);
mainFrame.setFocusable(true);
mainFrame.setLayout(new BorderLayout(10,0));
mainFrame.addWindowListener(new WindowAdapter() { // Exits out of application
@Override
public void windowClosing(WindowEvent e) {
Database.saveFile();
mainFrame.dispose();
}
});
icon = new ImageIcon("EggSMP.png");
mainFrame.setIconImage(icon.getImage());
mainFrame.getContentPane().setBackground(new Color(100,100,100));
// Right Panel - Panel that holds bottom panel and main panel
rightPanel = new JPanel(new BorderLayout(5,5));
rightPanel.setBackground(new Color(150,150,150));
rightPanel.setPreferredSize(new Dimension(1200,500));
mainFrame.add(rightPanel,BorderLayout.CENTER);
mainPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,20,20));
mainPanel.setPreferredSize(new Dimension(1000,0));
mainPanel.setBackground(new Color(230,230,230));
mainScrollPane = new JScrollPane(mainPanel);
mainScrollPane.createVerticalScrollBar();
mainScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
mainScrollPane.getVerticalScrollBar().setUnitIncrement(20);
rightPanel.add(mainScrollPane); // adds mainPanel, with scroll bar
KeyStroke ctrlV = KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_DOWN_MASK);
mainPanel.getActionMap().put("Paste", paste);
mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ctrlV, "Paste");;
// Side Panel - Navigate and organize folders
sidePanel = new JPanel(new FlowLayout());
sidePanel.setPreferredSize(new Dimension(500,100));
sidePanel.setBackground(new Color(220,228,232));
mainFrame.add(sidePanel,BorderLayout.WEST);
//Top Panel - Search Bar & Sorting Options
topPanel = new JPanel(new BorderLayout());
topPanel.setPreferredSize(new Dimension(1000,50));
topPanel.setBackground(new Color(230,230,230));
rightPanel.add(topPanel,BorderLayout.NORTH);
//Search Panel - Holds Search Bar
searchPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING,5,12));
searchPanel.setPreferredSize(new Dimension(500,50));
searchPanel.setBackground(new Color(230,230,230));
topPanel.add(searchPanel,BorderLayout.EAST);
//Search Label
searchLabel = new JLabel();
searchLabel.setFont(new Font("Arial",Font.BOLD,20));
searchLabel.setText("Search:");
searchPanel.add(searchLabel);
//Search Bar - Search for Items within
searchBar = new JTextField();
searchBar.setPreferredSize(new Dimension(250,30));
searchBar.setBackground(new Color(250,250,250));
searchBar.setFont(new Font("Arial",Font.PLAIN,20));
searchBar.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
jFrameRefresh();
searchText = searchBar.getText();
}
@Override
public void insertUpdate(DocumentEvent e) {
jFrameRefresh();
searchText = searchBar.getText();
}
@Override
public void changedUpdate(DocumentEvent e) {
jFrameRefresh();
searchText = searchBar.getText();
}
});
searchPanel.add(searchBar);
//Sort Panel - Holds Sort Filter
sortPanel = new JPanel(new FlowLayout(FlowLayout.LEADING,5,12));
sortPanel.setPreferredSize(new Dimension(600,50));
sortPanel.setBackground(new Color(230,230,230));
topPanel.add(sortPanel,BorderLayout.WEST);
//Sort Label
icon = new ImageIcon(new ImageIcon("SortBlack.png").getImage().getScaledInstance(30, 30, Image.SCALE_DEFAULT));
sortByLabel = new JLabel();
sortByLabel.setFont(new Font("Arial",Font.BOLD,20));
sortByLabel.setText("Sort By:");
sortByLabel.setIcon(icon);
sortPanel.add(sortByLabel);
//sort Filter - Sorts data by selected filter
JComboBox<String> sortBy = new JComboBox<String>(sortOptions);
sortBy.setPreferredSize(new Dimension(200,30));
sortBy.setFont(new Font("Arial",Font.PLAIN,20));
sortPanel.add(sortBy);
// Bottom Panel - Undecided
bottomPanel = new JPanel(new BorderLayout());
bottomPanel.setPreferredSize(new Dimension(100,50));
bottomPanel.setBackground(new Color(220,228,232));
rightPanel.add(bottomPanel,BorderLayout.SOUTH);
// Button Panel - Holds Add Button
addButtonPanel = new JPanel();
addButtonPanel.setPreferredSize(new Dimension(50,50));
addButtonPanel.setBackground(new Color(220,228,232));
bottomPanel.add(addButtonPanel,BorderLayout.EAST);
// Add Button - Will open window to import new info
addButton = new JButton("+");
addButton.setFont(new Font("Arial",Font.BOLD,20));
addButton.setAlignmentX(JPanel.CENTER_ALIGNMENT);
addButton.setAlignmentY(JPanel.CENTER_ALIGNMENT);
addButtonPanel.add(addButton);
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==addButton) {
pasteBool = false;
new AddToClippyBoard();
}
}
});
startUp = false;
jFrameRefresh();
}
public static void jFrameRefresh() {
mainPanel.removeAll();
loadClippy();
System.out.println("repaint");
mainFrame.revalidate();
mainFrame.repaint();
}
public static void loadClippy() {
int mainPanelSize = 0;
for (int i = 0; i < Database.jsonArray.size(); i++) {
JSONObject tempObject = (JSONObject) Database.jsonArray.get(i);;
flowPanel = new JPanel(new BorderLayout());
flowPanel.setBackground(new Color(220,220,220));
mainPanel.add(flowPanel);
footerPanel = new JPanel();
footerPanel.setPreferredSize(new Dimension(1000,5));
footerPanel.setBackground(new Color(220,220,220));
flowPanel.add(footerPanel,BorderLayout.SOUTH);
titlePanel = new JPanel(new BorderLayout());
titlePanel.setPreferredSize(new Dimension(1000,50));
titlePanel.setBackground(new Color(220,220,220));
flowPanel.add(titlePanel,BorderLayout.NORTH);
titleLabel = new JLabel();
titleLabel.setFont(new Font("Arial",Font.BOLD,25));
titleLabel.setText(tempObject.get("name").toString());
titlePanel.add(titleLabel);
heightPanel = new JPanel();
heightPanel.setBackground(new Color(0,0,220));
flowPanel.add(heightPanel,BorderLayout.EAST);
valueLabel = new JTextArea();
valueLabel.setFont(new Font("Arial",Font.PLAIN,15));
valueLabel.setBackground(new Color(220,220,220));
valueLabel.setLineWrap(true);
valueLabel.setWrapStyleWord(true);
valueLabel.setEditable(false);
valueLabel.setText(tempObject.get("value").toString());
flowPanel.add(valueLabel);
mainFrame.revalidate();
mainFrame.repaint();
System.out.println(heightPanel.getHeight());
mainPanelSize += 55+heightPanel.getHeight();
}
mainPanel.setPreferredSize(new Dimension(1000,mainPanelSize));
}
}
对于我正在处理的部分,搜索“public static void LoadClippy()”。
我浏览了很多论坛,并解决了第一个问题,它会打印 0,因为您必须首先添加并重新绘制 JPanel 才能获得高度。问题已经解决了,这不是问题
只需使用JPanel.getSize().getHeight()。不包括换行,只是所有内容的高度,就好像没有换行一样
当我想到在东侧添加一个子 JPanel 的想法时,我觉得我是一个天才,这样我就可以得到它的高度,对吗?不知何故,即使它们在屏幕上的高度不同,它们也会输出相同的 getHeight()
每个 JPanel 右侧奇怪的蓝线是我的 heightPanel。对于我们的眼睛来说,它们的高度不同,但如果它们有换行,它们会打印相同的值
<- I print the heightPanel.getHeight(). All the same value
如果您有任何问题,我很乐意回答。我已经被困在这个问题上有一段时间了😅
任何帮助将不胜感激
您的问题似乎是一个 XY 问题,您询问如何解决特定的代码问题,而最佳解决方案是使用完全不同的方法。
您的问题是“为什么
getHeight()
没有像我希望的那样工作,而真正的问题是您使用了错误的布局管理器。您似乎想要创建 JScrollPane 中保存的项目列表,正确滚动并正确显示,但由 JScrollPane 保存并保存所有列表子组件的主 JPanel 使用 FlowLayout,这是一种非常有限的布局管理器,主要用于非常简单的基于线性的布局。在这种情况下,一种可能的解决方案是让滚动窗格持有的主 JPanel 使用面向页面轴的 BoxLayout。这样,添加的组件将添加到之前添加的组件下方。这样,使用 BoxLayout,JScrollPane将自动正确调整其视口的大小,而无需使用任何getHeight()
拼凑,一个脆拼凑,正如您所发现的那样。
例如我的MRE程序:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
@SuppressWarnings("serial")
public class UserInterface2 extends JPanel {
private static final int PREF_W = 1600;
private static final int PREF_H = 900;
JPanel mainPanel = new JPanel();
public UserInterface2() {
setLayout(new BorderLayout());
setBackground(new Color(100, 100, 100));
JPanel sidePanel = new JPanel();
sidePanel.setPreferredSize(new Dimension(500, 100));
sidePanel.setBackground(new Color(220, 228, 232));
add(sidePanel, BorderLayout.WEST);
JPanel topPanel = new JPanel();
topPanel.setPreferredSize(new Dimension(1000, 50));
topPanel.setBackground(new Color(230, 230, 230));
JPanel rightPanel = new JPanel(new BorderLayout(5, 5));
rightPanel.setBackground(new Color(150, 150, 150));
rightPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
mainPanel.setBackground(new Color(230, 230, 230));
JScrollPane scrollPane = new JScrollPane(mainPanel);
rightPanel.add(scrollPane);
add(rightPanel);
int maxI = 30;
for (int i = 0; i < maxI; i++) {
mainPanel.add(createFlowPanel(i));
}
}
private JPanel createFlowPanel(int i) {
// panel to hold each cell
JPanel flowPanel = new JPanel();
flowPanel.setLayout(new BorderLayout());
flowPanel.setBackground(new Color(220, 220, 220));
// add a white border around the panel to separate cells
int ebGap = 14;
flowPanel.setBorder(BorderFactory.createLineBorder(Color.WHITE, ebGap));
JLabel titleLabel = new JLabel("", SwingConstants.LEADING);
titleLabel.setFont(new Font("Arial", Font.BOLD, 25));
// titleLabel.setText(tempObject.get("name").toString());
titleLabel.setText("name " + i); // !!
flowPanel.add(titleLabel, BorderLayout.PAGE_START);
JTextArea valueLabel = new JTextArea();
valueLabel.setFont(new Font("Arial", Font.PLAIN, 15));
valueLabel.setBackground(new Color(220, 220, 220));
valueLabel.setLineWrap(true);
valueLabel.setWrapStyleWord(true);
valueLabel.setEditable(false);
// create a bunch of random text of random lengths
StringBuilder sb = new StringBuilder();
for (int j = 0; j < 3 + (int) 3 * Math.random(); j++) {
for (int k = 0; k < 10 + (int) 20 * Math.random(); k++) {
for (int l = 0; l < 4 + (int)8 * Math.random(); l++) {
char myChar = (char)('a' + (int) ('z' - 'a' + 1) * Math.random());
sb.append(myChar);
}
sb.append(" ");
}
sb.append(System.lineSeparator());
}
valueLabel.setText(sb.toString());
flowPanel.add(valueLabel);
return flowPanel;
}
@Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
int w = Math.max(superSize.width, PREF_W);
int h = Math.min(superSize.height, PREF_H);
return new Dimension(w, h);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
UserInterface2 ui2 = new UserInterface2();
JFrame frame = new JFrame("ClippyBoards");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(ui2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}