更改 JLabel 文本会更改 GridBagLayout 的空间分布

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

我有一个带有 GridBagLayout 的 JFrame,其中包含一个 JLabel 和一个 JScrollPane。 JScrollPane 包含一个ScrollablePanel,而ScrollablePanel 又包含一定数量的DebugComponent。 DebugComponents 维护从 JScrollPane 的高度导出的纵横比。 JFrame 与 GridBagLayout 的布局一开始就很合适。

但是现在,我使用 MouseMotionListener 通过线程间接更改 JLabel 的文本。如果鼠标悬停在 DebugComponent 上,则会显示一条文本。否则该区域是空的。然而,当我移动到 DebugComponent 时,布局发生了变化。如果我在 DebugComponent 和 ScrollablePanel 之间来回移动鼠标,JScrollPane 使用的空间会变得越来越大。仅当只剩下 JLabel 文本的空间时,它才会停止。

代码是我的问题的抽象。除了 ScrollablePanel 的类(在此处获取)之外,代码已完成。

package de.franken.debug;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;

public class DebugGUI {

    private static JLabel label;
    public static ScrollablePanel panel;

    /** Main method + GUI configuration */
    public static void main(String[] args) {
        JFrame frame = new JFrame(); // JFrame
        frame.setLayout(new GridBagLayout());
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        GridBagConstraints c = new GridBagConstraints();

        panel = new ScrollablePanel(new GridLayout(1, 0)); // Panel containing DebugItems
        panel.setScrollableHeight(ScrollablePanel.ScrollableSizeHint.FIT);
        for (int i = 0; i < 1; i++) {
            panel.add(new DebugComponent(0.2));
        }
        c = new GridBagConstraints();
        c.gridy = 1;
        c.weighty = 0.6;
        c.gridwidth = 1;
        c.weightx = 1;
        c.fill = GridBagConstraints.BOTH;

        JScrollPane pane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); // ScrollPane containing Panel
        new SlideThread(pane);
        frame.add(pane, c);

        label = new JLabel("PLACEHOLDER"); // Label displaying String
        label.setHorizontalAlignment(SwingConstants.CENTER);
        c = new GridBagConstraints();
        c.gridy = 2;
        c.weighty = 0.4;
        c.fill = GridBagConstraints.BOTH;
        c.gridwidth = 1;
        c.weightx = 1;
        frame.add(label, c);

        frame.setSize(400, 400);
        frame.setVisible(true);

    }

    /**
     * Change text of JLabel beneath ScrollablePane. -> Called by SlideThread
     * 
     * @param strg : the String to be displayed
     */
    public static void setPreview(String strg) {
        label.setText(strg);
    }

    static class DebugComponent extends JComponent {

        private static final long serialVersionUID = -4770356342749347317L;
        private double widthRatio;

        /**
         * JComponent as part of ScrollablePanel with constant dimension ratio
         * 
         * @param widthRatio : the ratio to be multiplied with height to get width
         */
        DebugComponent(double widthRatio) {
            this.widthRatio = widthRatio;
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension parent = super.getSize();

            return new Dimension((int) (parent.height * widthRatio), parent.height);
        }

        @Override
        protected void paintComponent(Graphics g) {
            // TODO Auto-generated method stub
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillRect(0, 0, (int) getPreferredSize().getWidth() - 1, (int) getPreferredSize().getHeight() - 1);
        }
    }

    static class SlideThread extends Thread {
        private String strg = " ";

        SlideThread(JScrollPane pane) {
            pane.addMouseMotionListener(adapter);
            this.start();
        }

        @Override
        public void run() {
            while (true) {
                try {
                    sleep(45);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                DebugGUI.setPreview(strg);
            }
        }

        // Show String during hovering
        MouseAdapter adapter = new MouseAdapter() {

            @Override
            public void mouseMoved(MouseEvent e) {
                Component c = DebugGUI.panel.getComponentAt(e.getPoint());
                if (c instanceof DebugComponent) {
                    strg = "Titel";
                } else {
                    strg = " ";
                }
            }
        };
    }

}

java swing gridbaglayout
1个回答
0
投票

GridBagLayout 仅考虑可见组件,因此当您的 JLabel 为空时,布局会将其视为无维度组件,并表现得好像它实际上不存在一样。

您可以尝试采取以下几项措施来避免此问题:

a) 将 JLabel 的文本设为空白,而不是空,例如

myLabel.setText(" ")
而不是
myLabel.setText("")

b) 当不应该有任何文本时,更改文本的颜色以匹配标签的背景颜色。

您可能会幸运地将标签放入 GridBagLayout 的一个单元格内的 BorderLayout 中,希望 BorderLayout 的“贪婪”性质扩展组件以占用尽可能多的可用空间,但我还没有尝试过我自己,所以我不能肯定。

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