JScrollPane 组件在我单击它们之前是不可见的

JScrollPane components are invisible until I click them

因此,我尝试将组件添加到 JScrollPane,但只有当我将鼠标悬停在它们上方时它们才会出现。 这是我的代码:

package com.alex.apps;

import java.awt.CardLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneLayout;

public class main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //GetPageInfo gpi=new GetPageInfo();
        JFrame frame=new JFrame("Bookmark");
        JScrollPane pane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        frame.setContentPane(pane);
        
        JTextField text=new JTextField();
        text.setBounds(0, 10, 400, 40);
        pane.add(text);
        
        JButton add=new JButton("+");
        add.setBounds(403, 10, 40, 40);
        pane.add(add);
        
        
        frame.setSize(480, 860);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}

你知道为什么它不起作用吗?

pane.add(add);

不要将组件直接添加到滚动窗格。

相反,您需要将组件添加到滚动窗格的视口中:

//pane.add(add);
pane.setViewportView( add );

阅读有关 How to Use Scroll Panes 的 Swing 教程部分,了解滚动窗格的工作原理。

我在您的代码中发现了几个问题:

  1. public class main {、类 应该以大写字母开头,跟在 Java naming conventions 之后,这将使您和其他人更容易阅读和遵循您的代码,同时 main 是所有 Java 类 的入口点方法的名称,所以这可能会造成混淆
  • FirstWordUpperCasedClass
  • firstWordLowerCasedVariable
  • firstWordLowerCasedMethod()
  • ALL_WORDS_UPPER_CASED_CONSTANT
  1. .setBounds(...),在您的情况下,您使用的是默认值 Layout Managers,因此这些调用将被忽略,除非您有充分的理由(并且在此程序中您不要)因为不使用布局管理器,请坚持使用这些管理器,如果需要则将它们组合起来。

  2. 不要直接在你的 JFrame 上调用 setSize(...),这会将 window 装饰品变成这个尺寸,而是设置一个 preferredSize 对于 JPanel 并将 JPanel 添加到您的 JFrame,然后在您的 JFrame 上调用 pack(),请参阅:Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? 了解更多信息-深度解释。

  3. 在同一个问题的 中补充@camickr,以及您在那里发表的评论:

But now the button occupies the whole pane.

您正在尝试添加一个 JTextField 和一个 JButton,并且从 setBounds(...) 电话 我看到您正在尝试添加 + JTextField 右侧的按钮,因此在本例中,只需添加 JTextFieldJButton 都设置为全新的 JPanel,然后将 JScrollPane 的视口设置为这个新的 JPanel.

@camickr 建议将视口设置为 JButton,这就是为什么 JButton 占据了整个 space。

  1. 创建带有数字参数的 JTextField,它将告诉 Swing 您要在其上显示的列数(或字符数),而不是空的。

  2. 最后但并非最不重要的一点是,将您的程序放在 Event Dispatch Thread (EDT), see point #2 in 上以获得更多信息。

在遵循上述所有这些建议之后,您会得到一个更好的代码:

import java.awt.Dimension;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class ScrollPaneSample {
    private JFrame frame;
    private JPanel pane;
    private JScrollPane scrollPane;
    private JTextField text;
    private JButton add;
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ScrollPaneSample()::createAndShowGUI);
    }
    
    private void createAndShowGUI() {
        frame = new JFrame("Bookmark");
        pane = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 100);
            }
        };
        scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        text = new JTextField(10);
        pane.add(text);

        add = new JButton("+");
        pane.add(add);

        scrollPane.setViewportView(pane);
        
        frame.add(scrollPane);
        
        frame.pack();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

我现在 getPreferredSize(...) return 变小了,因为 window 对于这个例子来说太大了,你可以根据自己的需要调整它的大小。