Java 如何在 JTable 中使用 hashMap

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2257309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:20:31  来源:igfitidea点击:

how to use hashMap with JTable

javaswing

提问by sutoL

i have a hashMap which i would like its data to be viewed in a JTable how ever i am having trouble getting the hashMap amount of columns and rows and the data to be displayed.i have a hashmap which takes a accountID as the key and a object of students in which each students have their data like name,id, age, etc.however referring to the JTable docs, it says i would need ints for the row and column and a multidimension array of type Object. how can i do it? can i change my hashMap into a multidimenion array?

我有一个 hashMap,我希望在 JTable 中查看它的数据,但是我在获取列和行的 hashMap 数量以及要显示的数据时遇到问题。我有一个 hashmap,它以 accountID 作为键和一个学生的对象,其中每个学生都有他们的数据,如姓名、身、年龄等。然而,参考 JTable 文档,它说我需要行和列的整数以及对象类型的多维数组。我该怎么做?我可以将我的 hashMap 更改为多维数组吗?

--Edit i have edited my question so it could be more clear , i am fairly new to Java i do not really get what some of you have posted, especially since the work i am doing is quite related to OO and grasping OO concepts is my biggest challenge,

- 编辑我编辑了我的问题,所以它可能更清楚,我对 Java 还很陌生,我不太明白你们中的一些人发布的内容,特别是因为我正在做的工作与 OO 非常相关,并且掌握 OO 概念是我最大的挑战,

/I have a dataStorage class, the registered user is added to the HashMap with a Key input of his Username, which is getUser ./

/我有一个 dataStorage 类,注册用户被添加到 HashMap 中,并使用他的用户名的 Key 输入,即 getUser 。/

import java.util.*;

public class DataStorage 
{
    HashMap<String, Student> students = new HashMap<String, Student>();  
    HashMap<String, Staff> staffMembers = new HashMap<String, Staff>();  
    //Default constructor
    public DataStorage(){
    }

    public void addStaffMember(Staff aAcc) 
    {
     staffMembers.put(aAcc.getUser(),aAcc);
    }

    public void addStudentMember(Student aAcc)
    {
     students.put(aAcc.getUser(),aAcc);
    }

   public Staff getStaffMember(String user)
   {
   return   staffMembers.get(user);
   }

   public Student getStudent(String user)
   {
    return students.get(user);
   }

   public int getStudentRows()
   {
        return students.size();
   }


}

/**** This is a student class which extends Account***/

/**** 这是一个扩展 Account 的学生类***/

public class Student extends Account {

    private String studentNRIC;
    private String diploma;
    private String gender;
    private double level;
    private int credits;
    private int age;
    private boolean partTime;
    private boolean havePc;
    private boolean haveChild;

    public Student(String n, String nr, String id, String dep, String user, String pass)
    {
        super(n, dep, user, pass, id);
        studentNRIC = nr;
    }

    public void setPartTime(boolean state)
    {
        if(state == true)
        {
            partTime = true;
        }
        else
        {
            partTime = false;
        }
    }

    public boolean getPartTime()
    {
        return partTime;
    }

    public void setHavePc(boolean state)
    {
        if(state == true)
        {
            havePc = true;
        }
        else
        {
            havePc = false;
        }
    }

    public boolean getHavePc()
    {
        return havePc;
    }

    public void setHaveChild(boolean state)
    {
        if(state == true)
        {
            haveChild = true;
        }
        else
        {
            haveChild = false;
        }
    }

    public boolean getHaveChild()
    {
        return haveChild;
    }
    public void setDiploma(String dip)
    {
        diploma = dip;
    }

    public String getDiploma()
    {
        return diploma;
    }

    public void setCredits(String cre)
    {
        credits = Integer.parseInt(cre);
    }

    public int getCredits()
    {
        return credits;
    }

    public void setGender(String g)
    {
        gender = g;
    }

    public String getGender()
    {
        return gender;
    }

    public void setAge(String a)
    {
        age = Integer.parseInt(a);
    }

