I have a JTree with DefaultMutableTreeNodes. On some levels these nodes were initialized with my own serializable objects. In total there are two different types of objects (called "Step" and "Order"). I want to be able to drop only nodes which were initialized with either of these two objects. Any other nodes which are just Strings shouldn't be droppable. One "Order" can contain many "Steps". I want to be able to drag them onto a JPanel were they get inserted into a JList. If a "Order" was dropped all of the "Steps" are supposed to be inserted, if only a "Step" was dropped only that particular "Step" is supposed to be inserted.
SSCCE below!
JTree:
tree = new JTree();
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.setDragEnabled(true);
tree.setModel(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JPanel:
public class TablePanel extends JPanel
{
private static final long serialVersionUID = 3216206960422611905L;
public TablePanel()
{
super();
setLayout(new MigLayout("", "[grow]", "[][grow]"));
JProgressBar progressBar = new JProgressBar();
progressBar.setMaximum(28800); // 8 hours in seconds
progressBar.setStringPainted(true);
add(progressBar, "cell 0 0,growx");
DefaultListModel<Step> listModel = new DefaultListModel<Step>();
JList<Step> list = new JList<Step>();
list.setModel(listModel);
setDropTarget(new DropTarget(this, TransferHandler.COPY, new DropTargetAdapter()
{
private int index = 0;
private int amount = 0;
#Override
public void drop(DropTargetDropEvent dtde)
{
amount = 0;
index = 0;
}
#Override
public void dragExit(DropTargetEvent dte)
{
if (listModel.size() > 0)
{
if (amount == 1)
{
listModel.remove(index);
}
else
{
for (int i = 0; i < amount; i++)
{
listModel.remove(index + i);
}
}
amount = 0;
}
}
#Override
public void dragEnter(DropTargetDragEvent dtde)
{
try
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(Order.auftragFlavor))
{
Order a = (Order) tr.getTransferData(Order.auftragFlavor); // Wrong, how do I get this?
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = a.getSteps().size();
}
else if (dtde.isDataFlavorSupported(Step.arbeitsgangFlavor))
{
Step ag = (Step) tr.getTransferData(Step.arbeitsgangFlavor);
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = 1;
}
else
{
dtde.rejectDrag();
}
}
catch (Exception e)
{
e.printStackTrace();
dtde.rejectDrag();
}
}
#Override
public void dragOver(DropTargetDragEvent dtde)
{
try
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(Order.auftragFlavor))
{
Order a = (Order) tr.getTransferData(Order.auftragFlavor); // Wrong, how do I get this?
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = a.getSteps().size();
}
else if (dtde.isDataFlavorSupported(Step.arbeitsgangFlavor))
{
Step ag = (Step) tr.getTransferData(Step.arbeitsgangFlavor);
dtde.acceptDrag(DnDConstants.ACTION_COPY);
amount = 1;
}
else dtde.rejectDrag();
}
catch (Exception e)
{
e.printStackTrace();
dtde.rejectDrag();
}
}
}, true, null));
add(list, "cell 0 1,grow");
}
}
When you are dragging over the JList, then the data should be inserted into the list to give the user feedback and the possibility to place it in the list. If not dropped, it should be removed again.
How can drag and drop my objects onto the JPanel, but not nodes which are just Strings?
EDIT:
With (String) tr.getTransferData(DataFlavor.stringFlavor) I am able to get the label of the node, but this is not really helpfull, because I don't know if it was a Order, Step or just a string node.
EDIT2 SSCCE:
public class Test extends JFrame
{
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
Test window = new Test();
window.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
public Test()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode string1 = new DefaultMutableTreeNode("String 1");
DefaultMutableTreeNode order1 = new DefaultMutableTreeNode(new ParentObject());
order1.add(new DefaultMutableTreeNode(new ChildObject()));
order1.add(new DefaultMutableTreeNode(new ChildObject()));
string1.add(order1);
root.add(string1);
DefaultTreeModel model = new DefaultTreeModel(root);
JTree tree = new JTree(model);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.setDragEnabled(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
contentPane.add(tree, BorderLayout.WEST);
CustPanel panel = new CustPanel();
contentPane.add(panel, BorderLayout.CENTER);
}
}
class CustPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public CustPanel()
{
super();
setLayout(new MigLayout("", "[grow]", "[][grow]"));
JProgressBar progressBar = new JProgressBar();
add(progressBar, "cell 0 0,growx");
DefaultListModel<ChildObject> listModel = new DefaultListModel<ChildObject>();
JList<ChildObject> list = new JList<ChildObject>();
list.setModel(listModel);
setDropTarget(new DropTarget(this, TransferHandler.COPY, new DropTargetAdapter()
{
#Override
public void drop(DropTargetDropEvent dtde)
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
}
catch (UnsupportedFlavorException | IOException e)
{
e.printStackTrace();
}
}
}
#Override
public void dragExit(DropTargetEvent dte)
{
}
#Override
public void dragEnter(DropTargetDragEvent dtde)
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
}
catch (UnsupportedFlavorException | IOException e)
{
e.printStackTrace();
}
}
}
#Override
public void dragOver(DropTargetDragEvent dtde)
{
Transferable tr = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
}
catch (UnsupportedFlavorException | IOException e)
{
e.printStackTrace();
}
}
}
}, true, null));
add(list, "cell 0 1,grow");
}
}
class ParentObject implements Serializable
{
private static final long serialVersionUID = 1279985471254050120L;
public ArrayList<ChildObject> getChildren()
{
return new ArrayList<ChildObject>();
}
#Override
public String toString()
{
return "ParentObject";
}
}
class ChildObject implements Serializable
{
private static final long serialVersionUID = -5833860202973614790L;
#Override
public String toString()
{
return "ChildObject";
}
}
but not nodes which are just Strings?
You might be able to use a TransferHandler#createTransferable(...) method to get the DefaultMutableTreeNode.
TransferHandler#createTransferable(JComponent) (Java Platform SE 8 )
Demo - DropDemo (The Java™ Tutorials > Creating a GUI With JFC/Swing > Drag and Drop and Data Transfer)
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import java.util.*;
import javax.activation.*;
import javax.swing.*;
import javax.swing.tree.*;
public class Test2 {
public JComponent makeUI() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode string1 = new DefaultMutableTreeNode("String 1");
DefaultMutableTreeNode order1 = new DefaultMutableTreeNode(new ParentObject());
order1.add(new DefaultMutableTreeNode(new ChildObject()));
order1.add(new DefaultMutableTreeNode(new ChildObject()));
string1.add(order1);
root.add(string1);
DefaultTreeModel model = new DefaultTreeModel(root);
JTree tree = new JTree(model);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setTransferHandler(new TreeTransferHandler());
tree.setDragEnabled(true);
DefaultListModel<ChildObject> listModel = new DefaultListModel<ChildObject>();
JList<ChildObject> list = new JList<ChildObject>();
list.setModel(listModel);
list.setDropTarget(new DropTarget(list, TransferHandler.COPY, new DropTargetAdapter() {
private void print(Transferable tr) {
try {
Object node = tr.getTransferData(TreeTransferHandler.FLAVOR);
System.out.println(node); // I want the actual object
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
#Override
public void drop(DropTargetDropEvent dtde) {
if (dtde.isDataFlavorSupported(TreeTransferHandler.FLAVOR)) {
print(dtde.getTransferable());
}
}
#Override public void dragExit(DropTargetEvent dte) {}
#Override public void dragEnter(DropTargetDragEvent dtde) {}
#Override public void dragOver(DropTargetDragEvent dtde) {}
}, true, null));
JPanel contentPane = new JPanel(new GridLayout(1, 2));
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
contentPane.add(new JScrollPane(tree), BorderLayout.WEST);
contentPane.add(new JScrollPane(list), BorderLayout.CENTER);
return contentPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
try {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new Test2().makeUI());
f.setBounds(100, 100, 450, 300);
f.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
class ParentObject implements Serializable {
public ArrayList<ChildObject> getChildren() {
return new ArrayList<ChildObject>();
}
#Override
public String toString() {
return "ParentObject";
}
}
class ChildObject implements Serializable {
#Override
public String toString() {
return "ChildObject";
}
}
class TreeTransferHandler extends TransferHandler {
public static final DataFlavor FLAVOR = new ActivationDataFlavor(
DefaultMutableTreeNode[].class,
DataFlavor.javaJVMLocalObjectMimeType,
"Array of DefaultMutableTreeNode");
#Override protected Transferable createTransferable(JComponent c) {
JTree source = (JTree) c;
TreePath[] paths = source.getSelectionPaths();
DefaultMutableTreeNode[] nodes = new DefaultMutableTreeNode[paths.length];
for (int i = 0; i < paths.length; i++) {
nodes[i] = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
}
return new DataHandler(nodes, FLAVOR.getMimeType());
}
#Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
}
Related
I am working on a school project using BlueJay and I have created two classes in package Logic which are the Game class, and the VectorGames class.
In my package GUI, I created a class called AddGame and ViewGame class.
The issue that I have encountered is that, when I click the Save Button on Addgame, it saves the file only once. When I try to save it doesn't do or say anything it just stays there returning nothing. Another issue encountered is that on ViewGame, the gameType column is remaining empty ( this is from combo type box )
AddGame code :
package GUI;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import Logic.*;
public class AddGame extends JFrame implements ActionListener{
private JPanel north, south, east, west, center;
private JLabel titleLabel, westLabel, eastLabel;
private JTextField gameNameFld, gameKeyFld;
private JComboBox gameTypeCombo;
private JButton saveButton, clearButton;
private VectorGames vg;
public AddGame(){
super("Adding a Game");
this.setLayout(new BorderLayout());
vg = new VectorGames();
vg.readFromFile();
//north panel
north = new JPanel();
this.add(north,BorderLayout.NORTH);
titleLabel = new JLabel("Add a game below");
titleLabel.setFont(new Font("Verdana",Font.BOLD,20));
titleLabel.setForeground(Color.black);
north.add(titleLabel);
//west and east panels
west = new JPanel();
east = new JPanel();
this.add(west, BorderLayout.WEST);
this.add(east, BorderLayout.EAST);
westLabel = new JLabel(" ");
eastLabel = new JLabel(" ");
west.add(westLabel);
east.add(eastLabel);
//center panel
center = new JPanel();
this.add(center, BorderLayout.CENTER);
center.setLayout(new GridLayout(4,2,0,20));
gameNameFld = new JTextField();
gameKeyFld = new JTextField();
gameTypeCombo = new JComboBox();
gameTypeCombo.setModel(new DefaultComboBoxModel(new String[]
{"<--Select-->", "Arcade", "Puzzle", "Adventure", "Shooter", "Roleplay"}));
center.add(createLabel("Game Name"));
center.add(gameNameFld);
center.add(createLabel("Game Key"));
center.add(gameKeyFld);
center.add(createLabel("Game Type"));
center.add(gameTypeCombo);
//south panel
south = new JPanel();
south.setLayout(new FlowLayout());
this.add(south, BorderLayout.SOUTH);
clearButton = new JButton("Clear");
south.add(clearButton);
clearButton.addActionListener(this);
saveButton = new JButton("Save");
south.add(saveButton);
saveButton.addActionListener(this);
this.setSize(300,400);
this.setLocation(50,50);
this.setVisible(true);
}
private JLabel createLabel(String title){
return new JLabel(title);
}
private void clearFields(){
gameNameFld.setText("");
gameKeyFld.setText("");
gameTypeCombo.setSelectedIndex(0);
}
private boolean validateForm(){
boolean flag = false;
if(gameNameFld.getText().equals("")||gameKeyFld.getText().equals("")||
gameTypeCombo.getSelectedIndex()==0){
flag = true;
}
return flag;
}
public void actionPerformed(ActionEvent event){
if (event.getSource() == clearButton){
clearFields();
}
if(event.getSource() == saveButton){
if(validateForm() == true){
JOptionPane.showMessageDialog(null,"You have empty fields",
"Empty Fields", JOptionPane.ERROR_MESSAGE);
} else if(vg.checkGamebyGameKey(gameKeyFld.getText()) == true){
JOptionPane.showMessageDialog(null,"Game Key already exists!",
"Game Key Check", JOptionPane.ERROR_MESSAGE);
} else {
Game tempGame = new Game(gameNameFld.getText(),gameKeyFld.getText(),
(String)gameTypeCombo.getSelectedItem());
vg.addGame(tempGame);
vg.saveToFile();
JOptionPane.showMessageDialog(null, "Game added successfully!", "Adding a Game",
JOptionPane.INFORMATION_MESSAGE);
clearFields();
}
}
}
}
ViewGame code:
package GUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import Logic.*;
public class ViewGame extends JFrame {
private JTable table;
private VectorGames vg;
public ViewGame(){
super("Viewing Games by Name");
this.setLayout(new BorderLayout());
vg = new VectorGames();
vg.readFromFile();
vg.sortGamesByName();
int numOfGames = vg.getVectorSize();
int count = 0;
Game tempGame = new Game();
String[] tableHeader = {"Game Name", "Game Type", "Game Key"};
Object [][] tableContent = new Object[numOfGames][3];
for(int i = 0; i < numOfGames; i++){
tempGame = vg.getGamesByIndex(count);
tableContent[i][0] = tempGame.getGameName();
tableContent[i][2] = tempGame.getGameType();
tableContent[i][1] = tempGame.getGameKey();
}
table = new JTable (tableContent, tableHeader);
JScrollPane scrollPane = new JScrollPane(table);
table.setPreferredScrollableViewportSize(new Dimension(500, 400));
this.add(table.getTableHeader(), BorderLayout.NORTH);
this.add(table, BorderLayout.CENTER);
this.setSize(500,600);
this.setLocation(100,50);
this.setVisible(true);
}
}
Game code:
package Logic;
import java.io.*;
public class Game implements Serializable{ // Using serializable to allow easy save and read access
//Initializing variables related to Game
private String gameName, gameKey, gameType;
//Creating a constructor with the parameters for class Games
public Game(String gameName, String gamekey, String gameType){
setGameName(gameName);
setGameKey(gameKey);
setGameType(gameType);
}
//Setting up a parameterless constructor for class Games
public Game(){
}
public String getGameName(){//Get Method for gameName
return gameName;
}
public String getGameKey(){//Get Method for gameKey
return gameKey;
}
public String getGameType(){//Get Method for gameType
return gameType;
}
public void setGameName(String gameName){//Set Method for gameName
this.gameName = gameName;
}
public void setGameKey(String gameKey){//Set Method for gameKey
this.gameKey = gameKey;
}
public void setGameType(String gameType){//Set Method for gameType
this.gameType = gameType;
}
public String toString(){
return "Game Name : " + gameName + "\nGame Key : "
+ gameKey + "\nGame Type ; " + gameType;
}
}
VectorGames code:
package Logic;
import java.util.*;
import java.io.*;
import java.lang.*;
public class VectorGames extends IOException{
/* Add a Game, Remove a Game, getVectorGame Size, print allGamesAvailable,
* saveToFile , searchGame and return boolean literal, searchGame and return
* client object, sort games, readFromFile.
*
*/
private Vector<Game> games;
public VectorGames(){
games = new Vector<Game>();
}
//Adding a Game
public void addGame(Game game){
games.add(game);
}
public void deleteGame(Game game){
games.remove(game);
}
public int getVectorSize(){
return games.size();
}
public void clearVector(){
games.clear();
}
public void printGames(){
for(Game tempGame : games){
System.out.println(tempGame.toString());
System.out.println("");
}
}
public Game getGamesByIndex(int i){
Game tempGame = new Game();
if (i < getVectorSize()){
tempGame = games.get(i);
}
return tempGame;
}
public void sortGamesByName(){
Game currentGame = new Game();
Game nextGame = new Game();
Game tempGame = new Game();
for(int i = 0; i < getVectorSize(); i++){
for(int j = 0; j < getVectorSize()-i-1; j++){
currentGame = games.elementAt(j);
nextGame = games.elementAt(j+1);
if(currentGame.getGameName().compareTo(nextGame.getGameName())>0){
tempGame = currentGame;
games.setElementAt(nextGame, j);
games.setElementAt(tempGame, j+1);
}
}
}
}
public boolean checkGamebyGameKey(String gameKey){
boolean flag = false;
for(Game tempGames : games){
if(tempGames .getGameKey().equals(gameKey)){
flag = true;
}
}
return flag;
}
public Game accessGameByGameName(String gameName){
Game foundGameName = new Game();
for(Game tempGames: games){
if(tempGames.getGameName().equals(gameName)){
foundGameName = tempGames;
}
}
return foundGameName;
}
public void saveToFile(){
try{
File f = new File("C:/Users/Denis/Desktop/GameStore/Databases","gameList.obj");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(games);
oos.flush();
oos.close();
}catch (IOException ioe){
System.err.println("Cannot write to file!");
}
}
public void readFromFile(){
try{
File f = new File("C:/Users/Denis/Desktop/GameStore/Databases","gameList.obj");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
games = (Vector<Game>) ois.readObject();
ois.close();
} catch (FileNotFoundException fnfe){
System.err.println("Cannot find file!");
}catch (IOException ioe){
System.err.println("Cannot read from file!");
}catch(ClassNotFoundException cnfe){
System.err.println("Client class cannot be found!");
}
}
}
Main class: GameCenter
public class GameCenter extends JFrame {
public static void main(String... args) {
SwingUtilities.invokeLater(() -> new GameCenter().setVisible(true));
}
public GameCenter() {
super("Game Center");
init();
}
private void init() {
setLayout(new BorderLayout(5, 5));
Model model = new Model();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.add("Add", new AddTabPanel(model));
tabbedPane.add("View", new ViewTabPanel(model));
add(tabbedPane, BorderLayout.CENTER);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(400, 500);
setMinimumSize(new Dimension(400, 500));
setResizable(false);
}
}
Game entity:
final class Game {
private static final Pattern RECORD = Pattern.compile("(?<key>.+)\\|(?<name>.+)\\|(?<type>.+)");
private final String name;
private final String key;
private final String type;
public static Game createFromRecord(String str) {
Matcher matcher = RECORD.matcher(str);
return matcher.matches() ? new Game(matcher.group("name"), matcher.group("key"), matcher.group("type")) : null;
}
public Game(String name, String key, String type) {
this.name = name;
this.key = key;
this.type = type;
}
public String getName() {
return name;
}
public String getKey() {
return key;
}
public String getType() {
return type;
}
public String serialize() {
return String.format("%s|%s|%s", key, name, type);
}
}
Table model:
final class Model extends AbstractTableModel {
private static final long serialVersionUID = 1858846855164475327L;
private final Map<String, Game> keyGame = new TreeMap<>();
private final List<Game> data = new ArrayList<>();
private File file;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public void add(String name, String key, String type) {
keyGame.put(key, new Game(name, key, type));
fireTableDataChanged();
}
public void remove(int rowIndex) {
keyGame.remove(data.get(rowIndex).getKey());
fireTableDataChanged();
}
public void save() throws IOException {
if (file == null)
return;
try (FileWriter out = new FileWriter(file, false)) {
for (Game game : keyGame.values())
out.write(game.serialize() + '\n');
}
}
public void read() throws IOException {
if (file == null)
return;
keyGame.clear();
for (String record : Files.readAllLines(file.toPath())) {
Game game = Game.createFromRecord(record);
if (game != null)
keyGame.put(game.getKey(), game);
}
fireTableDataChanged();
}
private enum Column {
NAME("Game Name", Game::getName),
KEY("Game Key", Game::getKey),
TYPE("Game Type", Game::getType);
private final String title;
private final Function<Game, Object> get;
Column(String title, Function<Game, Object> get) {
this.title = title;
this.get = get;
}
public Object getValue(Game game) {
return get.apply(game);
}
}
// ========== AbstractTableModel ==========
#Override
public void fireTableDataChanged() {
data.clear();
data.addAll(keyGame.values());
super.fireTableDataChanged();
}
// ========== TableModel ==========
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return Column.values().length;
}
#Override
public String getColumnName(int columnIndex) {
return Column.values()[columnIndex].title;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return Column.values()[columnIndex].getValue(data.get(rowIndex));
}
}
AddGame tab panel:
final class AddTabPanel extends JPanel implements ActionListener, DocumentListener {
private final Model model;
private final JTextField nameField = new JTextField();
private final JTextField keyField = new JTextField();
private final JLabel nameLabel = new JLabel("Game Name");
private final JLabel keyLabel = new JLabel("Game Key");
private final JLabel typeLabel = new JLabel("Game Type");
private final JComboBox<String> typeCombo = createGameTypeCombo();
private final JButton openButton = new JButton("Open");
private final JButton saveButton = new JButton("Save");
private final JButton clearButton = new JButton("Clear");
public AddTabPanel(Model model) {
this.model = model;
init();
addListeners();
}
private void init() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = createConstraints();
add(createTitlePanel(), gbc);
add(createMainPanel(), gbc);
add(createButtonPanel(), gbc);
gbc.weighty = 1;
add(Box.createVerticalGlue(), gbc);
onNameFieldChanged();
onKeyFieldChanged();
onTypeComboChanged();
}
private static JPanel createTitlePanel() {
JLabel label = new JLabel("Add a game below");
label.setFont(new Font("Verdana", Font.BOLD, 20));
JPanel panel = new JPanel();
panel.add(label);
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridLayout(3, 2, 5, 5));
panel.add(nameLabel);
panel.add(nameField);
panel.add(keyLabel);
panel.add(keyField);
panel.add(typeLabel);
panel.add(typeCombo);
return panel;
}
private static GridBagConstraints createConstraints() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
return gbc;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.add(clearButton);
panel.add(saveButton);
panel.add(openButton);
return panel;
}
private static JComboBox<String> createGameTypeCombo() {
JComboBox<String> combo = new JComboBox<>();
combo.setModel(new DefaultComboBoxModel<>(new String[] { "<--Select-->", "Arcade", "Puzzle", "Adventure", "Shooter", "Roleplay" }));
return combo;
}
private void addListeners() {
clearButton.addActionListener(this);
saveButton.addActionListener(this);
openButton.addActionListener(this);
nameField.getDocument().addDocumentListener(this);
keyField.getDocument().addDocumentListener(this);
typeCombo.addActionListener(this);
}
private void validateFields() {
String name = nameField.getText().trim();
String key = keyField.getText().trim();
int type = typeCombo.getSelectedIndex();
saveButton.setEnabled(!name.isEmpty() && !key.isEmpty() && type != 0);
}
private void onNameFieldChanged() {
nameLabel.setForeground(nameField.getText().trim().isEmpty() ? Color.RED : Color.BLACK);
validateFields();
}
private void onKeyFieldChanged() {
keyLabel.setForeground(keyField.getText().trim().isEmpty() ? Color.RED : Color.BLACK);
validateFields();
}
private void onTypeComboChanged() {
typeLabel.setForeground(typeCombo.getSelectedIndex() == 0 ? Color.RED : Color.BLACK);
validateFields();
}
private void onCleanButton() {
nameField.setText(null);
keyField.setText(null);
typeCombo.setSelectedIndex(0);
validateFields();
}
private void onSaveButton() {
String name = nameField.getText().trim();
String key = keyField.getText().trim();
String type = (String)typeCombo.getSelectedItem();
model.add(name, key, type);
if (model.getFile() == null) {
JFileChooser fileChooser = new JFileChooser();
int res = fileChooser.showSaveDialog(this);
model.setFile(res == JFileChooser.APPROVE_OPTION ? fileChooser.getSelectedFile() : null);
}
try {
model.save();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot save file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
private void onOpenButton() {
JFileChooser fileChooser = new JFileChooser();
int res = fileChooser.showOpenDialog(null);
model.setFile(res == JFileChooser.APPROVE_OPTION ? fileChooser.getSelectedFile() : null);
try {
model.read();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot read file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
// ========== ActionListener ==========
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == typeCombo)
onTypeComboChanged();
else if (e.getSource() == clearButton)
onCleanButton();
else if (e.getSource() == saveButton)
onSaveButton();
else if (e.getSource() == openButton)
onOpenButton();
}
// ========== DocumentListener ==========
#Override
public void insertUpdate(DocumentEvent e) {
if (e.getDocument() == nameField.getDocument())
onNameFieldChanged();
else if (e.getDocument() == keyField.getDocument())
onKeyFieldChanged();
}
#Override
public void removeUpdate(DocumentEvent e) {
if (e.getDocument() == nameField.getDocument())
onNameFieldChanged();
else if (e.getDocument() == keyField.getDocument())
onKeyFieldChanged();
}
#Override
public void changedUpdate(DocumentEvent e) {
}
}
ViewGame tab panel:
final class ViewTabPanel extends JPanel implements ActionListener, PopupMenuListener {
private final Model model;
private final JTable table = new JTable();
private final JPopupMenu popupMenu = new JPopupMenu();
private final JMenuItem deleteItem = new JMenuItem("Delete");
public ViewTabPanel(Model model) {
this.model = model;
init();
addListeners();
}
private void init() {
setLayout(new GridLayout(1, 1));
add(new JScrollPane(table));
popupMenu.add(deleteItem);
table.setComponentPopupMenu(popupMenu);
table.setAutoCreateRowSorter(true);
table.setModel(model);
table.updateUI();
}
private void addListeners() {
popupMenu.addPopupMenuListener(this);
deleteItem.addActionListener(this);
}
// ========== ActionListener ==========
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == deleteItem) {
model.remove(table.getSelectedRow());
try {
model.save();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot save file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
}
// ========== PopupMenuListener ==========
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent event) {
if (event.getSource() == popupMenu) {
SwingUtilities.invokeLater(() -> {
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table));
if (rowAtPoint > -1)
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
});
}
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent event) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent event) {
}
}
I want to implement dragging and dropping of files from a directory such as someones hard drive but can't figure out how to do it. I've read the java api but it talks of color pickers and dragging and dropping between lists but how to drag files from a computers file system and drop into my application. I tried writing the transferhandler class and a mouse event for when the drag starts but nothing seems to work. Now I'm back to just having my JFileChooser set so drag has been enabled but how to drop?
Any info or point in the right direction greatly appreciated.
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
public class FileChooserDemo
extends JPanel
implements ActionListener
{
JLabel selectedFileLabel;
JList selectedFilesList;
JLabel returnCodeLabel;
public FileChooserDemo()
{
super();
createContent();
}
void initFrameContent()
{
JPanel closePanel = new JPanel();
add(closePanel, BorderLayout.SOUTH);
}
private void createContent()
{
setLayout(new BorderLayout());
JPanel NorthPanel = new JPanel();
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
JMenuItem quit = new JMenuItem("Quit");
menuBar.add(menu);
menu.add(quit);
NorthPanel.add(menu,BorderLayout.NORTH);
JPanel buttonPanel = new JPanel(new GridLayout(7,1 ));
JButton openButton = new JButton("Open...");
openButton.setActionCommand("OPEN");
openButton.addActionListener(this);
buttonPanel.add(openButton);
JButton saveButton = new JButton("Save...");
saveButton.setActionCommand("SAVE");
saveButton.addActionListener(this);
buttonPanel.add(saveButton);
JButton delete = new JButton("Delete");
delete.addActionListener(this);
delete.setActionCommand("DELETE");
buttonPanel.add(delete);
add(buttonPanel, BorderLayout.WEST);
// create a panel to display the selected file(s) and the return code
JPanel displayPanel = new JPanel(new BorderLayout());
selectedFileLabel = new JLabel("-");
selectedFileLabel.setBorder(BorderFactory.createTitledBorder
("Selected File/Directory "));
displayPanel.add(selectedFileLabel, BorderLayout.NORTH);
selectedFilesList = new JList();
JScrollPane sp = new JScrollPane(selectedFilesList);
sp.setBorder(BorderFactory.createTitledBorder("Selected Files "));
MouseListener listener = new MouseAdapter()
{
public void mousePressed(MouseEvent me)
{
JComponent comp = (JComponent) me.getSource();
TransferHandler handler = comp.getTransferHandler();
handler.exportAsDrag(comp, me, TransferHandler.MOVE);
}
};
selectedFilesList.addMouseListener(listener);
displayPanel.add(sp);
returnCodeLabel = new JLabel("");
returnCodeLabel.setBorder(BorderFactory.createTitledBorder("Return Code"));
displayPanel.add(returnCodeLabel, BorderLayout.SOUTH);
add(displayPanel);
}
public void actionPerformed(ActionEvent e)
{
int option = 0;
File selectedFile = null;
File[] selectedFiles = new File[0];
if (e.getActionCommand().equals("CLOSE"))
{
System.exit(0);
}
else if (e.getActionCommand().equals("OPEN"))
{
JFileChooser chooser = new JFileChooser();
chooser.setDragEnabled(true);
chooser.setMultiSelectionEnabled(true);
option = chooser.showOpenDialog(this);
selectedFiles = chooser.getSelectedFiles();
}
else if (e.getActionCommand().equals("SAVE"))
{
JFileChooser chooser = new JFileChooser();
option = chooser.showSaveDialog(this);
selectedFiles = chooser.getSelectedFiles();
}
// display the selection and return code
if (selectedFile != null)
selectedFileLabel.setText(selectedFile.toString());
else
selectedFileLabel.setText("null");
DefaultListModel listModel = new DefaultListModel();
for (int i =0; i < selectedFiles.length; i++)
listModel.addElement(selectedFiles[i]);
selectedFilesList.setModel(listModel);
returnCodeLabel.setText(Integer.toString(option));
}
public static void main(String[] args)
{
SwingUtilities.invokeLater
(new Runnable()
{
public void run()
{
FileChooserDemo app = new FileChooserDemo();
app.initFrameContent();
JFrame frame = new JFrame("LoquetUP");
frame.getContentPane().add(app);
frame.setDefaultCloseOperation(3);
frame.setSize(600,400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
//frame.pack();
frame.setVisible(true);
}
});
}
}
This is my take on the idea. I've used the "traditional" drag and drop API in this example. It has some extra "paint" tweaks just to show off what you might be able to do.
This example doesn't scan folders dropped onto it, so any folder will only register as a single file, but I'm sure you can work it out
public class TestDragNDropFiles {
public static void main(String[] args) {
new TestDragNDropFiles();
}
public TestDragNDropFiles() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new DropPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DropPane extends JPanel {
private DropTarget dropTarget;
private DropTargetHandler dropTargetHandler;
private Point dragPoint;
private boolean dragOver = false;
private BufferedImage target;
private JLabel message;
public DropPane() {
try {
target = ImageIO.read(new File("target.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
message = new JLabel();
message.setFont(message.getFont().deriveFont(Font.BOLD, 24));
add(message);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
protected DropTarget getMyDropTarget() {
if (dropTarget == null) {
dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, null);
}
return dropTarget;
}
protected DropTargetHandler getDropTargetHandler() {
if (dropTargetHandler == null) {
dropTargetHandler = new DropTargetHandler();
}
return dropTargetHandler;
}
#Override
public void addNotify() {
super.addNotify();
try {
getMyDropTarget().addDropTargetListener(getDropTargetHandler());
} catch (TooManyListenersException ex) {
ex.printStackTrace();
}
}
#Override
public void removeNotify() {
super.removeNotify();
getMyDropTarget().removeDropTargetListener(getDropTargetHandler());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (dragOver) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(0, 255, 0, 64));
g2d.fill(new Rectangle(getWidth(), getHeight()));
if (dragPoint != null && target != null) {
int x = dragPoint.x - 12;
int y = dragPoint.y - 12;
g2d.drawImage(target, x, y, this);
}
g2d.dispose();
}
}
protected void importFiles(final List files) {
Runnable run = new Runnable() {
#Override
public void run() {
message.setText("You dropped " + files.size() + " files");
}
};
SwingUtilities.invokeLater(run);
}
protected class DropTargetHandler implements DropTargetListener {
protected void processDrag(DropTargetDragEvent dtde) {
if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
} else {
dtde.rejectDrag();
}
}
#Override
public void dragEnter(DropTargetDragEvent dtde) {
processDrag(dtde);
SwingUtilities.invokeLater(new DragUpdate(true, dtde.getLocation()));
repaint();
}
#Override
public void dragOver(DropTargetDragEvent dtde) {
processDrag(dtde);
SwingUtilities.invokeLater(new DragUpdate(true, dtde.getLocation()));
repaint();
}
#Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
#Override
public void dragExit(DropTargetEvent dte) {
SwingUtilities.invokeLater(new DragUpdate(false, null));
repaint();
}
#Override
public void drop(DropTargetDropEvent dtde) {
SwingUtilities.invokeLater(new DragUpdate(false, null));
Transferable transferable = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.acceptDrop(dtde.getDropAction());
try {
List transferData = (List) transferable.getTransferData(DataFlavor.javaFileListFlavor);
if (transferData != null && transferData.size() > 0) {
importFiles(transferData);
dtde.dropComplete(true);
}
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
dtde.rejectDrop();
}
}
}
public class DragUpdate implements Runnable {
private boolean dragOver;
private Point dragPoint;
public DragUpdate(boolean dragOver, Point dragPoint) {
this.dragOver = dragOver;
this.dragPoint = dragPoint;
}
#Override
public void run() {
DropPane.this.dragOver = dragOver;
DropPane.this.dragPoint = dragPoint;
DropPane.this.repaint();
}
}
}
}
You need to experiment with Drag & Drop and see exactly what flavors are available when you try to drag files. If you do this in your custom TransferHandler you'll be pleasantly surprised one Flavor is the DataFlavor.javaFileListFlavor, which indicates that the item can be used simply as a List. Try it and you'll see that it works!
Note on review of your posted code, I don't see any code for your attempt at using a TransferHandler, so it is hard to say what you could be doing wrong here.
Edit 1
You seem to be trying to use a MouseListener for your drag and drop, and I'm not familiar with this usage. Can you show a reference to a tutorial that tells you to do this?
Edit 2
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class FileDragDemo extends JPanel {
private JList list = new JList();
public FileDragDemo() {
list.setDragEnabled(true);
list.setTransferHandler(new FileListTransferHandler(list));
add(new JScrollPane(list));
}
private static void createAndShowGui() {
FileDragDemo mainPanel = new FileDragDemo();
JFrame frame = new JFrame("FileDragDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class FileListTransferHandler extends TransferHandler {
private JList list;
public FileListTransferHandler(JList list) {
this.list = list;
}
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
public boolean canImport(TransferSupport ts) {
return ts.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
}
public boolean importData(TransferSupport ts) {
try {
#SuppressWarnings("rawtypes")
List data = (List) ts.getTransferable().getTransferData(
DataFlavor.javaFileListFlavor);
if (data.size() < 1) {
return false;
}
DefaultListModel listModel = new DefaultListModel();
for (Object item : data) {
File file = (File) item;
listModel.addElement(file);
}
list.setModel(listModel);
return true;
} catch (UnsupportedFlavorException e) {
return false;
} catch (IOException e) {
return false;
}
}
}
I'm adding a string to a JList with DefaultListModel and it takes seconds to appear. Sometimes, I may have to click on the JList to have the list appear.
I'm using Eclipse Indigo. When I set a breakpoint after adding the element to JList, execution is fast.
I searched the web and SO for JList slow and they all talk about adding many items to the list. I'm adding the first element to the list.
Here's my code fragments:
private DefaultListModel function_list_model = new DefaultListModel();
private JList list_functions = new JList(function_list_model);
//...
// Initialization code:
JPanel panel_function_list = new JPanel();
panel_function_list.setBounds(10, 53, 541, 220);
panel_functions.add(panel_function_list);
panel_function_list.setLayout(null);
JLabel lblFunctions = new JLabel("Functions");
lblFunctions.setHorizontalAlignment(SwingConstants.CENTER);
lblFunctions.setBounds(235, 11, 99, 14);
panel_function_list.add(lblFunctions);
list_functions.setBorder(new LineBorder(new Color(0, 0, 0)));
list_functions.setBounds(10, 42, 492, 177);
list_functions.setFont(new Font("Courier New", Font.PLAIN, 12));
list_functions.setPreferredSize(new Dimension(0, 150));
list_functions.setMinimumSize(new Dimension(32767, 100));
list_functions.setMaximumSize(new Dimension(32767, 100));
JScrollPane scrollPane_functions = new JScrollPane(list_functions);
scrollPane_functions.setBounds(10, 79, 541, 183);
panel_functions.add(scrollPane_functions);
// Code to add a string:
String burger = new String("burger");
function_list_model.addElement(burger);
I'm also using WindowBuilder with Eclipse.
So how do I improve the performance of JList?
if you want I can to generating new Item from Char[] and to call doClick() for JButton("Fire")
import java.awt.*;
import java.awt.event.*;
import java.util.Date;
import javax.swing.*;
import javax.swing.event.*;
public class ListDemo extends JPanel implements ListSelectionListener {
private JList list;
private DefaultListModel listModel;
private static final String hireString = "Hire";
private static final String fireString = "Fire";
private JButton fireButton;
private JTextField employeeName;
private javax.swing.Timer timer = null;
private int delay = 3;
private int count = 0;
public ListDemo() {
super(new BorderLayout());
listModel = new DefaultListModel();
listModel.addElement("Jane Doe");
listModel.addElement("John Smith");
listModel.addElement("Kathy Green");
list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
list.addListSelectionListener(this);
list.setVisibleRowCount(5);
JScrollPane listScrollPane = new JScrollPane(list);
JButton hireButton = new JButton(hireString);
HireListener hireListener = new HireListener(hireButton);
hireButton.setActionCommand(hireString);
hireButton.addActionListener(hireListener);
hireButton.setEnabled(false);
fireButton = new JButton(fireString);
fireButton.setActionCommand(fireString);
fireButton.addActionListener(new FireListener());
employeeName = new JTextField(10);
employeeName.addActionListener(hireListener);
employeeName.getDocument().addDocumentListener(hireListener);
String name = listModel.getElementAt(list.getSelectedIndex()).toString();
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.add(fireButton);
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(new JSeparator(SwingConstants.VERTICAL));
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(employeeName);
buttonPane.add(hireButton);
buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
add(listScrollPane, BorderLayout.CENTER);
add(buttonPane, BorderLayout.PAGE_END);
start();
System.out.println(new Date());
}
private void start() {
timer = new javax.swing.Timer(delay * 10, updateCol());
timer.start();
}
public Action updateCol() {
return new AbstractAction("text load action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
listModel.addElement("Jane Doe");
listModel.addElement("John Smith");
listModel.addElement("Kathy Green");
list.ensureIndexIsVisible(listModel.getSize()-1);
count++;
if (count >= 500) {
timer.stop();
System.out.println("update cycle completed");
System.out.println(new Date());
}
}
};
}
class FireListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int index = list.getSelectedIndex();
listModel.remove(index);
int size = listModel.getSize();
if (size == 0) { //Nobody's left, disable firing.
fireButton.setEnabled(false);
} else { //Select an index.
if (index == listModel.getSize()) {
index--;
}
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
}
class HireListener implements ActionListener, DocumentListener {
private boolean alreadyEnabled = false;
private JButton button;
HireListener(JButton button) {
this.button = button;
}
#Override
public void actionPerformed(ActionEvent e) {
String name = employeeName.getText();
if (name.isEmpty() || alreadyInList(name)) {
Toolkit.getDefaultToolkit().beep();
employeeName.requestFocusInWindow();
employeeName.selectAll();
return;
}
int index = list.getSelectedIndex(); //get selected index
if (index == -1) { //no selection, so insert at beginning
index = 0;
} else { //add after the selected item
index++;
}
listModel.insertElementAt(employeeName.getText(), index);
//listModel.addElement(employeeName.getText());
employeeName.requestFocusInWindow();
employeeName.setText("");
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
protected boolean alreadyInList(String name) {
return listModel.contains(name);
}
#Override
public void insertUpdate(DocumentEvent e) {
enableButton();
}
#Override
public void removeUpdate(DocumentEvent e) {
handleEmptyTextField(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
if (!handleEmptyTextField(e)) {
enableButton();
}
}
private void enableButton() {
if (!alreadyEnabled) {
button.setEnabled(true);
}
}
private boolean handleEmptyTextField(DocumentEvent e) {
if (e.getDocument().getLength() <= 0) {
button.setEnabled(false);
alreadyEnabled = false;
return true;
}
return false;
}
}
#Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
if (list.getSelectedIndex() == -1) {
fireButton.setEnabled(false);
} else {
fireButton.setEnabled(true);
}
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("ListDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ListDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
I'm trying to create a form with a JList and a button
What I want to do, is select an item from the JList, and then press the button to perform an action dependant on the selection. However, as soon as the button is clicked, the JList loses focus, and the selection disappears, making the button unable to determine what element was selected in the JList.
Is there a solution to this?
Thanks in advance :)
I can't see any issue with example from Oracle JList tutorial
have look at ListSelectionListener
maybe carefully with SelectionModes
can you please to describe whats is your goal
code example
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ListDemo extends JPanel implements ListSelectionListener {
private JList list;
private DefaultListModel listModel;
private static final String hireString = "Hire";
private static final String fireString = "Fire";
private JButton fireButton;
private JTextField employeeName;
public ListDemo() {
super(new BorderLayout());
listModel = new DefaultListModel();
listModel.addElement("Jane Doe");
listModel.addElement("John Smith");
listModel.addElement("Kathy Green");
list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
list.addListSelectionListener(this);
list.setVisibleRowCount(5);
JScrollPane listScrollPane = new JScrollPane(list);
JButton hireButton = new JButton(hireString);
HireListener hireListener = new HireListener(hireButton);
hireButton.setActionCommand(hireString);
hireButton.addActionListener(hireListener);
hireButton.setEnabled(false);
fireButton = new JButton(fireString);
fireButton.setActionCommand(fireString);
fireButton.addActionListener(new FireListener());
employeeName = new JTextField(10);
employeeName.addActionListener(hireListener);
employeeName.getDocument().addDocumentListener(hireListener);
String name = listModel.getElementAt(list.getSelectedIndex()).toString();
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.add(fireButton);
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(new JSeparator(SwingConstants.VERTICAL));
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(employeeName);
buttonPane.add(hireButton);
buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
add(listScrollPane, BorderLayout.CENTER);
add(buttonPane, BorderLayout.PAGE_END);
}
class FireListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
int index = list.getSelectedIndex();
listModel.remove(index);
int size = listModel.getSize();
if (size == 0) { //Nobody's left, disable firing.
fireButton.setEnabled(false);
} else { //Select an index.
if (index == listModel.getSize()) {
index--;
}
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
}
class HireListener implements ActionListener, DocumentListener {
private boolean alreadyEnabled = false;
private JButton button;
public HireListener(JButton button) {
this.button = button;
}
public void actionPerformed(ActionEvent e) {
String name = employeeName.getText();
if (name.equals("") || alreadyInList(name)) {
Toolkit.getDefaultToolkit().beep();
employeeName.requestFocusInWindow();
employeeName.selectAll();
return;
}
int index = list.getSelectedIndex(); //get selected index
if (index == -1) { //no selection, so insert at beginning
index = 0;
} else { //add after the selected item
index++;
}
listModel.insertElementAt(employeeName.getText(), index);
//listModel.addElement(employeeName.getText());
employeeName.requestFocusInWindow();
employeeName.setText("");
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
protected boolean alreadyInList(String name) {
return listModel.contains(name);
}
public void insertUpdate(DocumentEvent e) {
enableButton();
}
public void removeUpdate(DocumentEvent e) {
handleEmptyTextField(e);
}
public void changedUpdate(DocumentEvent e) {
if (!handleEmptyTextField(e)) {
enableButton();
}
}
private void enableButton() {
if (!alreadyEnabled) {
button.setEnabled(true);
}
}
private boolean handleEmptyTextField(DocumentEvent e) {
if (e.getDocument().getLength() <= 0) {
button.setEnabled(false);
alreadyEnabled = false;
return true;
}
return false;
}
}
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
if (list.getSelectedIndex() == -1) {
fireButton.setEnabled(false);
} else {
fireButton.setEnabled(true);
}
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("ListDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ListDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Just have a field that you update every time a selection is made. You could do this by adding a listener on your JList.
private class selectListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
currentSelected = list.getSelectedIndex();
}
}
}
Then use that field when your button is pressed.
How can I register a custom data flavour, such that when I call
TransferHandler.TransferSupport.isDataFlavorSupported()
it returns true?
The flavour is initialised like so
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(DataManagerTreeNode.class, DataFlavor.javaJVMLocalObjectMimeType, "DataManagerTreeNode flavour");
Many thanks
I saw only once times correct code for JTable and DnD, offical code by Oracle (former Sun)
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;
public class FillViewportHeightDemo extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private DefaultListModel model = new DefaultListModel();
private int count = 0;
private JTable table;
private JCheckBoxMenuItem fillBox;
private DefaultTableModel tableModel;
private static String getNextString(int count) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < 5; i++) {
buf.append(String.valueOf(count));
buf.append(",");
}
buf.deleteCharAt(buf.length() - 1); // remove last newline
return buf.toString();
}
private static DefaultTableModel getDefaultTableModel() {
String[] cols = {"Foo", "Toto", "Kala", "Pippo", "Boing"};
return new DefaultTableModel(null, cols);
}
public FillViewportHeightDemo() {
super("Empty Table DnD Demo");
tableModel = getDefaultTableModel();
table = new JTable(tableModel);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setDropMode(DropMode.INSERT_ROWS);
table.setTransferHandler(new TransferHandler() {
private static final long serialVersionUID = 1L;
#Override
public boolean canImport(TransferSupport support) {
if (!support.isDrop()) { // for the demo, we'll only support drops (not clipboard paste)
return false;
}
if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { // we only import Strings
return false;
}
return true;
}
#Override
public boolean importData(TransferSupport support) { // if we can't handle the import, say so
if (!canImport(support)) {
return false;
}
JTable.DropLocation dl = (JTable.DropLocation) support.getDropLocation();// fetch the drop location
int row = dl.getRow();
String data; // fetch the data and bail if this fails
try {
data = (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException e) {
return false;
} catch (IOException e) {
return false;
}
String[] rowData = data.split(",");
tableModel.insertRow(row, rowData);
Rectangle rect = table.getCellRect(row, 0, false);
if (rect != null) {
table.scrollRectToVisible(rect);
}
model.removeAllElements(); // demo stuff - remove for blog
model.insertElementAt(getNextString(count++), 0); // end demo stuff
return true;
}
});
JList dragFrom = new JList(model);
dragFrom.setFocusable(false);
dragFrom.setPrototypeCellValue(getNextString(100));
model.insertElementAt(getNextString(count++), 0);
dragFrom.setDragEnabled(true);
dragFrom.setBorder(BorderFactory.createLoweredBevelBorder());
dragFrom.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
if (SwingUtilities.isLeftMouseButton(me) && me.getClickCount() % 2 == 0) {
String text = (String) model.getElementAt(0);
String[] rowData = text.split(",");
tableModel.insertRow(table.getRowCount(), rowData);
model.removeAllElements();
model.insertElementAt(getNextString(count++), 0);
}
}
});
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
JPanel wrap = new JPanel();
wrap.add(new JLabel("Drag from here:"));
wrap.add(dragFrom);
p.add(Box.createHorizontalStrut(4));
p.add(Box.createGlue());
p.add(wrap);
p.add(Box.createGlue());
p.add(Box.createHorizontalStrut(4));
getContentPane().add(p, BorderLayout.NORTH);
JScrollPane sp = new JScrollPane(table);
getContentPane().add(sp, BorderLayout.CENTER);
fillBox = new JCheckBoxMenuItem("Fill Viewport Height");
fillBox.addActionListener(this);
JMenuBar mb = new JMenuBar();
JMenu options = new JMenu("Options");
mb.add(options);
setJMenuBar(mb);
JMenuItem clear = new JMenuItem("Reset");
clear.addActionListener(this);
options.add(clear);
options.add(fillBox);
getContentPane().setPreferredSize(new Dimension(260, 180));
}
#Override
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == fillBox) {
table.setFillsViewportHeight(fillBox.isSelected());
} else {
tableModel.setRowCount(0);
count = 0;
model.removeAllElements();
model.insertElementAt(getNextString(count++), 0);
}
}
private static void createAndShowGUI() {//Create and set up the window.
FillViewportHeightDemo test = new FillViewportHeightDemo();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.pack(); //Display the window.
test.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}