下午好!有必要從事件串列(水平)中創建一個串列(垂直)。至少有2個問題:
- 事件串列區域(水平滾動)擴展到面板邊界之外。顯然,問題出在布局上,但我找不到正確的組合;
- 水平滾動不起作用(可能是由于上述問題),并且每組事件的滾動條必須不同。
import ivank.components.EventAdd;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class WindowAddCameras extends JFrame {
public static final List<JPanel> labels = new ArrayList<JPanel>();
public WindowAddCameras() {
super("Добавить камеру");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panelButton = new JPanel();
JButton addButton = new JButton(" ");
addButton.setFocusable(false);
panelButton.add(addButton);
JButton remButton = new JButton("-");
remButton.setFocusable(false);
panelButton.add(remButton);
JPanel externalPanel = new JPanel();
externalPanel.setLayout(new BorderLayout(0, 0));
JScrollPane scrollPaneGroupEvent = new JScrollPane(
externalPanel,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
JPanel internalPanel = new JPanel();
internalPanel.setLayout(new GridLayout(0, 1, 0, 0));
JScrollPane scrollPaneEvent = new JScrollPane(internalPanel);
scrollPaneEvent.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
scrollPaneEvent.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
externalPanel.add(scrollPaneEvent, BorderLayout.NORTH);
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int number = labels.size() 1;
EventAdd eventAdd = new EventAdd();
Dimension labelSize = new Dimension(80, 80);
//add event to group event
Random rand = new Random();
for(int a = 0; a < 20; a ) {
//random color border event for TEST
Color randomColor = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
eventAdd.createEventLabel("Камера " number, labelSize, randomColor);
}
labels.add(eventAdd);
internalPanel.add(eventAdd, BorderLayout.NORTH);
scrollPaneGroupEvent.revalidate();
}
});
remButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(labels.size() > 0) {
int index = labels.size() - 1;
JPanel panel = labels.remove(index);
internalPanel.remove(panel);
internalPanel.repaint();
scrollPaneGroupEvent.revalidate();
}
}
});
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panelButton, BorderLayout.NORTH);
this.getContentPane().add(scrollPaneGroupEvent, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(600, 400));
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
package ivank.components;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class EventAdd extends JPanel {
public EventAdd() {
super(new FlowLayout(FlowLayout.LEFT));
}
public JComponent createEventLabel(String name, Dimension labelSize, Color randomColor) {
this.setBorder(BorderFactory.createTitledBorder(name));
JLabel label = new JLabel();
label.setPreferredSize(labelSize);
label.setHorizontalAlignment(JLabel.CENTER);
label.setBorder(BorderFactory.createLineBorder(randomColor, 5));
this.add(label);
return label;
}
}
我所擁有的:在此處輸入影像描述 我想要獲得的:在此處輸入影像描述
uj5u.com熱心網友回復:
另一個滾動區域內的滾動區域是用戶界面反模式(反設計?)。應該避免。
我將創建一個基于垂直 BoxLayout 的可滾動面板:
public class WindowAddCameras extends JFrame {
private static final long serialVersionUID = 1;
public static final List<JPanel> labels = new ArrayList<JPanel>();
private static class CameraListPanel
extends JPanel
implements Scrollable {
private static final long serialVersionUID = 1;
CameraListPanel() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation,
int direction) {
return getScrollableIncrement(30,
visibleRect, orientation, direction);
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation,
int direction) {
return getScrollableIncrement(
orientation == SwingConstants.HORIZONTAL ?
getWidth() : getHeight(),
visibleRect, orientation, direction);
}
private int getScrollableIncrement(int amount,
Rectangle visibleRect,
int orientation,
int direction) {
if (orientation == SwingConstants.HORIZONTAL) {
return Math.min(amount, direction < 0 ? visibleRect.x :
getWidth() - (visibleRect.x visibleRect.width));
} else {
return Math.min(amount, direction < 0 ? visibleRect.y :
getHeight() - (visibleRect.y visibleRect.height));
}
}
}
public WindowAddCameras() {
super("Добавить камеру");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panelButton = new JPanel();
JButton addButton = new JButton(" ");
addButton.setFocusable(false);
panelButton.add(addButton);
JButton remButton = new JButton("-");
remButton.setFocusable(false);
panelButton.add(remButton);
JPanel camerasPanel = new CameraListPanel();
JScrollPane scrollPaneGroupEvent = new JScrollPane(camerasPanel);
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int number = labels.size() 1;
EventAdd eventAdd = new EventAdd();
Dimension labelSize = new Dimension(80, 80);
//add event to group event
Random rand = new Random();
for(int a = 0; a < 20; a ) {
//random color border event for TEST
Color randomColor = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
eventAdd.createEventLabel("Камера " number, labelSize, randomColor);
}
labels.add(eventAdd);
camerasPanel.add(eventAdd);
scrollPaneGroupEvent.revalidate();
}
});
remButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(labels.size() > 0) {
int index = labels.size() - 1;
JPanel panel = labels.remove(index);
camerasPanel.remove(panel);
camerasPanel.repaint();
scrollPaneGroupEvent.revalidate();
}
}
});
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panelButton, BorderLayout.NORTH);
this.getContentPane().add(scrollPaneGroupEvent, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(600, 400));
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new WindowAddCameras());
}
}
CameraListPanel 類主要是一個基本的可滾動面板;重要的部分是getScrollableTracksViewportWidth()回傳 true,這將導致面板的寬度與任何 JScrollPane 視口的寬度相匹配。這消除了對水平滾動條的任何需要。
當然,您會希望以某種方式顯示所有子組件。為此,我會讓 EventAdd 類計算一個可以容納所有孩子的高度:
public class EventAdd extends JPanel {
private static final long serialVersionUID = 1;
private final FlowLayout layout;
public EventAdd() {
layout = new FlowLayout(FlowLayout.LEFT);
setLayout(layout);
}
@Override
public Dimension getPreferredSize() {
Rectangle childSize = new Rectangle();
Component[] children = getComponents();
for (Component child : children) {
childSize.add(new Rectangle(child.getPreferredSize()));
}
Insets insets = getInsets();
int hgap = layout.getHgap();
int vgap = layout.getVgap();
int childWidth = childSize.width hgap;
Dimension size;
if (getParent() == null) {
size = new Dimension(
children.length * (childWidth * hgap) hgap,
childSize.height vgap * 2);
} else {
int width = getParent().getWidth();
width -= insets.left insets.right;
int childrenPerRow =
childWidth == 0 ? 0 : (width - hgap) / childWidth;
int rows;
if (childrenPerRow == 0) {
rows = 0;
} else {
rows = children.length / childrenPerRow;
if (children.length % childrenPerRow > 0) {
rows ;
}
}
size = new Dimension(width,
vgap rows * (childSize.height vgap));
}
size.width = insets.left insets.right;
size.height = insets.top insets.bottom;
return size;
}
uj5u.com熱心網友回復:
您可以只用一個 JScrollPane 進行水平和垂直滾動。但是您需要的是呈現您的內容的底層 JComponent。然而,這可以是一個JPanel,它可以根據您的需要延伸。
看看如何使用 ScrollPanes。
uj5u.com熱心網友回復:
JScrollPane 必須使用 jscrollpane 方法setViewportView分配一個 JViewport 。您還應該給它一個滾動條策略 setVerticalScrollBarPolicy setHorizo??ntalScrollBarPolicy 該策略int是前面兩個方法的類的一部分,被稱為“常量欄位值”,請參閱 JScrollPane 的 API 檔案。要展開 JScrollPane,請將其放入帶有 BorderLayout 的 JPanel并且在具有 JScrollPane 的特定面板中沒有其他元素。在 JPanel 上使用方法 setMinimumSize 和 setPreferredSize 和 setSize 或主視窗中的 BoxLayout(雖然我認為主視窗有一個特殊的布局,所以如果是這樣,則不需要 boxlayout)或堆疊中的更高級別面板,或者只是 setPreferredSize對于 JScrollPane。一個 jscrollpane 有一個由它的“ setView ”方法設定的視圖,它的視圖是一個 java.awt.Component 注意:一個JComponent 是一個java.awt.Component,任何 javax swing J 面板或 J 視口都是層次結構的 java.awt.Component。注意 jviewport 是 java.awt.Component 所以得到一個 jscrollpane.setViewportView 添加 jviewport 參考 jviewport.setView 作為 JPanel 與 BorderLayout ,添加另一個面板開始添加其他組件,但記住給所有 Jcomponents 一個 .preferredSize 方法使用. 如果您在 javax.swing.JList<E> 和 javax.swing.DefaultListModel<E> 之后,則 JList 必須放置在帶有 BorderLayout 的 JPanel 中,或者更困難的系統是 java.awt.GridBagLayout 然后放在 jscrollpane 中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/508248.html
