Oh boy. It's been a while since I've used Swing, but here goes nothing:
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class Application {
JFrame appFrame;
ShopPanel shopPanel;
InventoryPanel inventoryPanel;
JMenuBar menuBar;
List<Category> fakeData;
public Application() {
appFrame = new JFrame();
// this is a menu bar with menus that don't have menu items
menuBar = new JMenuBar();
menuBar.add( createHomeMenu() );
menuBar.add( createInMenu() );
menuBar.add( createOutMenu() );
menuBar.add( createCreateMenu() );
inventoryPanel = new InventoryPanel();
shopPanel = new ShopPanel();
shopPanel.setCategoryListener((category) -> {
inventoryPanel.setInventoryList( category.getItems() );
});
appFrame.setLayout( new BorderLayout() );
appFrame.setJMenuBar(menuBar);
appFrame.add( new ShopPanel(), BorderLayout.WEST );
appFrame.add( new InventoryPanel(), BorderLayout.CENTER );
fakeData = new ArrayList<>();
fakeData.add(new Category("Vehicles")
.addItem(new ShopItem(1, "Mad Max's Car", "Junker from Mad Max with a ridiculous v8 engine."))
.addItem(new ShopItem(2, "Back to the Futre Delorean", "Delorean time machine. Do not take over 88 MPH"))
.addItem(new ShopItem(3, "Bingo Bus", "The Bingo Bus is coming! The Bingo Bus is coming!"))
);
fakeData.add(new Category("Tools")
.addItem(new ShopItem(4, "Sonic Screw Driver", "Dr. Who gave me this screw driver. Works like a charm."))
.addItem(new ShopItem(5, "Tricorder", "Mr Spock's tricorder never needs to be charged."))
.addItem(new ShopItem(6, "NOC List", "Top Secret. This cannot be out in the open."))
);
shopPanel.setCategories( fakeData );
inventoryPanel.setInventoryList( fakeData.getFirst().items );
}
private static JMenu createCreateMenu() {
return new JMenu("Create");
}
private static JMenu createOutMenu() {
return new JMenu("Out");
}
private static JMenu createInMenu() {
return new JMenu("In");
}
private JMenu createHomeMenu() {
JMenu homeMenu = new JMenu("Home");
homeMenu.add(new AbstractAction("Exit") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Exit application");
System.exit(0);
}
});
return homeMenu;
}
public void show() {
// todo this isn't going to layout nicely because it's not filled out. Instead of packing it you could pick
// a predetermined size like 1024x768:
// appFrame.setSize( 1024, 768 );
appFrame.pack();
appFrame.setVisible(true);
}
public static void main(String[] args) {
Application app = new Application();
app.show();
}
}
public class InventoryPanel extends JPanel {
JList<ShopItem> inventoryList;
StandardListModel<ShopItem> items;
public InventoryPanel() {
items = new StandardListModel<ShopItem>();
inventoryList = new JList<>(items);
inventoryList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
inventoryList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
// todo logic for when something is selected
}
});
inventoryList.setCellRenderer(new ListCellRenderer<ShopItem>() {
@Override
public Component getListCellRendererComponent(JList<? extends ShopItem> list, ShopItem value, int index, boolean isSelected, boolean cellHasFocus) {
// todo build another panel for the image, name, description thingy and use that here
// todo return new ShopItemPanel( value );
return new JLabel(value.name);
}
});
setLayout(new BorderLayout());
add( new JScrollPane(inventoryList), BorderLayout.CENTER );
}
public void setInventoryList(List<ShopItem> items) {
this.items.setList( items );
}
}
public class ShopPanel extends JPanel {
JList<Category> shopCategories;
StandardListModel<Category> categories;
CategoryListener listener;
public interface CategoryListener {
public void categorySelected(Category category);
}
public ShopPanel() {
super(new BorderLayout());
categories = new StandardListModel<Category>();
shopCategories = new JList<>(categories);
shopCategories.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
shopCategories.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
listener.categorySelected( categories.get(e.getFirstIndex() ) );
}
});
shopCategories.setCellRenderer(new ListCellRenderer<Category>() {
@Override
public Component getListCellRendererComponent(JList list, Category value, int index, boolean isSelected, boolean cellHasFocus) {
return new JLabel(value.name);
}
});
add(shopCategories, BorderLayout.CENTER );
}
public void setCategories(List<Category> categories) {
this.categories.setList(categories);
}
public void setCategoryListener(CategoryListener listener) {
this.listener = listener;
}
}
public class StandardListModel<T> implements List<T>, ListModel<T> {
List<T> items;
List<ListDataListener> listeners = new ArrayList<>();
public StandardListModel() {
items = new ArrayList<T>();
}
public StandardListModel(List<T> backingList) {
items = backingList;
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
@Override
public boolean contains(Object o) {
return items.contains(o);
}
@Override
public Iterator<T> iterator() {
return items.iterator();
}
@Override
public Object[] toArray() {
return items.toArray();
}
@Override
public <T1> T1[] toArray( T1[] a) {
return items.toArray(a);
}
@Override
public boolean add(T t) {
boolean result = items.add(t);
notifyAdd(items.size() - 1, items.size() - 1);
return result;
}
@Override
public boolean remove(Object o) {
int index = items.indexOf(o);
if( index >= 0 ) {
boolean result = items.remove(o);
notifyRemoval( index, index );
return result;
}
return false;
}
@Override
public boolean containsAll( Collection<?> c) {
return items.containsAll(c);
}
@Override
public boolean addAll( Collection<? extends T> c) {
boolean result = items.addAll(c);
notifyAdd( items.size() - c.size(), items.size() - 1);
return result;
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
boolean result = items.addAll(index, c);
notifyAdd( index, index + c.size() );
return result;
}
@Override
public boolean removeAll( Collection<?> c) {
boolean result = items.removeAll(c);
notifyChanged();
return result;
}
@Override
public boolean retainAll( Collection<?> c) {
boolean result = items.retainAll(c);
notifyChanged();
return result;
}
@Override
public void replaceAll(UnaryOperator<T> operator) {
items.replaceAll(operator);
notifyChanged();
}
@Override
public void sort(Comparator<? super T> c) {
items.sort(c);
notifyChanged();
}
@Override
public void clear() {
int size = size();
items.clear();
notifyRemoval(0, size);
}
@Override
public boolean equals(Object o) {
return items.equals(o);
}
@Override
public int hashCode() {
return items.hashCode();
}
@Override
public T get(int index) {
return items.get(index);
}
@Override
public T set(int index, T element) {
T t = items.set(index, element);
notifyChanged( index, index );
return t;
}
@Override
public void add(int index, T element) {
items.add(index, element);
notifyAdd( index, index );
}
@Override
public T remove(int index) {
T t = items.remove(index);
notifyRemoval( index, index );
return t;
}
@Override
public int indexOf(Object o) {
return items.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return items.lastIndexOf(o);
}
@Override
public ListIterator<T> listIterator() {
return items.listIterator();
}
@Override
public ListIterator<T> listIterator(int index) {
return items.listIterator(index);
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
return items.subList(fromIndex, toIndex);
}
@Override
public Spliterator<T> spliterator() {
return items.spliterator();
}
@Override
public void addFirst(T t) {
items.addFirst(t);
notifyAdd( 0, 0 );
}
@Override
public void addLast(T t) {
items.addLast(t);
notifyAdd( items.size(), items.size() );
}
@Override
public T getFirst() {
return items.getFirst();
}
@Override
public T getLast() {
return items.getLast();
}
@Override
public T removeFirst() {
T t = items.removeFirst();
notifyRemoval(0,0);
return t;
}
@Override
public T removeLast() {
T t = items.removeLast();
notifyRemoval(items.size(), items.size());
return t;
}
@Override
public List<T> reversed() {
return items.reversed();
}
@Override
public int getSize() {
return size();
}
@Override
public T getElementAt(int index) {
return get(index);
}
@Override
public <T1> T1[] toArray(IntFunction<T1[]> generator) {
return items.toArray(generator);
}
@Override
public boolean removeIf(Predicate<? super T> filter) {
boolean removed = items.removeIf(filter);
notifyChanged();
return removed;
}
@Override
public Stream<T> stream() {
return items.stream();
}
@Override
public Stream<T> parallelStream() {
return items.parallelStream();
}
@Override
public void forEach(Consumer<? super T> action) {
items.forEach(action);
}
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
private void notifyChanged(int start, int end) {
ListDataEvent event = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, start, end);
listeners.forEach((l) -> l.contentsChanged(event));
}
private void notifyChanged() {
notifyChanged(0, items.size());
}
private void notifyRemoval(int start, int end) {
ListDataEvent event = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, start, end );
listeners.forEach((l) -> l.intervalRemoved(event));
}
private void notifyAdd(int start, int end) {
ListDataEvent event = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, start, end );
listeners.forEach((l) -> l.intervalRemoved(event));
}
public void setList(List<T> items) {
this.items = items;
notifyChanged();
}
}
public class Category {
String name;
List<ShopItem> items;
public Category(String name) {
this.name = name;
items = new ArrayList<>();
}
public Category addItem( ShopItem item) {
this.items.add(item);
return this;
}
public List<ShopItem> getItems() {return items;}
}
public class ShopItem {
final Integer id;
final String name;
final String description;
public ShopItem(Integer id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
}
}
I did not compile or run this. It's an idea of how to do things in Swing. But this should give you a pretty good framework to get started. Split up the classes into separate files and hopefully you can fire it up and see things happen.
The Application class is the main start of the program.
The ShopPanel controls the left hand list of Category-ies (ie Vehicle, Tools, etc)
The InventoryPanel controls the center list of ShopItems within the selected Category
The StandardListModel is a helper class that makes working with ListModels much much easier. It implements java.util.List and ListModel so it is suitable to be used like a normal Java List, but it can be dropped directly into a JList control without needing to write any extra code. Huge time saver in Swing programming.
ShopItem and Category are your model objects per your mock up. They hold data and represent the things in the UI. You'll parse your spreadsheet with POI and populate this model with it. It all resides in memory which makes things easier.
I didn't fully implement the last panel layout which was the ShopItemPanel that is something you can do. If I were doing it I'd read up on GroupLayout. Good luck.
JTable