我有带有 4 个选项卡的 JTabbedPane。JtabbedPane 位于 JLayeredPane 上。第一个和第四个选项卡包含带有自定义模型的 JTable。每个表每 5-10 秒刷新一次。
当第一个选项卡处于活动状态,并且 4 号的 JTable 刚刚完成刷新时,我可以看到 1 号的 4 号的内容。看截图。
当我单击另一个选项卡或最小化窗口时,这种奇怪的效果就消失了。直到在第 4 个选项卡上再次刷新该表。
使用 Future<> 对象完成刷新。我在 Netbeans 中使用了 Swing GUI 构建器,所以我有大量的代码。会发布任何可能有用的文章。
我试图重新验证jTabbedPane,没有效果。表和 jScrollPanes 都将 opaque 属性设置为 true。所以我尝试使用 SwingUtilities.invokeLater()。它有点帮助 - 现在第一次内容更新进展顺利,但后来 - 同样的问题。
第二个表模型具有更新其内容的方法
public void setData(LinkedList<Object[]> __rows) {
NewDevsTableModel.__rows = __rows;
fireTableDataChanged();
}
它在这里使用(我在这里添加了 SwingUtilities)
static class checkNew implements Callable<Boolean> {
@Override
public Boolean call() {
ServiceMessage sm = ServiceMessage.getNewList();
try {
connect();
os.write(sm.serialize());
for (int i=0; i<10; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {}
if (is.available() > 0) {
break;
}
if (i == 9) {
disconnect();
return false;
}
}
byte[] actByte = new byte[is.available()];
is.read(actByte);
try {
sm = ServiceMessage.Deserialize(actByte); //may be there are no new devices
if (sm.getType() == ServiceMessageType.NODATA) {
MainWindow.jTabbedPane1.setEnabledAt(3, false);
if (MainWindow.jTabbedPane1.getSelectedIndex() == 3) {
MainWindow.jTabbedPane1.setSelectedIndex(0);
}
return true;
} else {
return false; //wrong answer type
}
} catch (ClassCastException | StreamCorruptedException e) {
//remember selection and scroll
final int scroll = MainWindow.jScrollPane3.getVerticalScrollBar().getValue();
final int[] rows = MainWindow.newDevsTable.getSelectedRows();
int col = MainWindow.devicesTable.getSelectedColumn();
String[] parts = new String(actByte).split("\n");
final LinkedList<Object[]> l = new LinkedList();
for (int i=0; i<parts.length; i++) {
String[] dev = parts[i].split(";", -1);
String descr = dev[2];
boolean iptype = (!dev[3].equals("-"));
String address = dev[4];
boolean atmtype = (dev[5].equals("+"));
if (MainWindow.newDevsTable.getRowCount() >= (i+1)) {
if ((MainWindow.newDevsTable.getValueAt(i, 4) != null) && !MainWindow.newDevsTable.getValueAt(i, 4).equals("")) {
descr = MainWindow.newDevsTable.getValueAt(i, 4).toString();
}
}
Object[] o = {dev[0], dev[1], MainWindow.language[180], MainWindow.language[4], descr, iptype, address, atmtype};
l.add(o);
}
if (!l.isEmpty()) {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
MainWindow.newDevsPanel.setVisible(true);
MainWindow.jTabbedPane1.setEnabledAt(3, true);
((NewDevsTableModel)MainWindow.newDevsTable.getModel()).setData(l);
ButtonColumn buttonColumn = new ButtonColumn(MainWindow.newDevsTable, addAction, 2, true);
buttonColumn = new ButtonColumn(MainWindow.newDevsTable, rejAction, 3, false);
//put selection back
for (int i=0; i<rows.length; i++) {
MainWindow.newDevsTable.addRowSelectionInterval(rows[i], rows[i]);
}
MainWindow.jScrollPane3.getVerticalScrollBar().setValue(scroll);
}
});
} else {
MainWindow.jTabbedPane1.setEnabledAt(3, false);
if (MainWindow.jTabbedPane1.getSelectedIndex() == 3) {
MainWindow.jTabbedPane1.setSelectedIndex(0);
}
}
return true;
}
} catch (IOException e) {
disconnect();
return false;
} catch (ClassNotFoundException e) {
return false;
}
}
}
我以这种方式提交任务
public static Future<Boolean> checkNewDevices() {
final Future<Boolean> task;
task = service.submit(new checkNew());
return task;
}
要自动刷新,我使用单独的线程
public class CheckNewPassThread extends Thread {
int pause = 10000;
@Override
public void run() {
for (;;) {
HostConnection.checkNewDevices();
try {
Thread.sleep(pause);
} catch (InterruptedException e) {}
}
}
}
打开窗口时启动
private void formWindowOpened(java.awt.event.WindowEvent evt) {
HostConnection.getData();
HostConnection.getDeviceAddress();
RefreshData refreshThread = new RefreshData();
refreshThread.start();
new CheckNewPassThread().start();
}