我制作了一个自定义ListModel,自定义CellRenderer来填充自定义对象JList。每个单元格包含两个图像和三个字符串。这个JList由并发中的三个线程动态填充,但首先我测试它是通过按一个按钮逐个添加对象。将对象添加到列表的方法作为链接到该按钮的ActionListener调用。
问题在于,当我的列表中显示许多对象时,我的程序开始滞后。然后我的问题是:什么是动态填充JList并使其成为"滞后"?
的最佳方式主要课程:
public class Main extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
JFrame main = new JFrame();
@SuppressWarnings("rawtypes")
JList tradesList = new JList();
TradesListModel lm = new TradesListModel();
@SuppressWarnings("unchecked")
public Main(){
GUI();
tradesList.setCellRenderer(new TradeRenderer());
tradesList.setModel(lm);
}
public void GUI(){
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setMinimumSize(new Dimension(450,700));
main.setLocationRelativeTo(null);
Container pane = main.getContentPane();
pane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1;
// BUTTONS PANEL
JPanel buttonsPanel = new JPanel();
buttonsPanel.setLayout(new GridBagLayout());
gbc.gridx = 0;
gbc.gridy = 0;
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
addTrade();
}
});
buttonsPanel.add(startButton, gbc);
gbc.gridx++;
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
lm.clear();
}
});
buttonsPanel.add(stopButton, gbc);
// LIST PANEL
JPanel listPanel = new JPanel();
listPanel.setLayout(new GridBagLayout());
listPanel.setBorder(BorderFactory.createTitledBorder("Trades List"));
JScrollPane scrollList = new JScrollPane(tradesList);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
listPanel.add(scrollList, gbc);
GridBagConstraints mc = new GridBagConstraints();
mc.insets = new Insets(5,5,5,5);
mc.fill = GridBagConstraints.BOTH;
mc.weightx = 1;
mc.gridx = 0;
mc.gridy = 0;
pane.add(buttonsPanel, mc);
mc.gridy++;
mc.weighty = 1;
pane.add(listPanel, mc);
main.setVisible(true);
}
public void addTrade(){
lm.add(new Trade("userr", "Platform", "#", "Noteeeeeessss", "Site", 999));;
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Main();
}
TradesListModel类:
package window;
import java.util.ArrayList;
import javax.swing.AbstractListModel;
import main.Trade;
public class TradesListModel extends AbstractListModel<Object>{
/**
*
*/
private static final long serialVersionUID = 1L;
private ArrayList<Trade> trades;
public TradesListModel(){
trades = new ArrayList<Trade>();
}
public void add(Trade trade){
trades.add(trade);
this.fireContentsChanged(this, 0, trades.size());
}
public void remove(int index){
trades.remove(index);
}
public void clear(){
trades.clear();
this.fireIntervalRemoved(this, 0, trades.size());
}
@Override
public int getSize() {
return trades.size();
}
@Override
public Object getElementAt(int index) {
return trades.get(index);
}
}
TradeRenderer类:
package window;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import main.Trade;
public class TradeRenderer extends JPanel implements ListCellRenderer<Object>{
/**
*
*/
private static final long serialVersionUID = 1L;
private GridBagConstraints gbc;
public TradeRenderer(){
this.setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
}
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus){
Trade trade = (Trade) value;
JLabel haveLabel = new JLabel(trade.getUsername());
JLabel wantLabel = new JLabel(trade.getNotes());
gbc.gridx = 0;
gbc.gridy = 0;
this.add(haveLabel, gbc);
gbc.gridy++;
this.add(wantLabel, gbc);
setEnabled(true);
return this;
}
}
贸易类:
package main;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
public class Trade {
private String username;
private String platform;
private String url;
private ArrayList<Item> have;
private ArrayList<Item> want;
private String notes;
private String site;
private long time;
public Trade(String username, String platform, String url, String notes, String site, long time){
this.username=username;
this.platform=platform;
this.url=url;
this.notes=notes;
this.site=site;
this.time=time;
have = new ArrayList<Item>();
want = new ArrayList<Item>();
}
public void addHave(Item i){
have.add(i);
}
public void addWant(Item i){
want.add(i);
}
public String getUsername(){
return username;
}
public String getPlatform(){
return platform;
}
public String getUrl(){
return url;
}
public String getNotes(){
return notes;
}
EDIT1:我尝试使用SwingWorker运行我的应用程序,但它没有改善延迟,并且随着许多新的Trade对象被添加到JList并显示,GUI开始滞后。 这是SwingWorker的实现:
private void start(){
SwingWorker<Boolean, Trade> worker = new SwingWorker<Boolean, Trade>(){
@Override
protected Boolean doInBackground() throws Exception {
for(int i=0; i<30; i++){
publish();
System.out.println("Trade added.");
}
return true;
}
@Override
protected void process(List<Trade> chunks) {
lm.add(new Trade("username", "platform", "#", "Noteeeeeessss", "Site", 999));
}
};
worker.execute();
}
该应用程序由这个新的主类启动:
package window;
import javax.swing.SwingUtilities;
public class App {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new MainFrame();
}
});
}
}