    public int getAge()
    {
        return age;
    }
    public void setLevel(String lvl)
    {
        level = Double.parseDouble(lvl);
    }

    public double getLevel()
    {
        return level;
    }
    public void setStudentNRIC(String nr)
    {
        studentNRIC = nr;
    }

    public String getStudentNRIC()
    {
        return studentNRIC;
    }

}

/**** This is a the Account superclass***/

/**** 这是一个 Account 超类***/

public class Account {

    private String name;
    private String department;
    private String username;
    private String password;
    private String accountID;
    public Account()
    {
    }   
    public Account(String nm,String dep,String user,String pass, String accID) 
    {
        name = nm;
        department = dep;
        username = user;
        password = pass;
        accountID = accID;

    }

    public void setName(String nm)
    {
        name = nm;
    }

    public String getName()
    {
        return name;
    }

    public void setDep(String d)
    {
        department = d;
    }

    public String getDep()
    {
        return department;
    }

    public void setUser(String u)
    {
        username = u;
    }
    public String getUser()
    {
        return username;
    }

    public void setPass(String p)
    {
        password = p;
    }

    public String getPass()
    {
        return password;
    }

    public void setAccID(String a)
    {
        accountID = a;
    }

    public String getAccID()
    {
        return accountID;
    }
}

回答by Brian Agnew

Why not create an object that implements an interface in the fashion that JTable desires (an Objectarray), and provides a bridge to your existing map of Students ? So you can keep your existing data structure that is obviously working for you, and you're simply providing an adaptorfor the benefit of the view (the JTable).

为什么不创建一个对象,以 JTable 想要的方式(Object数组)实现接口,并为您现有的 Students 地图提供桥梁?因此,您可以保留显然对您有用的现有数据结构,并且您只是为了视图(JTable)的利益而提供一个适配器

From the link:

从链接:

An adapter allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface. The adapter translates calls to its interface into calls to the original interface, and the amount of code necessary to do this is typically small. The adapter is also responsible for transforming data into appropriate forms.

通过在使用原始接口的同时向客户端提供其接口,适配器允许类一起工作,而这些类通常由于不兼容的接口而无法一起工作。适配器将对其接口的调用转换为对原始接口的调用,并且执行此操作所需的代码量通常很少。适配器还负责将数据转换为适当的形式。

I would try notto change a working data structure to fit with a particular GUI component (what happens if at a later stage you want to display via HTML or similar) but adapt to each view as a requirement comes up.

我会尽量更改工作数据结构以适应特定的 GUI 组件(如果在稍后阶段您想通过 HTML 或类似方式显示会发生什么),而是在出现需求时适应每个视图。

回答by willcodejavaforfood

You have several options availableto you here. I would probably build my own TableModeland convert the HashMapinto a List, but that would require that accountIDwas part of Student and I cannot tell if it is from your post. So probably easier to create a multi dimensional array. To do this you need to examine every object in your HashMapand to do this we would use a 'loop'.

您可以在此处使用多种选择。我可能会建立自己的TableModel并将其转换HashMap为列表,但这需要它accountID是学生的一部分,我无法确定它是否来自您的帖子。所以创建多维数组可能更容易。为此,您需要检查您的每个对象,HashMap为此我们将使用“循环”。

First create the array to hold your data:

首先创建数组来保存您的数据:

Object[][] tableData = new Object[students.keySet().size()][numberOfColumns];

Replace numberOfColumns with the number of columns your table has.

将 numberOfColumns 替换为您的表的列数。

int index = 0;
for (String key : students.keySet())
{
    Student student = students.get(key);
    tableData[index][0] = student.getXXX
    tableData[index][1] = student.getYYY
    tableData[index][2] = student.getZZZ
    // and so forth
    index++;
}

So what we do here is create a loop that will examine every key in the students HashMap and with that key we retrieve the Student object and populate the array with the correct data.

所以我们在这里做的是创建一个循环,该循环将检查学生 HashMap 中的每个键,并使用该键检索 Student 对象并使用正确的数据填充数组。

