JButtons 只有当鼠标悬停在它们上面时才会出现
JButtons only appear when mouse hover over them
我的项目有问题(可能不止一个..)。
JButton
组件只有在我将鼠标悬停在它们上面时才会显示。
我的项目基本上是从 MySQL 获取数据并将其设置在按钮上。
例如:
- 'Aaa', 1000, 'alphabet' 在 jbutton[0]
- 'Bbb'、50、'alphabet2' 在 jbutton[1]
上
等等...
按钮在 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 + "]";
}
}
我的项目有问题(可能不止一个..)。
JButton
组件只有在我将鼠标悬停在它们上面时才会显示。
我的项目基本上是从 MySQL 获取数据并将其设置在按钮上。
例如:
- 'Aaa', 1000, 'alphabet' 在 jbutton[0]
- 'Bbb'、50、'alphabet2' 在 jbutton[1] 上
等等...
按钮在 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 + "]";
}
}