java - 编辑 JComboBox 中的选定项目
问题描述
我的目标是创建一个长度由另一个组件控制的列表,其中每个项目的值都可以编辑。
我的尝试使用具有一定数量元素的可编辑 JComboBox。但是,在我下面的代码中,所选索引不断更改为 -1,这不允许我修改该项目。有没有办法使用 JComboBox 选择和编辑项目?
//cb is a JComboBox with elements of type ComboItem. idx is defined elsewhere.
cb.addItemListener(new ItemListener() {
@SuppressWarnings("unchecked")
@Override
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
idx = ((JComboBox<ComboItem>) e.getSource()).getSelectedIndex();
System.out.println("idx:"+idx);
}
});
//Pressing enter should commit changes.
cb.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyChar() == KeyEvent.VK_ENTER) {
String parse = ((JTextComponent) cb.getEditor().getEditorComponent()).getText();
parse = parse.substring(parse.lastIndexOf(":")+1).replaceAll("[^0-9]+", ""); //Processes edits.
cb.getItemAt(idx).change("Layer "+idx, Integer.parseInt(parse)); //This method should change the
System.out.println("selected item:"+cb.getSelectedItem()); // data for each item.
}
}
});
//Editing the text in the JComboBox and pressing the enter key should update the selected item.
JComboBox 不是必需的,因此如果它是此任务的更好选择,请随意建议不同的组件。
解决方案
经过一天的反复试验,我终于提出了一个可行的解决方案。我没有使用JComboBox
可能不是为执行所需任务而设计的 a ,而是制作了 a ,每次按下按钮时都会JScrollPane
添加一个子项。JPanel
每个面板都有一个可以自定义的文本字段对象和一个删除它的按钮。就我而言,我添加了一个DocumentFilter
允许正 < 5 位整数的值。
我无法弄清楚如何在滚动条出现之前删除添加的面板之间的间距,所以如果你有一个解决方案,请评论一个解决方案。另外,如果还有其他可以改进的地方,也请评论这些建议。
滚动面板
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.JLabel;
@SuppressWarnings("serial")
public class TestScrollPane extends JPanel {
private int w,h;
private JPanel content;
private JScrollPane scroll;
private JButton add;
private JLabel getTextLabel;
private JButton getTextBtn;
/**
* Create the panel.
*/
public TestScrollPane(int width, int height) {
setLayout(null);
w = width; h = height;
scroll = new JScrollPane();
scroll.setBounds(0, 0, w, h);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
add(scroll);
content = new JPanel();
scroll.setViewportView(content);
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
add = new JButton("+");
add.setBounds(0, h, 89, 23);
add(add);
getTextLabel = new JLabel("");
getTextLabel.setBounds(10, 425, 215, 14);
add(getTextLabel);
getTextBtn = new JButton("Get Text");
getTextBtn.setBounds(225, 425, 215, 14);
getTextBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String a[] = getText(),
b = "";
b += "[";
for(int i = 0; i < a.length - 1; i++)
b += a[i]+", ";
b += a[a.length-1]+"]";
System.out.println(b);
getTextLabel.setText(b);
}
});
add(getTextBtn);
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("adding "+content.getComponentCount());
content.add(new ScrollItem(content.getComponentCount()));
validate();
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(w, h);
}
public String[] getText() {
String out[] = new String[content.getComponentCount()],s;
for(int i = 0; i < out.length; i++)
out[i] = (s = ((ScrollItem) content.getComponent(i)).out) == null ? "0" : s;
return out;
}
private class ScrollItem extends JPanel {
private JTextField text;
private JButton del;
private int idx;
private String out;
public ScrollItem(int id) {
idx = id;
setBounds(0, idx*20, w-5, 20);
setLayout(null);
text = new JTextField();
text.setBounds(0, 0, (w-5)*3/4, 20);
text.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
out = text.getText();
}
});
AbstractDocument d = (AbstractDocument) text.getDocument();
d.setDocumentFilter(new TextFilter(4));
del = new JButton("X");
del.setBounds((w-5)*3/4, 0, (w-5)/4, 20);
del.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.remove(idx);
for(int i = idx; i < content.getComponentCount(); i++)
((ScrollItem) content.getComponent(i)).moveUp();
content.validate();
content.repaint();
System.out.println("Removed "+idx);
}
});
add(text);
add(del);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(w-5, 20);
}
public void moveUp() {
idx--;
content.validate();
content.repaint();
}
}
private class TextFilter extends DocumentFilter {
private int max;
public TextFilter(int maxChars) {
max = maxChars;
}
@Override
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a) throws BadLocationException {
System.out.println("insert");
if ((fb.getDocument().getLength() + str.length()) <= max && str.matches("\\d+"))
super.insertString(fb, offs, str, a);
else
showError("Length: "+((fb.getDocument().getLength() + str.length()) <= max)+" | Text: "+str.matches("\\d+")+" | Str: "+str);
}
@Override
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) throws BadLocationException {
System.out.println("replace");
if ((fb.getDocument().getLength() + str.length() - length) <= max && str.matches("\\d+"))
super.replace(fb, offs, length, str, a);
else
showError("Length: "+((fb.getDocument().getLength() + str.length() - length) <= max)+" | Text: "+str.matches("\\d+")+" | Str: "+str);
}
private void showError(String cause) {
JOptionPane.showMessageDialog(null, cause);
}
}
}
测试窗口
import java.awt.EventQueue;
import javax.swing.JFrame;
public class TestWindow {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestWindow window = new TestWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public TestWindow() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 435, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestScrollPane(430, 247));
}
}
推荐阅读
- php - php 中缺少类 php_com_dotnet
- ios - UICollectionView 重新加载数据而不调用 reloadData()
- javascript - 保存平面列表中的参数导航,并将其显示在另一个屏幕上
- javascript - ReactJS 中的异步函数阻塞组件
- docx4j - 通过 docx4j-export-fo 在 TOC 中获取错误的页码
- .net - 使用 CefSharp 从 JavaScript 调用 C# 是否有一种不那么痛苦的方法?
- javascript - 从另一个对象中省略具有某些深度值的对象
- vue.js - 如何防止chartjs上的标签截断?
- jenkins - 参数化构建不适用于 Pipeline AWS Steps s3 上传插件
- google-apps-script - Send notification to specific email from column M only when value 1 in column L is chosen