JButtons 只有当鼠标悬停在它们上面时才会出现

JButtons only appear when mouse hover over them

我的项目有问题(可能不止一个..)。 JButton 组件只有在我将鼠标悬停在它们上面时才会显示。

我的项目基本上是从 MySQL 获取数据并将其设置在按钮上。

例如:

等等...

按钮在 JPanel 上,它位于 JScrollPane 中。 (我是故意这样做的,因为数据不能在没有滚动的情况下放在一个面板中,当我单击按钮时,必须弹出一个与单击按钮上的信息相关的新 window)

我在另一个按钮集上添加了一个 ActionListener,这是 'category' 个按钮(鸡肉、披萨),用于将数据放在我上面提到的按钮上。单击类别按钮时,将根据类别提取数据并一个一个地设置在按钮上。

我搜索了很多次来解决这个问题,但我找不到答案。只是假设,它发生是因为我到处使用 setLayout(null),或者因为在主框架设置为可见后添加了按钮。

解决问题很好,但我更想知道原因。

请帮我找出这个问题的原因,以免下次再犯同样的错误,避免不良做法!

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class JbuttonNotShowUp extends JFrame implements ActionListener {
    JButton chicken, pizza;
    JButton[] jbtnArray;
    JPanel jp, jpFullofButtons;
    JScrollPane jsp;

    public JbuttonNotShowUp() {

        jp = new JPanel();
        jp.setLayout(null);

        jpFullofButtons = new JPanel();
        jpFullofButtons.setLayout(null);

        jsp = new JScrollPane(jpFullofButtons, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        chicken = new JButton("chicken");
        pizza = new JButton("pizza");

        jp.setBounds(0, 0, 440, 650);

        chicken.setBounds(25, 80, 61, 35);
        pizza.setBounds(90, 80, 61, 35);

        jsp.setBounds(25, 140, 385, 450);

        chicken.addActionListener(this);
        pizza.addActionListener(this);

        jp.add(jsp);
        jp.add(chicken);
        jp.add(pizza);
        add(jp);

        setBounds(0, 0, 450, 650);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        JbuttonNotShowUp f = new JbuttonNotShowUp();
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        JButton jbutton = (JButton) e.getSource();

        jpFullofButtons.removeAll();

        DataDAO dao = new DataDAO();
        ArrayList<DataVO> list = dao.dataExtract(jbutton.getText());

        jbtnArray = new JButton[list.size()];

        int y = 0;
        for (int i = 0; i < list.size(); i++) {
            jbtnArray[i] = new JButton(
                    list.get(i).getName() + "," + list.get(i).getPrice() + "," + list.get(i).getDescription());
            jbtnArray[i].setSize(390, 50);
            jbtnArray[i].setLocation(0, y);
            jbtnArray[i].addActionListener(this);
            jpFullofButtons.add(jbtnArray[i]);
            y += 50;
        }

    }
}

问题:

  • 您正在使用 null layout-using JPanel 将 JButton 保存在 JScrollPane 中,这将使滚动窗格无法显示滚动条和有效滚动
  • 您将组件添加到容器(与上面相同的 JPanel)中,但没有告诉 GUI 重新绘制容器,因此组件(添加的 JButton)不会显示。后者通过在将组件添加到 JPanel 后调用 jpFullofButtons.repaint(); 来修复——但是 JScrollPane 仍然无法正常工作

最好使用合适的布局管理器,这里可能是 GridLayout,并在向容器 jpFullofButtons JPanel 添加组件后调用 revalidate()repaint()

关于您的 MRE 尝试的旁注:它 几乎 在那里,但您仍然留在 DAO 要求以及未定义的 class,DataVO,阻止我们复制、粘贴和 运行 您的代码。

我的 MRE 示例:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.text.NumberFormat;
import java.util.Locale;
import javax.swing.*;

@SuppressWarnings("serial")
public class JButtonsShowUp extends JPanel {
    private JButton reAddButtonsBtn = new JButton("Re-Add Buttons");
    private JPanel jpFullofButtons = new JPanel(new GridLayout(0, 1));
    private JScrollPane jsp = new JScrollPane(jpFullofButtons);
    
    public JButtonsShowUp() {
        reAddButtonsBtn.addActionListener(e -> reAddButtons());
        JPanel topPanel = new JPanel();
        topPanel.add(reAddButtonsBtn);
        
        jsp.setPreferredSize(new Dimension(385, 450));
        
        int gap = 20;
        setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
        setLayout(new BorderLayout());
        add(topPanel, BorderLayout.PAGE_START);
        add(jsp, BorderLayout.CENTER);
    }
    
    private void reAddButtons() {
        jpFullofButtons.removeAll();
        int max = 100;
        for (int i = 0; i < max; i++) {
            String randomText = "";
            for (int j = 0; j < 5; j++) {
                char c = (char) ('a' + (int) (26 * Math.random()));
                randomText += c;
            }
            
            double randomPrice = 10 + 20 * Math.random();
            final DataVO2 data = new DataVO2(randomText, randomPrice);
            
            String text = String.format("Text: %s%02d, Price: $%1.2f", randomText, i, randomPrice);
            JButton button = new JButton(text);
            button.addActionListener(e -> buttonAction(data));
            jpFullofButtons.add(button);
        }
        jpFullofButtons.revalidate();
        jpFullofButtons.repaint();
        
    }
    
    private void buttonAction(DataVO2 data) {
        System.out.println("Button pressed: " + data);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JButtonsShowUp mainPanel = new JButtonsShowUp();

            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

}

class DataVO2 {
    private NumberFormat priceFormat = NumberFormat.getCurrencyInstance(Locale.US);
    private String name;
    private double price;

    public DataVO2(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        String priceText = priceFormat.format(price);
        return "DataVO2 [name=" + name + ", price=" + priceText + "]";
    }
    
}