JList 没有像我预期的那样表现
JList not behaving as I expected
我正在练习 JList
,当单击“添加数字”按钮时,它会填充随机数,我 运行 遇到了一些我无法解决的问题修复。
在下面的代码中,我放置了一个按钮来切换列表的可见性状态,但事实证明它不起作用,除非列表最初是可见的。
然后我将列表设置为显示 8 行,但只显示了 7 行。
最后,如果只使用小数点后 3 位,那么右侧有足够的空间,为什么水平滚动窗格会出现?
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class JListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
listFrame myFrame=new listFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
}
}
class listFrame extends JFrame {
private static DecimalFormat df3 = new DecimalFormat("#.###");
public listFrame() {
setTitle("List demo");
setBounds(400,300,400,300);
listModel = new DefaultListModel();
randomNumberList=new JList(listModel);
//**********************************************************************
// the number of elements visible in the list turns out to be
// one less than the specified below
randomNumberList.setVisibleRowCount(8);
//**********************************************************************
randomNumberList.setFixedCellWidth(100);
JScrollPane scrollPanel=new JScrollPane(randomNumberList);
//**********************************************************************
// if this line is uncommented the button fails to make the list visible
// scrollPanel.setVisible(false);
//**********************************************************************
JPanel listPanel=new JPanel();
listPanel.add(scrollPanel);
JPanel textPanel=new JPanel();
toggle=new JButton("Toggle Visible");
toggle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
scrollPanel.setVisible(!scrollPanel.isVisible());
}
});
textPanel.add(toggle);
addNumber=new JButton("Add Numbers");
addNumber.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double min=0;
double max=1000;
double x= Math.random()*(max-min+1)+min;
listModel.addElement(df3.format(x));
randomNumberList.ensureIndexIsVisible(listModel.getSize()-1);
}
});
textPanel.add(addNumber);
add(listPanel,BorderLayout.NORTH);
add(textPanel,BorderLayout.SOUTH);
}
private JButton toggle,addNumber;
private JList randomNumberList;
private DefaultListModel listModel;
}
更新:这是我在下面的评论中提到的一些代码,其中 setVisibleRowCount 确实有效:
import java.awt.BorderLayout;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class JList_ShowMonths {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame myLFrame=new MonthFrame();
myLFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myLFrame.setVisible(true);
}
}
class MonthFrame extends JFrame {
private JList<String> monthList;
private JPanel listPanel,txtPanel;
private JLabel selectionLabel;
public MonthFrame() {
setTitle("Display the month names");
setBounds(400,300,400,300);
String [] months= {"January","February","March","April","May","June",
"July","August","September","October","November","December"};
monthList=new JList<String>(months);
monthList.setVisibleRowCount(4);
JScrollPane monthScroll=new JScrollPane(monthList);
listPanel=new JPanel();
listPanel.add(monthScroll);
monthList.addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
List<String> values=monthList.getSelectedValuesList();
StringBuilder text=new StringBuilder("Selected month: ");
for (String element:values) {
String word=element;
text.append(word);
text.append(" ");
}
selectionLabel.setText(text.toString());
}
});
txtPanel=new JPanel();
selectionLabel=new JLabel("Mes seleccionado:");
txtPanel.add(selectionLabel);
add(listPanel,BorderLayout.NORTH);
add(txtPanel,BorderLayout.SOUTH);
}
}
首先是代码。代码后的解释。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.text.DecimalFormat;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class LstFrame extends JFrame {
private static DecimalFormat df3 = new DecimalFormat("#.###");
private JButton toggle, addNumber;
private JList<Object> randomNumberList;
private DefaultListModel<Object> listModel;
public LstFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("List demo");
listModel = new DefaultListModel<Object>();
randomNumberList = new JList<>(listModel);
randomNumberList.setVisibleRowCount(8);
randomNumberList.setFixedCellWidth(100);
JScrollPane scrollPanel = new JScrollPane(randomNumberList);
scrollPanel.setPreferredSize(new Dimension(110, 100));
scrollPanel.setVisible(false);
JPanel textPanel = new JPanel();
toggle = new JButton("Toggle Visible");
toggle.addActionListener(e -> {
scrollPanel.setVisible(!scrollPanel.isVisible());
revalidate();
});
textPanel.add(toggle);
addNumber = new JButton("Add Numbers");
addNumber.addActionListener(e -> {
double min = 0;
double max = 1000;
double x = Math.random() * (max - min + 1) + min;
listModel.addElement(df3.format(x));
randomNumberList.ensureIndexIsVisible(listModel.getSize() - 1);
});
textPanel.add(addNumber);
add(scrollPanel, BorderLayout.CENTER);
add(textPanel, BorderLayout.SOUTH);
setSize(260, 240);
setLocationByPlatform(true);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new LstFrame());
}
}
如果一个组件最初是不可见的,则不会对其进行绘制,其余组件也不会以为不可见组件留下 space 的方式进行绘制。因此,在上面的代码中,我设置了 JFrame
的大小。我只是简单地摆弄数字,直到找到合适的值。
是的,JFrame
[的内容窗格] 的默认布局管理器是 BorderLayout。只有 BorderLayout
中的中心组件以其首选大小显示。因此,您应该在中心而不是在 NORTH 添加 JScrollPane
(其中包含 JList
)。并且您还应该明确设置 JScrollPane
的首选大小。另请注意,在确定 NORTH、EAST、WEST 和 SOUTH 组件所需的 space 后,CENTER 组件占据了剩余的所有 space。因此,如果您调整 JFrame
的大小,JScrollPane
的大小也会改变。
包含 JButton
的 JPanel
可以安全地添加到 SOUTH。
当您更改容器中显示的组件时(通过添加或删除组件或更改组件的可见性),您需要重新绘制 GUI。方法 revalidate
是一种方法。 toggle
.
参考 ActionListener
我不知道如何创建动画 GIF,所以我无法添加一个演示上述代码的实际操作。但是,我可以 post 分开显示不同状态的图像。
启动应用程序后。
按下后 切换 Visibe
添加十个 [随机] 数字后 – 因为 JScrollPane
的首选高度足以显示九个数字。
我正在练习 JList
,当单击“添加数字”按钮时,它会填充随机数,我 运行 遇到了一些我无法解决的问题修复。
在下面的代码中,我放置了一个按钮来切换列表的可见性状态,但事实证明它不起作用,除非列表最初是可见的。
然后我将列表设置为显示 8 行,但只显示了 7 行。
最后,如果只使用小数点后 3 位,那么右侧有足够的空间,为什么水平滚动窗格会出现?
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class JListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
listFrame myFrame=new listFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
}
}
class listFrame extends JFrame {
private static DecimalFormat df3 = new DecimalFormat("#.###");
public listFrame() {
setTitle("List demo");
setBounds(400,300,400,300);
listModel = new DefaultListModel();
randomNumberList=new JList(listModel);
//**********************************************************************
// the number of elements visible in the list turns out to be
// one less than the specified below
randomNumberList.setVisibleRowCount(8);
//**********************************************************************
randomNumberList.setFixedCellWidth(100);
JScrollPane scrollPanel=new JScrollPane(randomNumberList);
//**********************************************************************
// if this line is uncommented the button fails to make the list visible
// scrollPanel.setVisible(false);
//**********************************************************************
JPanel listPanel=new JPanel();
listPanel.add(scrollPanel);
JPanel textPanel=new JPanel();
toggle=new JButton("Toggle Visible");
toggle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
scrollPanel.setVisible(!scrollPanel.isVisible());
}
});
textPanel.add(toggle);
addNumber=new JButton("Add Numbers");
addNumber.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double min=0;
double max=1000;
double x= Math.random()*(max-min+1)+min;
listModel.addElement(df3.format(x));
randomNumberList.ensureIndexIsVisible(listModel.getSize()-1);
}
});
textPanel.add(addNumber);
add(listPanel,BorderLayout.NORTH);
add(textPanel,BorderLayout.SOUTH);
}
private JButton toggle,addNumber;
private JList randomNumberList;
private DefaultListModel listModel;
}
更新:这是我在下面的评论中提到的一些代码,其中 setVisibleRowCount 确实有效:
import java.awt.BorderLayout;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class JList_ShowMonths {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame myLFrame=new MonthFrame();
myLFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myLFrame.setVisible(true);
}
}
class MonthFrame extends JFrame {
private JList<String> monthList;
private JPanel listPanel,txtPanel;
private JLabel selectionLabel;
public MonthFrame() {
setTitle("Display the month names");
setBounds(400,300,400,300);
String [] months= {"January","February","March","April","May","June",
"July","August","September","October","November","December"};
monthList=new JList<String>(months);
monthList.setVisibleRowCount(4);
JScrollPane monthScroll=new JScrollPane(monthList);
listPanel=new JPanel();
listPanel.add(monthScroll);
monthList.addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
List<String> values=monthList.getSelectedValuesList();
StringBuilder text=new StringBuilder("Selected month: ");
for (String element:values) {
String word=element;
text.append(word);
text.append(" ");
}
selectionLabel.setText(text.toString());
}
});
txtPanel=new JPanel();
selectionLabel=new JLabel("Mes seleccionado:");
txtPanel.add(selectionLabel);
add(listPanel,BorderLayout.NORTH);
add(txtPanel,BorderLayout.SOUTH);
}
}
首先是代码。代码后的解释。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.text.DecimalFormat;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class LstFrame extends JFrame {
private static DecimalFormat df3 = new DecimalFormat("#.###");
private JButton toggle, addNumber;
private JList<Object> randomNumberList;
private DefaultListModel<Object> listModel;
public LstFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("List demo");
listModel = new DefaultListModel<Object>();
randomNumberList = new JList<>(listModel);
randomNumberList.setVisibleRowCount(8);
randomNumberList.setFixedCellWidth(100);
JScrollPane scrollPanel = new JScrollPane(randomNumberList);
scrollPanel.setPreferredSize(new Dimension(110, 100));
scrollPanel.setVisible(false);
JPanel textPanel = new JPanel();
toggle = new JButton("Toggle Visible");
toggle.addActionListener(e -> {
scrollPanel.setVisible(!scrollPanel.isVisible());
revalidate();
});
textPanel.add(toggle);
addNumber = new JButton("Add Numbers");
addNumber.addActionListener(e -> {
double min = 0;
double max = 1000;
double x = Math.random() * (max - min + 1) + min;
listModel.addElement(df3.format(x));
randomNumberList.ensureIndexIsVisible(listModel.getSize() - 1);
});
textPanel.add(addNumber);
add(scrollPanel, BorderLayout.CENTER);
add(textPanel, BorderLayout.SOUTH);
setSize(260, 240);
setLocationByPlatform(true);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new LstFrame());
}
}
如果一个组件最初是不可见的,则不会对其进行绘制,其余组件也不会以为不可见组件留下 space 的方式进行绘制。因此,在上面的代码中,我设置了 JFrame
的大小。我只是简单地摆弄数字,直到找到合适的值。
是的,JFrame
[的内容窗格] 的默认布局管理器是 BorderLayout。只有 BorderLayout
中的中心组件以其首选大小显示。因此,您应该在中心而不是在 NORTH 添加 JScrollPane
(其中包含 JList
)。并且您还应该明确设置 JScrollPane
的首选大小。另请注意,在确定 NORTH、EAST、WEST 和 SOUTH 组件所需的 space 后,CENTER 组件占据了剩余的所有 space。因此,如果您调整 JFrame
的大小,JScrollPane
的大小也会改变。
包含 JButton
的 JPanel
可以安全地添加到 SOUTH。
当您更改容器中显示的组件时(通过添加或删除组件或更改组件的可见性),您需要重新绘制 GUI。方法 revalidate
是一种方法。 toggle
.
ActionListener
我不知道如何创建动画 GIF,所以我无法添加一个演示上述代码的实际操作。但是,我可以 post 分开显示不同状态的图像。
启动应用程序后。
按下后 切换 Visibe
添加十个 [随机] 数字后 – 因为 JScrollPane
的首选高度足以显示九个数字。