Victor Euan Jr
Victor Euan Jr

Reputation: 11

How to add premade dynamic JFrame Forms into existing JPanel

I'm trying to create a Dynamic UI to inventory items around the shop. Right now I have a MainMenu JFrame Form which can either select elements from the JTree on the left or the JTextField on top. I have those methods sorted already, however I am having issues populating the JPanel inside a JScrollPane with a JPanel Form that can be called using:

public DisplayItem(int ID) throws IOException{
    initComponents();
    ArrayList<Integer> cellsWanted = new ArrayList<>(Arrays.asList(0, 1, 4, 5, 16));
    ArrayList<String> list = readSelect(ID, cellsWanted);
    BufferedImage img = ImageIO.read(new File(list.get(4)));
    ImageIcon icon = new ImageIcon(img);
    DisplayID.setText(list.get(0));
    DisplayName.setText(list.get(1));
    DisplayDescription.setText(list.get(2));
    DisplayLocation.setText(list.get(3));
    DisplayImage.setIcon(icon);
}

To test out my DisplayItem I temporarily assigned the In button on the top of the page to call:

private void jButton12ActionPerformed(java.awt.event.ActionEvent evt) {                                          
    try {
        // TODO add your handling code here:
        jPanel9.add(new DisplayItem(20));
    } catch (IOException ex) {
        Logger.getLogger(MainMenu.class.getName()).log(Level.SEVERE, null, ex);
    }
} 

In theory, the program will call to create a new DisplayItem with an ID of 20 which sources the data from its respective Excel row using Apache POI. It will generate the JPanel Form and add it as a new object inside the JPanel. I want these DisplayItems to stack on top of each other using GroupLayout however every time I call the function it returns:

`AWT-EventQueue-0 ERROR Log4j API could not find a logging provider.` 

It also prevents In to be pressed again. I want to know why exactly my program is throwing the IOException and if I am trying to go about this the wrong way. If there are any solutions or resources I can be directed to that helps a lot, thank you. For extra reference, here is more of my code that could be helpful in analyzing my issue:

DisplayItem java MainMenu java ExcelRead java

Had to put them in google docs since code goes past question limits. Also sorry for ugly code formatting, stackoverflow kept giving me formatting errors for some reason idk...

Upvotes: 1

Views: 62

Answers (1)

chubbsondubs
chubbsondubs

Reputation: 38842

I'll cut to the chase. You are going down the wrong path here. I really think you ought to stick with using JList to render your list of items in your shop. In order to display your items you can use your DIsplayItem component, but you'll use a CellRenderer to paint that component on the screen. Wrapping the JList in a JScrollPane will handle scrolling (solved no more work). But if you want to edit things you'll need to use a JDialog that populates a DIsplayItem component to provide interactivity. JList supports using CellRenderers, but not inline editors. If you really have to do that you'll need to switch to JTable, but JTable's learning curve is steep. Using JList is VERY efficient when lists are large, and it behaves well with JScrollPane. Your current approach is most certainly NOT efficient.

Stacking real components on top of each other using layouts and scrolling is going to be a serious headache. It uses a lot of memory because each row in the JPanel will instantiate a DisplayItem for every item in the list. Even if it's NOT on the screen. JList and JTable mitigate these issues using a single instance to paint only the displayed rows on the screen. This uses far less memory.

Using the ListModel to hold all of your items and rendering those is a much much simpler way to work with the UI. As opposed to mapping your list into a set of child panels inside a larger panel. And you hadn't even started to think about adding/removing/updating things yet. Binding changes made to your model back to your child panels is a solved problem with JList. If you do this on your own you are re-solving that same problem in a less easy way. You are either going to destroy and re-create panels a lot, or you have a complicated mapping rows in a list with child panels. That's a complicated algorithm you DON'T have to deal with using JList.

inventoryList.setCellRenderer(new ListCellRenderer<ShopItem>() {
   DisplayItem displayItem = new DisplayItem(); // << the only instance you need

   @Override
   public Component getListCellRendererComponent(JList<? extends ShopItem> list, ShopItem value, int index, boolean isSelected, boolean cellHasFocus) {
        displayItem.setItem( value );
        return displayItem;
     }
   });
});

Upvotes: 0

Related Questions