使用NetBeans GUI编辑器为学校创建保龄球计划。我可以将JPanel添加到JList吗?如果是这样的话?
答案 0 :(得分:4)
这不可能(意味着它不会像你期望的那样) - 你真正想要的是一个列表LayoutManager
,它将在垂直或水平列表中布置组件。因此,不要使用JList
,而是使用JPanel
和类似列表的布局管理器。
试试这些:
BoxLayout
会将所有JPanels
放在一个列/行GridLayout
会将所有JPanels
放在一个列/行中并使它们的大小相同答案 1 :(得分:2)
试试这个。它适用于我。
class PanelRenderer implements ListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JPanel renderer = (JPanel) value;
renderer.setBackground(isSelected ? Color.red : list.getBackground());
return renderer;
}
}
public void ShowItemList(List<JPanel> paneList, JPanel container) {
DefaultListModel model = new DefaultListModel();
for (JPanel pane:paneList) {
model.addElement(pane);
}
final JList list = new JList(model);
list.setFixedCellHeight(40);
list.setSelectedIndex(-1);
list.setCellRenderer(new JPanelToJList.PanelRenderer());
JScrollPane scroll1 = new JScrollPane(list);
final JScrollBar scrollBar = scroll1.getVerticalScrollBar();
scrollBar.addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
System.out.println("JScrollBar's current value = " + scrollBar.getValue());
}
});
container.add(scroll1);
}
答案 2 :(得分:1)
转到本教程: 它与你的问题有相同的概念......
http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#renderer
答案 3 :(得分:0)
我只是整理了一些不是JList的内容,因此它缺少很多功能,但是您可以轻松地添加这些功能。
但是您得到的是:一个列表(所有成员大小均相等),可以轻松容纳约20亿个面板,而没有内存或性能问题-请参阅演示代码。此外,JPanel可以包含您想要的任何内容,这些组件将正常工作。
在演示中,JPanel成员没有内部JPanel,并且对鼠标事件完全透明(JButton除外,这很好):添加到整个容器中的侦听器将其接收,如演示中所示。如果添加更多的组件层次结构,IDK可能会变得棘手。
无论如何,这件事闪电般快速,并且最重要的是,它可以完成工作:列表中的JPanels既可以操作,也可以选择。 (没有内置选择代码,但是就像我说的:容易做到。鼠标悬停在其中的演示代码。)
final public class FastPanelListDemo {
private static JFrame window = null;
private static FastPanelList panelList = null;
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
setLookAndFeelDefault();
panelList = new FastPanelList(FastPanelList.FPLOrientation.VERTICAL,
FastPanelListDemo::supplyPanel,
0.1,
0.95,
false,
80,
Integer.MAX_VALUE);
final Container contentPane = panelList.container;
contentPane.setPreferredSize(new Dimension(300, 800));
contentPane.setBackground(Color.GRAY);
window = new JFrame("FastPanelList demo");
window.setContentPane(contentPane);
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
contentPane.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(final MouseEvent e) {
final JPanel itemUnderMouse = panelList.getItemUnderMouse(e);
if (itemUnderMouse != null) {
itemUnderMouse.setBackground(new Color((float) Math.random(),
(float) Math.random(),
(float) Math.random()));
}
}
});
});
}
private static JPanel supplyPanel(final int panelIndex) { // Just supply something that extends JPanel. You can put as much data in as you want. E.g. "boolean isMouseHovering" etc.
final JLabel label = new JLabel("panel " + panelIndex);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setVerticalAlignment(SwingConstants.CENTER);
final JButton button = new JButton("click me");
button.addActionListener(e -> {
JOptionPane.showMessageDialog(window,
"That was button " + panelIndex + ".",
"* CLICK *",
JOptionPane.INFORMATION_MESSAGE);
});
final JPanel panel = new JPanel(new BorderLayout(0,
0));
panel.setBorder(BorderFactory.createEmptyBorder(10,
10,
10,
10));
panel.setBackground(new Color((float) Math.random(),
(float) Math.random(),
(float) Math.random()));
panel.add(label, BorderLayout.CENTER);
panel.add(button, BorderLayout.EAST);
return panel;
}
private static void setLookAndFeelDefault() {
setLookAndFeel("Windows",
UIManager.getSystemLookAndFeelClassName(),
UIManager.getCrossPlatformLookAndFeelClassName(),
"Windows Classic",
"Nimbus",
"Metal",
"CDE/Motif");
}
/**
* @param intendedLAFIs ANYTHING, but ideally a LookAndFeel name or several. The first value that equalsIgnoreCase
* an installed LookAndFeelInfo.getName() will be used.
*/
private static void setLookAndFeel(final String... intendedLAFIs) {
if (intendedLAFIs != null && intendedLAFIs.length > 0) {
final UIManager.LookAndFeelInfo[] installedLAFIs = UIManager.getInstalledLookAndFeels();
LAFILOOP:
for (String intendedLAFI : intendedLAFIs) {
for (final UIManager.LookAndFeelInfo lafi : UIManager.getInstalledLookAndFeels()) {
if (lafi.getName().equalsIgnoreCase(intendedLAFI)) {
try {
UIManager.setLookAndFeel(lafi.getClassName());
break LAFILOOP;
} catch (Exception e) {
continue LAFILOOP;
}
}
}
}
} else {
throw new IllegalArgumentException("intendedLAFIs is null or empty.");
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* FastPanelList v[1, 2019-05-22 14!00 UTC] by Dreamspace President
*/
final public class FastPanelList {
public enum FPLOrientation {
HORIZONTAL(Adjustable.HORIZONTAL),
VERTICAL(Adjustable.VERTICAL);
final public int orientationAsConstant;
FPLOrientation(final int orientationAsConstant) {
this.orientationAsConstant = orientationAsConstant;
}
}
final public FPLOrientation orientation;
final private Function<Integer, JPanel> panelSupplier;
final private double fractionOfExtentToScrollPerArrowClick;
final private double fractionOfExtentToScrollPerTrackClick;
final private boolean hideScrollbarWhenUnnecessary;
final private JScrollBar scrollBar;
final private int scrollBarWidth; // The default width it normally has in any GUI.
final public JPanel container; // The container of it all.
private int panelSize = 0; // The horizontal or vertical extent of each contained panel.
private int panelCount = 0; // The amount of panels, indeed max Integer.MAX_VALUE.
private long contentSize = 0; // The sum total extent of all "contained panels". (They're not really contained, but nobody will see that.)
private long actualScrollPosition = 0; // The true scroll position, think contentSize.
private Dimension lastKnownContainerSize = new Dimension(0, 0);
private Map<Integer, JPanel> knownPanels = new HashMap<>(); // All panels of which some pixels are currently potentially visible are cached here.
/**
* @param orientation Whether horizontal or the more common vertical arrangement.
* @param panelSupplier Your code that supplies the panels as needed on the fly.
* @param fractionOfExtentToScrollPerArrowClick E.g. 0.1 for 10% of the visible area to become hidden/shown when you
* click a scrollbar arrow.
* @param fractionOfExtentToScrollPerTrackClick E.g. 0.95 for 95% of the visible area to become hidden/shown when
* you click in the scrollbar track.
* @param hideScrollbarWhenUnnecessary Guess.
* @param panelSize Can later also be done via setter. (Not tested.)
* @param panelCount dto.
*/
public FastPanelList(final FPLOrientation orientation,
final Function<Integer, JPanel> panelSupplier,
final double fractionOfExtentToScrollPerArrowClick,
final double fractionOfExtentToScrollPerTrackClick,
final boolean hideScrollbarWhenUnnecessary,
final int panelSize,
final int panelCount) {
if (orientation == null) {
throw new IllegalArgumentException("orientation is null.");
}
if (panelSupplier == null) {
throw new IllegalArgumentException("panelSupplier is null.");
}
this.orientation = orientation;
this.panelSupplier = panelSupplier;
this.fractionOfExtentToScrollPerArrowClick = Math.max(0, fractionOfExtentToScrollPerArrowClick);
this.fractionOfExtentToScrollPerTrackClick = Math.max(0, fractionOfExtentToScrollPerTrackClick);
this.hideScrollbarWhenUnnecessary = hideScrollbarWhenUnnecessary;
setPanelSize(panelSize);
setPanelCount(panelCount);
scrollBarWidth = determineScrollBarDefaultWidth();
scrollBar = new JScrollBar(orientation.orientationAsConstant, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
scrollBar.addAdjustmentListener(e -> update());
container = new JPanel(null); // NULL: We want to layout everything manually.
container.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(final ComponentEvent e) {
update();
}
});
}
private int determineScrollBarDefaultWidth() { // Called only ONE time.
final JScrollPane dummyForDefaultSize = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
dummyForDefaultSize.setPreferredSize(new Dimension(1000, 1000));
dummyForDefaultSize.setSize(dummyForDefaultSize.getPreferredSize());
dummyForDefaultSize.doLayout();
return dummyForDefaultSize.getVerticalScrollBar().getSize().width;
}
/**
* FastPanelList requires each item to have the exact same size. This is where you define it (if you reconsidered
* after your constructor call).
*
* @param panelSize Will become >=1
*/
public void setPanelSize(final int panelSize) {
this.panelSize = Math.max(1, panelSize);
}
/**
* FastPanelList easily manages Integer.MAX_VALUE (about 2 billion) panels with no memory or performance problems.
* You define the amount here. You don't add/remove panels in this thing: Instead, you will be asked to provide
* panels as required depending on screen layout etc.
*
* @param panelCount Will become >=0
*/
public void setPanelCount(final int panelCount) {
this.panelCount = Math.max(0, panelCount);
}
/**
* Clears the internal JPanel cache. Necessary if you want to repopulate the list. Setting the panel count and
* calling update() is not sufficient. (Call update AFTER this method.)
*/
public void clear() {
knownPanels.clear();
}
public JPanel getItemUnderMouse(final MouseEvent e) {
return getItemUnderMouse(e.getX(), e.getY());
}
public JPanel getItemUnderMouse(final int xInComponent,
final int yInComponent) {
final long realPositionUnderMouse = (actualScrollPosition + (orientation == FPLOrientation.HORIZONTAL ? (long) xInComponent : (long) yInComponent));
final int indexUnderMouse = (int) (realPositionUnderMouse / panelSize);
return knownPanels.get(indexUnderMouse);
}
/**
* This layouts the component. This is done automatically when the scrollbar is moved or the container is resized,
* but any other action would require YOU to call this.
*/
public void update() {
container.removeAll();
lastKnownContainerSize = container.getSize();
final int containerSize;
if (orientation == FPLOrientation.HORIZONTAL) {
scrollBar.setLocation(0, lastKnownContainerSize.height - scrollBarWidth);
scrollBar.setSize(lastKnownContainerSize.width, scrollBarWidth);
containerSize = lastKnownContainerSize.width;
} else {
scrollBar.setLocation(lastKnownContainerSize.width - scrollBarWidth, 0);
scrollBar.setSize(scrollBarWidth, lastKnownContainerSize.height);
containerSize = lastKnownContainerSize.height;
}
contentSize = (long) panelCount * (long) panelSize;
final long invisibleStuff = contentSize - containerSize;
actualScrollPosition = Math.max(0, Math.min(invisibleStuff,
(long) (getScrollBarPosRatio() * (invisibleStuff))
));
final int extent;
if (contentSize > 0) {
final double visibleRatio = containerSize / (double) contentSize;
extent = (int) Math.max(0, Math.min(Integer.MAX_VALUE, Integer.MAX_VALUE * visibleRatio));
} else {
extent = Integer.MAX_VALUE;
}
final int unitIncrement = (int) Math.max(1,
Math.min(extent,
extent * fractionOfExtentToScrollPerArrowClick));
final int blockIncrement = (int) Math.max(1,
Math.min(extent,
extent * fractionOfExtentToScrollPerTrackClick));
scrollBar.getModel().setExtent(extent);
scrollBar.setUnitIncrement(unitIncrement);
scrollBar.setBlockIncrement(blockIncrement);
scrollBar.setVisible(!hideScrollbarWhenUnnecessary || extent < Integer.MAX_VALUE);
final Dimension panelSizes = getPanelSize();
long n = actualScrollPosition;
final long endOfScreen = actualScrollPosition + containerSize + panelSize;
final Map<Integer, JPanel> newKnownPanels = new HashMap<>();
while (n < endOfScreen) { // Loop ongoing = need more panels to fill the view.
// Calc index of current panel.
final long panelIndex = n / panelSize;
if (panelIndex > Integer.MAX_VALUE) {
throw new Error();
} else if (panelIndex >= panelCount) {
break;
}
final int panelIndexInt = (int) panelIndex;
// Obtain current panel - if possible from cache, else from external provider (which might likely create it from scratch).
JPanel panel = knownPanels.get(panelIndexInt);
if (panel == null) {
panel = panelSupplier.apply(panelIndexInt);
if (panel == null) {
throw new IllegalArgumentException("panelSupplier returned null for index " + panelIndex);
}
}
newKnownPanels.put(panelIndexInt, panel);
// Set position and size.
final int panelPos = (int) ((panelIndex * panelSize) - actualScrollPosition);
final Point location;
if (orientation == FPLOrientation.HORIZONTAL) {
location = new Point(panelPos, 0);
} else {
location = new Point(0, panelPos);
}
panel.setLocation(location);
panel.setSize(panelSizes);
n += panelSize;
}
knownPanels = newKnownPanels; // Will now contain all panels needed for display. All panels that were in the map, but are no longer needed, are now gone forever.
// Layout.
container.add(scrollBar);
for (JPanel panel : newKnownPanels.values()) {
container.add(panel);
panel.revalidate();
}
container.repaint(); // required
}
/**
* @return the correct width&height a contained JPanel needs to have. Is applied by update() automatically.
*/
public Dimension getPanelSize() {
if (orientation == FPLOrientation.HORIZONTAL) {
return new Dimension(panelSize,
lastKnownContainerSize.height - (scrollBar.isVisible() ? scrollBarWidth : 0));
} else {
return new Dimension(lastKnownContainerSize.width - (scrollBar.isVisible() ? scrollBarWidth : 0),
panelSize);
}
}
/**
* @return 0 to 1, expressing position of scroll bar handle.
*/
public double getScrollBarPosRatio() {
final int scrollRangeSize = Integer.MAX_VALUE - scrollBar.getVisibleAmount(); // Which should really be named getExtent(). Or rather the other way round.
return scrollBar.getValue() / (double) scrollRangeSize;
}
}