如下图,目标是,当我点击JTable的某一行(JTable的内容来自左边的文件),在GUI的黄色框,将要显示selected行的最后一个int数据。
简短提一下为什么写这篇东西:在功能实现过程中遇到了挺多的有意义的困难,是课上老师没有讲过的,接下来一个个列出。
问题一:第一个遇到的问题是不熟悉ListSelectionListener的用法,更不知道ListSelectionModel的用法,认为ListSelectionModel是个可有可无的选择(说出来还有点不好意思呢)。
这里就讲一下ListSelectionModel的设置方法,先从table里挖出selectionMode, 然后给selectionMode加上ListSelectionListener, 最后再给予设置(我自己的版本中只允许单选),所以就是:
selectionMode = table.getSelectionModel(); selectionMode.addListSelectionListener(this); selectionMode.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
问题二: 解决完第一个问题我的码看起来是这样的:
public class Main_panel extends JPanel{ private Research_and_InfoPanel research_and_infoPanel; private JScrollPane scrollpane; private ListSelectionModel listSelectionModel; Main_panel(){ super(); BoxLayout main_layout = new BoxLayout(this, BoxLayout.X_AXIS); setLayout(main_layout); //creation panels research_and_infoPanel = new Research_and_InfoPanel(); //database for TablePanel Vector<String> column_names = new Vector<String>(); column_names.add("Title"); column_names.add("Author"); column_names.add("Year"); column_names.add("Path"); Vector<Object> data = new Vector<Object>(); data = proof_main.libreria.merge_table_elements(); //define JTable JTable table = new JTable(data,column_names); //define Jscrollpane that contain the table scrollpane = new JScrollPane(table,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED ); listSelectionModel = table.getSelectionModel(); listSelectionModel.addListSelectionListener(new SelectionListener()); scrollpane.setPreferredSize(new Dimension( 450, 550)); research_and_infoPanel.setPreferredSize(new Dimension( 250, 550)); add(scrollpane); add(research_and_infoPanel); } class SelectionListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { // TODO Auto-generated method stub int selectedRow = table.getSelectedRow(); String title = (String) table.getValueAt(selectedRow, 1); //research_and_infoPanel.displayInfo(selectedRow, title); <--这是我将来想要调用的函数,属于research_and_infoPanel 也就是黄色方块 } } }
可以看到,我的JTable, JScrollPanel 和 ListSelectionListener 以及他的valueChanged函数都在 Main_Panel 当中,有点混乱,所以我就想要分开Main_Panel 和其他部分元素,建了一个新的JScrollPanel子类,另开一页。效果是这样的:
public class myScrollPane extends JScrollPane implements ListSelectionListener { private JTable table; private ListSelectionModel selectionMode; myScrollPane(){ super(); //database for table Vector<String> column_names = new Vector<String>(); column_names.add("Title"); column_names.add("Author"); column_names.add("Year"); column_names.add("Path"); Vector<Object> data = new Vector<Object>(); data = proof_main.libreria.merge_table_elements(); //define JTable and add it in scrollpane table = new JTable(data,column_names); setViewportView(table); //set scrollpane setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS); setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED); //set selectionMode and add Listener selectionMode = table.getSelectionModel(); selectionMode.addListSelectionListener(this); selectionMode.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } public void valueChanged(ListSelectionEvent e) { //rows count from zero int selectedRow = table.getSelectedRow(); selectedRow++; Main_panel.research_and_infoPanel.displayInfo(selectedRow); } }
又记起了一个因为无知而浪费了不少时间的问题,就是16行, 我天真地以为只要用 add(table) 就有效,结果Table显示不出来,仔细看了下手册发现需要用setViewportview(table).
OK, 这样总体上看起来清爽整齐多了,我也“解禁”了research_and_infoPanel.displayInfo(selectedRow)函数。接下来我们看看这个函数是怎样运作的。
public class Research_and_InfoPanel extends JPanel{ private JPanel research_panel, info_panel; private JLabel label1; Research_and_InfoPanel(){ research_panel = new JPanel(); info_panel = new JPanel(); research_panel.setMaximumSize( new Dimension( 250, 500) ); info_panel.setMaximumSize( new Dimension( 250, 500) ); research_panel.setBackground(Color.gray); info_panel.setBackground(Color.yellow); BoxLayout secondary_layout = new BoxLayout(this, BoxLayout.Y_AXIS); setLayout(secondary_layout); label1 = new JLabel(); info_panel.add(label1); add(research_panel); add(info_panel); } public void displayInfo(int numberRow){ char filetype = proof_main.libreria.check_filetype(numberRow); Vector<Object> extra_info = proof_main.libreria.get_info(filetype,numberRow); switch(filetype){ case ‘E‘: { label1.setText(extra_info.get(0).toString()); } break; case ‘M‘: { label1.setText(extra_info.get(0).toString()); } break; case ‘V‘: { label1.setText(extra_info.get(0).toString()); } break; } } } //以下是libreria.get_info(filetype,numberRow)函数内容 public Vector<Object> get_info(char filetype, int number){ Vector<Object> extra_info = new Vector<Object>(); extra_info.clear(); int bound_E = record_E.media_files.size(); int bound_M = bound_E + record_M.media_files.size(); switch(filetype){ case ‘E‘: { extra_info.addElement(record_E.media_files.get(number-1).get_n_pages()); } break; case ‘M‘: { number = number-bound_E; extra_info.addElement(record_M.media_files.get(number-1).get_duration()); extra_info.addElement(record_M.media_files.get(number-1).get_sample_rate()); } break; case ‘V‘: { number = number-bound_M; extra_info.addElement(record_V.media_files.get(number-1).get_duration()); } break; } return extra_info; }
上面贴的码分两部分,第一部分是Research_and_InfoPanel类,里面有JLabel,故名有两个panel,但这不是我们的重点,重点在它在displayInfo中的码,因为这里面才是把数字挖出来的码。可以看到,挖出的数据由proof_main.libreria.get_info(filetype,numberRow)提供,这里提一下我有三种不同类型的文件,是E,V和M,读者们可以当这事儿没有。而numberRow则是被鼠标或键盘选中的行,从上上个例子中用table.getSelectedRow挖出,被传啊传的直到传给libreria.get_info()。在这篇里我就不提供别的没有重要联系的码,但是需要解释一下另有load()函数负责从文件中读取数字并装入record_E.media_files,record_M.media_files,record_V.media_files中的,大家可以想象以上第60,62,68行其实是对应的数字(在第一张图片中,相对应的数字是30)。 load()函数我以后会在未来的新文中献出。
《点击JTable的某一个行,在另一个JPanel显示其相对应内容的功能实现》