我有一个我正在处理的程序,它接受输入名称并创建JLabel并将它们填充到ArrayList中。当用户单击“开始”按钮时,JLabel将填充在左侧JPanel中。我一直尝试使用DnD来允许用户拖动并重新排序左侧面板中的标签。到目前为止,我只能将文本从一个标签复制到另一个标签。我的目标是在列表中向上或向下拖动标签,并根据它在JPanel中放置的位置,使剩余的JLabel在面板中向上或向下移动。我在面板上使用FlowLayout,标签宽度足以创建垂直对齐。这是我的代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.TransferHandler;
import javax.swing.border.Border;
public class Gui extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private ArrayList<JLabel> players = new ArrayList<JLabel>();
private ArrayList<JLabel> monsters = new ArrayList<JLabel>();
private JButton addPlayer = new JButton();
private JButton removePlayer = new JButton();
private JButton addMonster = new JButton();
private JButton removeMonster = new JButton();
private JTextField name = new JTextField();
private JPanel listPanel = new JPanel();
private JPanel buttonPanel = new JPanel();
private JButton encounter = new JButton();
private JButton begin = new JButton();
//private JButton remove;// = new JButton();
int x_pressed;
int y_pressed;
public Gui(){
super("D&D Initiative");
final Container container = getContentPane();
container.setLayout(new FlowLayout()); //change to GridBagLayout
container.setPreferredSize(new Dimension(800, 500));
listPanel.setPreferredSize(new Dimension(600, 500));
listPanel.setBackground(Color.BLUE);
listPanel.setOpaque(true);
buttonPanel.setPreferredSize(new Dimension(200,500));
buttonPanel.setBackground(Color.GREEN);
buttonPanel.setOpaque(true);
Dimension size = new Dimension(190,30);
name.setPreferredSize(new Dimension(190,30));
addPlayer.setText("Add Player");
removePlayer.setText("Remove Player");
addPlayer.setPreferredSize(size);
removePlayer.setPreferredSize(size);
addMonster.setText("Add Monster");
removeMonster.setText("Remove Monster");
addMonster.setPreferredSize(size);
removeMonster.setPreferredSize(size);
begin.setText("Begin Encounter");
begin.setPreferredSize(size);
buttonPanel.add(name);
buttonPanel.add(addPlayer);
buttonPanel.add(addMonster);
buttonPanel.add(removePlayer);
buttonPanel.add(removeMonster);
buttonPanel.add(begin);
final Border paddingBorder = BorderFactory.createEmptyBorder(0,10,0,0);
addPlayer.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
if(name.getText().compareToIgnoreCase("") != 0){
final JLabel temp=new JLabel();
temp.setPreferredSize(new Dimension(590,50));
temp.setText(name.getText());
temp.setBackground(Color.GRAY);
temp.setForeground(Color.WHITE);
temp.setOpaque(true);
temp.setLayout(new BorderLayout());
temp.setBorder(BorderFactory.createCompoundBorder(null,paddingBorder));
//bPane.setPreferredSize(new Dimension(100,temp.getHeight()));
JButton remove = new JButton();
remove.setText("Remove");
remove.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("Count of listeners: " + ((JButton) e.getSource()).getActionListeners().length); //debugging
listPanel.remove(temp);
listPanel.revalidate();
System.out.println("remove");
listPanel.repaint();
}
});
temp.add(remove, BorderLayout.EAST);
MouseListener listener = new DragMouseAdapter();
temp.setTransferHandler(new TransferHandler("text"));
temp.addMouseListener(listener);
players.add(temp);
name.setText("");
name.requestFocusInWindow();
}else{
//throw error
}
}
});
begin.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
for(int i=0;i<players.size();i++){
JLabel h = players.get(i);
h.setMinimumSize(new Dimension(590,30));
int s = container.getHeight()/players.size();
if(s < 50){
h.setPreferredSize(new Dimension(590,listPanel.getHeight()/(players.size()+1)));
}else{
h.setPreferredSize(new Dimension(590,30));
}
listPanel.add(h, new Integer(1), 0);
}
listPanel.revalidate();
}
});
container.add(listPanel);
container.add(buttonPanel);
pack(); // pack the frame to fit the container inside
setLocation(150, 150); // set the location on the monitor
setVisible(true);
setResizable(false);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Gui application = new Gui();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//start of drag and drop
class DragMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
System.out.println(c);
}
}
仍有一些事情来自不同的尝试(例如未使用的变量)。
答案 0 :(得分:1)
考虑使用JList
而不是创建自己的标签组件,这有很多简洁的功能,只会让你的生活更简单,比如拖放......
有关详细信息,请查看How to Use Lists。
拖放是一个相当复杂的API,开始时可能会让人感到困惑,因为包含“传输API”并没有帮助,这只会增加混乱。
话虽如此,“转移API”正是您在这种情况下所寻找的......
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.activation.ActivationDataFlavor;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DragList {
public static void main(String[] args) {
new DragList();
}
public DragList() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DefaultListModel<String> listModel = new DefaultListModel<>();
listModel.addElement("Clara Holmes");
listModel.addElement("Bill Moss");
listModel.addElement("Della Reeves");
listModel.addElement("Lloyd Gross");
listModel.addElement("Cecilia Floyd");
listModel.addElement("Delia Cummings");
listModel.addElement("Tommy Benson");
listModel.addElement("Kirk Casey");
listModel.addElement("Chester Manning");
listModel.addElement("Elsa Chapman");
JList namesList = new JList(listModel);
namesList.setDragEnabled(true);
namesList.setDropMode(DropMode.ON_OR_INSERT);
namesList.setTransferHandler(new ListItemTransferHandler());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(namesList));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ListItemTransferHandler extends TransferHandler {
private DataFlavor flavor;
public ListItemTransferHandler() {
super("ListMove");
flavor = new ActivationDataFlavor(int[].class, DataFlavor.javaJVMLocalObjectMimeType, "List of values");
}
@Override
protected Transferable createTransferable(JComponent c) {
System.out.println("createTransferable");
JList list = (JList) c;
DefaultListModel<String> model = (DefaultListModel<String>) list.getModel();
int[] selectedValues = list.getSelectedIndices();
List<ValuePair> values = new ArrayList<>(selectedValues.length);
for (int index : selectedValues) {
values.add(new ValuePair(index, model.getElementAt(index)));
}
return new ListOfValues(values);
}
@Override
public boolean canImport(TransferSupport support) {
boolean canImport = support.isDrop() && support.isDataFlavorSupported(flavor);
return canImport;
}
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
@Override
public boolean importData(TransferSupport support) {
boolean imported = false;
if (canImport(support)) {
JList target = (JList) support.getComponent();
target.clearSelection();
JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
DefaultListModel<String> model = (DefaultListModel<String>) target.getModel();
int addIndex = dl.getIndex();
if (addIndex < 0 || addIndex >= model.size()) {
addIndex = model.size();
}
try {
List<ValuePair> values = (List<ValuePair>) support.getTransferable().getTransferData(flavor);
for (ValuePair vp : values) {
int index = vp.getIndex();
String value = model.get(index);
model.add(addIndex, value);
target.addSelectionInterval(addIndex, addIndex);
addIndex++;
}
imported = true;
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
return imported;
}
@Override
protected void exportDone(JComponent source, Transferable data, int action) {
if (action == MOVE) {
JList list = (JList) source;
DefaultListModel<String> model = (DefaultListModel<String>) list.getModel();
try {
// Get the list of values and sort in decending order
List<ValuePair> values = (List<ValuePair>) data.getTransferData(flavor);
Collections.sort(values, new Comparator<ValuePair>() {
@Override
public int compare(ValuePair o1, ValuePair o2) {
return o2.getIndex() - o1.getIndex();
}
});
// Loop through for each item...
for (ValuePair vp : values) {
// Get the "last known" index of the value...
String modelValue = model.get(vp.getIndex());
String value = vp.getValue();
int index = vp.getIndex();
// If the value no long resides at it's last location, we need to find it,
// we can't rely on contains, as there are two values of the same value...
if (modelValue != value) {
// Look behind us, only the length of the number of values that were previously selected...
int startIndex = Math.max(vp.getIndex() - values.size(), 0);
int endIndex = vp.getIndex();
index = getIndexFor(value, model, startIndex, endIndex);
if (index < 0) {
// Look forward, only the length of the number of values that were previously selected...
endIndex = Math.min(vp.getIndex() + values.size(), model.size() - 1);
startIndex = vp.getIndex();
index = getIndexFor(value, model, startIndex, endIndex);
}
}
if (index < 0) {
// We lost the item ??
throw new IOException("Missing value?");
} else {
model.remove(index);
}
}
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
}
protected int getIndexFor(String value, DefaultListModel<String> model, int startIndex, int endIndex) {
while (model.get(startIndex) != value && startIndex <= endIndex) {
startIndex++;
}
return model.get(startIndex) == value ? startIndex : -1;
}
public class ValuePair {
private int index;
private String value;
public ValuePair(int index, String value) {
this.index = index;
this.value = value;
}
public int getIndex() {
return index;
}
public String getValue() {
return value;
}
}
public class ListOfValues implements Transferable {
private List<ValuePair> values;
public ListOfValues(List<ValuePair> values) {
this.values = values;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{flavor};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return Arrays.asList(getTransferDataFlavors()).contains(flavor);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return values;
}
}
}
}
请查看Demo - BasicDnD以获取其他演示,以及有关传输API的更多信息。