首页 > 解决方案 > Java Swing自定义JList cellRenderer在添加新元素后未绘制所有元素

问题描述

所以这是我作为新手的第一个更大的项目。这个项目主要是一个 Swing GUI 应用程序,它基本上是一个公寓猎人应用程序。实际上,这是一个非常大的程序(至少对我来说),而且代码非常混乱,但我会尽力包含所有必要的内容。所以在程序中,其中一个 JPanel 包含一个 Jlist,其中包含所有可用的公寓,并且有一个自定义的 cellRenderer 类。看起来像这样(我将在代码片段之后详细说明所有内容):

class PanelRenderer extends DefaultListCellRenderer {


        @Override
        public Component getListCellRendererComponent(
            JList list, Object value, int index,
            boolean isSelected, boolean cellHasFocus) {

            JLabel label = (JLabel) super.getListCellRendererComponent(
                list, value, index, isSelected, cellHasFocus);

                    Pair pair = sqldata.getInfo((String)value);
                    if(MainController.data_storage!=null){
                        ImageIcon final_img = MainController.data_storage.get((String)value).get(0); //(String)value is From nameList array
                        label.setIcon(final_img); 
                        
                    }
                    ArrayList<String> tmp = sqldata.apartmentDetails(pair.getValue()+"");
                    
                    if(tmp.size()>0){
                        ids.add(tmp.get(tmp.size()-1));
                    }
                                 
                    label.setText("<html>Title: "+pair.getValue()+" <br/> Price: "+pair.getKey()+"  <br/> Owner: "+value+"<br/>  <br/>"
                            + " Room type: "+tmp.get(0)+"       <br/>        Room num: "+tmp.get(1)+"     <br/>         "
                                    + " Balcony:           "+(tmp.get(2).equals("true") ? "<font color='green'>✓&lt;/font>" : "<font color='red'>×</font>")+"        "
                                    + "       Pet: "+(tmp.get(3).equals("true") ? "<font color='green'>✓&lt;/font>" : "<font color='red'>×</font>")+" "
                                    + "               Yard: "+(tmp.get(4).equals("true") ? "<font color='green'>✓&lt;/font>" : "<font color='red'>×</font>")+"           "
                                            + "    Smoke: "+(tmp.get(5).equals("true") ? "<font color='green'>✓&lt;/font>" : "<font color='red'>×</font>")+"     "
                                            + "     Quiet: "+(tmp.get(6).equals("true") ? "<font color='green'>✓&lt;/font>" : "<font color='red'>×</font>")+" "
                                            + "               Deposit: "+(tmp.get(7).equals("true") ? "<font color='green'>✓&lt;/font>" : "<font color='red'>×</font>")+"</html>");
                    label.setHorizontalTextPosition(JLabel.RIGHT);
                    value = tmp.get(tmp.size()-1);
            return label;
        }
    } 

所以这一行:Pair pair = sqldata.getInfo((String)value);返回价格和公寓的标题。

此行:ImageIcon final_img = MainController.data_storage.get((String)value).get(0);返回与公寓所有者姓名关联的图像。

下一行:ArrayList<String> tmp = sqldata.apartmentDetails(pair.getValue()+"");返回公寓的其余部分。例如:城市、房间类型、宠物等。所以一个列表项有一张图片,还有一些文字。

我的应用程序有一个搜索按钮,按下时会从 sql 服务器获取所有数据,并从远程 FTP 服务器下载相应的数据。之后,Jlist 会显示结果。还有过滤器选项,如阳台、宠物、价格和城市。到目前为止,这些工作正常。上传新公寓后出现问题。如果我在上传新公寓后单击搜索按钮,所有内容都会正确返回(在内部,如列表),除了列表中的所有彩绘元素。因为什么都没有画。所以在插入(上传)之后,数据被插入到 SQL 表中,图像上传到 FTP 服务器上。这部分很好。此外,当我刷新将元素提供给 JList 的 arrayList 时,它会告诉我新公寓在其中(以及旧公寓)。但是 JList 上没有显示任何内容,它完全是空白的。此代码正在上传:

