gpt4 book ai didi

Java:在后台使用大量行更新 JTable

转载 作者:行者123 更新时间:2023-12-03 23:05:40 25 4
gpt4 key购买 nike

我正在编写一个简单的 Java Swing 实用程序,它将从 MQ JMS 服务器读取消息并将它们显示在 JTable 中。

private void getMessages() {
try {
if (null != Queue) {
Queue.close(); //Close previous queue connection if there is one.
}
Queue = new MQQueue(QueueManager, tableQueues.getValueAt(tableQueues.getSelectedRow(), 1).toString(), MQConstants.MQOO_INPUT_SHARED | MQConstants.MQOO_BROWSE | MQConstants.MQOO_OUTPUT, queueManager, null, null);
int count = 0;
modelMessages.setRowCount(0);
MQGetMessageOptions getOptions = new MQGetMessageOptions();
getOptions.options = MQConstants.MQGMO_BROWSE_FIRST;
ArrayList<Object[]> rows = new ArrayList<Object[]>();
while(true) {
if (count > 0) {
getOptions.options = MQConstants.MQGMO_BROWSE_NEXT;
}
MQMessage message = new MQMessage();
try {
Queue.get(message, getOptions);
byte[] b = new byte[message.getMessageLength()];
message.readFully(b);
rows.add(new Object[]{count + 1, new String(b)});
modelMessages.addRow(new Object[]{count + 1, new String(b)});
message.clearMessage();
count++;
}
catch (IOException e) {
break;
}
catch (MQException e) {
if (e.completionCode == 2 && e.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) {
break;
}
}
}
modelMessages.fireTableDataChanged();
} catch (MQException e) {
txtMessage.setText("MQJE001: Completion Code '" + e.completionCode + "', Reason '" + e.reasonCode + "'.");
modelMessages.setRowCount(0);
modelMessages.fireTableDataChanged();
}
}

这适用于较小的队列,但对于较大的队列,填充此表需要一段时间,与此同时,Swing 应用程序被卡住,因此我正在研究在后台填充 JTable 的方法,同时不仅保留应用程序但在此期间 JTable 本身可用且可滚动。

我对线程不是很熟悉,我尝试了一些方法,例如将某些部分包装在 SwingUtilities.invokeLater 中并实现 doInBackground(),但似乎没有任何效果。有人可以指出我如何继续进行的正确方向吗?

编辑

根据下面的回复,这里是解决方案:

public class GetMessagesWorker extends SwingWorker<DefaultTableModel, Object[]> {

//http://stackoverflow.com/questions/22072480/java-updating-jtable-with-lots-of-rows-in-the-background#

private final DefaultTableModel model;

public GetMessagesWorker(DefaultTableModel model){
this.model = model;
}

@Override
protected DefaultTableModel doInBackground() throws Exception {
try {
if (null != Queue) {
Queue.close(); //Close previous queue connection if there is one.
}
Queue = new MQQueue(QueueManager, tableQueues.getValueAt(tableQueues.getSelectedRow(), 1).toString(), MQConstants.MQOO_INPUT_SHARED | MQConstants.MQOO_BROWSE | MQConstants.MQOO_OUTPUT, queueManager, null, null);
int count = 0;
modelMessages.setRowCount(0);
MQGetMessageOptions getOptions = new MQGetMessageOptions();
getOptions.options = MQConstants.MQGMO_BROWSE_FIRST;
while(true) {
if (count > 0) {
getOptions.options = MQConstants.MQGMO_BROWSE_NEXT;
}
MQMessage message = new MQMessage();
try {
Queue.get(message, getOptions);
byte[] b = new byte[message.getMessageLength()];
message.readFully(b);
Object[] row = {count + 1, new String(b)};
publish(row);
message.clearMessage();
count++;
if (isCancelled()) {
modelMessages.setRowCount(0);
count = 0;
message.clearMessage();
return model;
}
}
catch (IOException e) {
break;
}
catch (MQException e) {
if (e.completionCode == 2 && e.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) {
break;
}
}
}
//modelMessages.fireTableDataChanged();
} catch (MQException e) {
txtMessage.setText("MQJE001: Completion Code '" + e.completionCode + "', Reason '" + e.reasonCode + "'.");
modelMessages.setRowCount(0);
modelMessages.fireTableDataChanged();
}
return model;
}

@Override
protected void process(List<Object[]> chunks){
for(Object[] row : chunks){
model.addRow(row);
}
}

}

这是监听器:

    tableQueues = new JTable(modelQueues);
tableQueues.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
txtMessage.setText("");
if (tableQueues.getSelectedRow() > -1) {
gmw.cancel(false);
gmw = new GetMessagesWorker(modelMessages);
gmw.execute();
}
}
}
});

最佳答案

这是由于 Swing 架构。您必须了解,执行监听器的同一个线程负责更多的事情(例如,刷新您的 UI)。

在您的情况下,我会使用 SwingWorker。这是一种特定于 Swing 的后台线程,具有特殊功能,可以在执行长任务时安全地将更新发送到您的 UI。您将在后台完成您的长期任务,并为它检索到的每个相关结果调用 publish()。每次调用 publish() 时,都会调用您的 process() 方法(在后台向主线程发送更新),在那里您可以更新表模型.

在这里您可以找到关于 SwingWorker 的更多信息:

http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

关于Java:在后台使用大量行更新 JTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22072480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com