This is to answer your question, but I would recommend that you take a look at the TableModel interface and build one around your HashMap of Students. More manly :)

这是为了回答您的问题,但我建议您查看 TableModel 接口并围绕您的 HashMap of Students 构建一个。更有男子气概:)

回答by Verhagen

The way to do this is by implementing the TableModelinterface for the student register (aka SortedMap). The TableModelis the table model representation of how the Swing JTable expects its data. The TableModelinterface, gives full flexibilty of providing that data.

实现这一点的方法是实现TableModel学生注册的接口(又名 SortedMap)。这TableModel是 Swing JTable 如何期望其数据的表模型表示。该TableModel接口提供了提供该数据的完全灵活性。

Once that implementation is created, creating a JTableis straight on:

一旦创建了该实现,就JTable可以直接创建一个:

// As StudentRegistration class
new JTable(new StudentTableModel(studentRegistration));
// Or as SortedMap<String, Student>
new JTable(new StudentTableModel(students));

In this scenario I expect that the plain SortedMap<String, Student>is not directly given, but a instance of StudentRegistration, which contains a SortedMap<String, Student>like that.

在这种情况下,我希望平原SortedMap<String, Student>不是直接给出的,而是 的实例StudentRegistration,其中包含SortedMap<String, Student>类似的。

/**
 * Models the {@link Student} entries as a Swing TableModel. 
 */
final public class StudentTableModel implements TableModel {
    /** The TableModel column names. */
    public final String columnNames[] = 
            new String[] {
                "Name", "Identification", "Age"
            };
    /** The list of TableModelListeners. */
    private final ArrayList<TableModelListener> tableModelListenerList = new ArrayList<TableModelListener>();
    /** The manager containing all the Student instances. */
    private final StudentRegistration register;


    public StudentTableModel(StudentRegistration register) {
        super();
        this.register = register;
    }


    public Class<?> getColumnClass(int columnIndex) {
        return null;
    }


    public int getColumnCount() {
        return columnNames.length;
    }

    public String getColumnName(int columnIndex) {
        return (columnIndex < columnNames.length) ? columnNames[columnIndex] : null;
    }

    public int getRowCount() {
        return register.getStudents().size();
    }


    public Object getValueAt(int rowIndex, int columnIndex) {
        // One solution
        String identification = register.getStudentIds().toArray()[rowIndex];
        Student student = register.getStudent(identification);
        // Other option
        SortedMap<String, Student> studentMap = register.getStudents();
        String[] studentIdArray = studentMap.keySet().toArray(new String[studentMap.keySet().size()]);
        Student student = studentMap.get(studentIdArray[rowIndex]);
        final Object result;
        switch (columnIndex) {
            case 0:
                result = student.getName();
                break;
            case 1:
                result = student.getIdentification();
                break;
            case 2:
                result = student.getAge();
                break;
            default:
                result = null;
        }
        return result;
    }


    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public void setValueAt(Object value, int rowIndex, int columnIndex) {
        // Just ignore, model is read only.
    }   


    public void addTableModelListener(TableModelListener tml) {
        if (! tableModelListenerList.contains(tml)) {
            tableModelListenerList.add(tml);
        }
    }

    public void removeTableModelListener(TableModelListener tml) {
        tableModelListenerList.remove(tml);
    }

}

PS: This sample comes partly from some other implementation, I just updated it to your scenario as described above. So it is quite possible that it contains some code glitzes. It is just provided to give you an idea on how a solution could look.

PS:此示例部分来自其他一些实现,我刚刚将其更新到您的场景中,如上所述。所以它很可能包含一些代码浮华。它只是为了让您了解解决方案的外观。

回答by Verhagen

Your DataStorageis like the StudentRegistrationis used in the sample code.

DataStorage就像StudentRegistration示例代码中使用的一样。

 // TIP: It can be handy to place the student in some order in the Map 
    //      (therefore using the sorted map).
    private SortedMap students = new TreeMap();  
    // QUESTION: Why not use argument name 'student'?
    public void addStudentMember(Student aAcc)
    {
        students.put(aAcc.getUser(),aAcc);
    }
    // Updated implementation
    public void addStudent(Student student)
    {
        students.put(student.getAccID(), student);
    }
 // QUESTION: Would a method name 'getNumberOfStudents' not be better?  
    public int getStudentRows()