if(validFile()){
                 if(!uploadMenuValidate()){
                   if(!img_container.isEmpty()){ 
                    for(File f : img_container){
                     try {
                         ftp.putFileToPath(f, FtpClient.DEST_DIR+SQLData.APP_USERNAME+"/"+f.getName());

                     } catch (FileNotFoundException ex) {
                         ex.printStackTrace();
                         } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                     }
                           sqldata.insert(SQLData.QUERY_ADD_APARTMENT, SQLData.APP_USERNAME,uploadmenu.getPriceField().getText(),uploadmenu.getCityField().getText(),uploadmenu.getRoomTypeSelector().getSelectedItem().toString(),
                                   uploadmenu.getRoomNum().getText(),uploadmenu.getBalconyCheck().isSelected()+"",uploadmenu.getPetCheck().isSelected()+"",uploadmenu.getYardCheck().isSelected()+"",uploadmenu.getSmokeCheck().isSelected()+"",
                                   uploadmenu.getFreqCheck().isSelected()+"",uploadmenu.getDepositCheck().isSelected()+"",img_container.size()>0 ? FtpClient.DEST_DIR+SQLData.APP_USERNAME+"/"+img_container.get(0).getName() : "",
                                   img_container.size()>1 ? FtpClient.DEST_DIR+SQLData.APP_USERNAME+"/"+img_container.get(1).getName() : "",img_container.size()>2 ? FtpClient.DEST_DIR+SQLData.APP_USERNAME+"/"+img_container.get(2).getName() : "",
                                   img_container.size()>3 ? FtpClient.DEST_DIR+SQLData.APP_USERNAME+"/"+img_container.get(3).getName() : "",uploadmenu.getDetailsBox().getText(),uploadmenu.getApTitle().getText(),mainc.getUniqueId());
                           
                           showInfoPanel("misc.INFO_UPLOAD_SUCCESS");

    
                                   data_storage = mainc.getApartments(sqldata.getApartments()); 
         }
    }
}

这里:data_storage = mainc.getApartments(sqldata.getApartments());内部 ArrayList 被刷新,它基本上包含了 JList 的元素。

一些可能很重要的代码:

mainJListPanel = new JList(nameList);

public String[] nameList = makeList();

     public String[] makeList(){
        
        int n = sqldata.getApartments().size();
        HashMap<String,List<String>> kt = sqldata.getApartments();
        String[] tmp =new String[n];
        ids = new ArrayList<>();
        
        
         int i = 0;
        for (String x : kt.keySet()){
            tmp[i++] = x; //Getting the owner names
        }
        return tmp;
    }
    
    public static String[] searchList(){
        int n = MainController.data_storage.size();
        String[] tmp = new String[n];
        
        int i = 0;
        for (String x : MainController.data_storage.keySet()){
            tmp[i++] = x;
        }
        return tmp;
    }

搜索按钮执行此操作:

data_storage = getApartments(sqldata.getSearchedApartments(mainmenu.getMenuMinPrice().getText()+"",mainmenu.getMenuMaxPrice().getText(),mainmenu.getMenuCity().getText(),
                String.valueOf((int)mainmenu.getMenuRoomNum().getValue()),mainmenu.getMenuRoomType().getSelectedItem()+"",mainmenu.getMenuBalcony().isSelected()+"",mainmenu.getMenuYard().isSelected()+"",mainmenu.getMenuPet().isSelected()+"",
                mainmenu.getMenuSmoke().isSelected()+"",mainmenu.getMenuFreq().isSelected()+"",mainmenu.getMenuDeposit().isSelected()+"", mainmenu.getMenuMiscText().getText()));
 //Getting everything from the filter, and //converting it into an SQL query --> This is working, the sql command is OK. 
            
            mainmenu.setNameList(mainmenu.searchList());
            mainmenu.getMenuMainPanel().revalidate();
            mainmenu.getMenuMainPanel().repaint();
//mainmenu is the instance of the JPanel, which contains the Jlist

奇怪的是,如果我检查一个过滤器选项,比如阳台,JList 会绘制结果。甚至新公寓也在上传的结果中。但是当我删除所有过滤器时,(所以基本上我希望每间公寓都回来),列表不会画任何东西。所以只有当我处于“上传后”状态时才会出现错误,并且我希望每个公寓都被绘制在 Jlist 上。如果我重新启动程序,新公寓将被绘制在列表中,并且一切正常,直到我再次上传新公寓。

标签: javaswinguser-interfacepaintjlist

解决方案


推荐阅读