JPanel.getHeight() 并不完全按预期工作

问题描述 投票:0回答:1

所以我有一个利用 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 才能获得高度。问题已经解决了,这不是问题

我尝试了两种方法:

  1. 只需使用JPanel.getSize().getHeight()。不包括换行,只是所有内容的高度,就好像没有换行一样

  2. 当我想到在东侧添加一个子 JPanel 的想法时,我觉得我是一个天才,这样我就可以得到它的高度,对吗?不知何故,即使它们在屏幕上的高度不同,它们也会输出相同的 getHeight()

Here is what it looks like.

每个 JPanel 右侧奇怪的蓝线是我的 heightPanel。对于我们的眼睛来说,它们的高度不同,但如果它们有换行,它们会打印相同的值

System.out.println()<- I print the heightPanel.getHeight(). All the same value

如果您有任何问题,我很乐意回答。我已经被困在这个问题上有一段时间了😅

任何帮助将不胜感激

java swing jframe jpanel jscrollpane
1个回答
0
投票

您的问题似乎是一个 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);
        });
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.