For me it is a little unclear why Studentextends from Account. The account identification, is that an unique-id, through the hole system? Do staff (users) and student (users) all have that as unique identification? Where / who creates them? If not the system self, it can never be guranteed that they also enter correctly into your system. Even when checking on uniqueness within your system, helps. But who say not someone else (by accedent) used someone else his/her unique id? (How are the student and staff (accounts) created? If these id's are indeed unique, why not use those for placing the student into a SortedMap? If the sorting is not important. Why not just use a List of students?

对我来说有点不清楚为什么StudentAccount. 账号标识,是唯一的id,通过洞系统吗?员工(用户)和学生(用户)是否都具有唯一标识?在哪里/谁创建它们?如果不是系统本身,则永远无法保证它们也能正确进入您的系统。即使在检查系统内的唯一性时,也有帮助。但是谁说不是其他人(通过 accedent)使用了其他人他/她的唯一 ID?(如何创建学生和教职员工(帐户)?如果这些 id 确实是唯一的,为什么不使用它们将学生放入 SortedMap 中?如果排序不重要。为什么不只使用学生列表?

Is the name parameter unique (by which you place the student in the Map)?

name 参数是否唯一(您将学生放置在地图中的依据)?

Programming is little more then learning a programming language. As once understanding the OO-language Java it is good to read some more general programming books. In your specific case I would say start with Domain Driven Design. And then continue with books like these Test Driven Development, Refactoring to Patternsand Design Patterns.

编程只不过是学习一门编程语言。了解 OO 语言 Java 后,最好阅读一些更通用的编程书籍。在您的特定情况下,我会说从Domain Driven Design开始。然后继续阅读诸如测试驱动开发重构为模式设计模式之类的书籍。

回答by Emil

public class HashMapToJtable {
public static void main(String[] args) {
    final Map<String,String> st=new TreeMap<String, String>();
    st.put("1","one");
    st.put("2","two");
    st.put("3","three");
    JTable t=new JTable(toTableModel(st));
    JPanel p=new JPanel();
    p.add(t);
    JFrame f=new JFrame();
    f.add(p);
    f.setSize(200,200);
    f.setVisible(true);
}
public static TableModel toTableModel(Map<?,?> map) {
    DefaultTableModel model = new DefaultTableModel(
        new Object[] { "Key", "Value" }, 0
    );
    for (Map.Entry<?,?> entry : map.entrySet()) {
        model.addRow(new Object[] { entry.getKey(), entry.getValue() });
    }
    return model;
}
}

This is a sample code for populating a Jtable from a map.For your purpose you will have to override the toStringmethod in your Student and Staff classes.

这是用于从地图填充 Jtable 的示例代码。为了您的目的,您必须覆盖Student 和 Staff 类中的 toString方法。

回答by Pyrite

Going off of Emil's answer, but to support older version (tested with Java 1.3).

离开埃米尔的回答,但支持旧版本(用 Java 1.3 测试)。

import javax.swing.*;
import java.util.*;
import javax.swing.table.*;

public class HashMapToJtable {
 public static void main(String[] args) {
  final Map st = new TreeMap();
  st.put("1","one");
  st.put("2","two");
  st.put("3","three");
  JTable t=new JTable(toTableModel(st));
  JPanel p=new JPanel();
  p.add(t);
  JFrame f=new JFrame();
  f.add(p);
  f.setSize(200,200);
  f.setVisible(true);
 }

 public static TableModel toTableModel(Map map) {
     DefaultTableModel model = new DefaultTableModel (
   new Object[] { "Key", "Value" }, 0
  );
  for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
   Map.Entry entry = (Map.Entry)it.next();
   model.addRow(new Object[] { entry.getKey(), entry.getValue() });
  }
  return model;
 }

}