gpt4 book ai didi

java - 在不丢失同步的情况下加载 JTable

转载 作者:行者123 更新时间:2023-12-01 19:38:47 24 4
gpt4 key购买 nike

此示例具有 JDViewCustomer有两个按钮的对话框<>重新加载JTable异步(我添加了一些 Thread.sleep() 调用来模拟网络负载)。

快速按下按钮会导致应用程序与屏幕失去同步(请参阅类LoadCustomerOrdersWorker.java,它还会在加载数据后执行重新验证/重绘)。

如何防止这种情况发生?

测试.java

package testrepaint;

public class Test {

private static JFrame frame;

private static void createAndShowGUI() {
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

run();

frame.pack();
frame.setVisible(true);
}

private static void run() {

List<CustomerOrder> customerOrders = new ArrayList<>();
customerOrders.add(new CustomerOrder(15, 60.0f));
customerOrders.add(new CustomerOrder(16, 280.0f));
customerOrders.add(new CustomerOrder(17, 150.53f));
customerOrders.add(new CustomerOrder(18, 280.0f));

new JDViewCustomer(frame, true, customerOrders).setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

JDViewCustomer.java

package testrepaint;

public class JDViewCustomer extends javax.swing.JDialog {

private static final long serialVersionUID = 1L;

private static final ExecutorService SINGLE_THREAD_POOL = Executors.newSingleThreadExecutor();

private JPanel jPanelCustomerOrders;
private JPanel panelContainingTheOtherPanels;
private JPanel panelAbaixoDeCustomerOrders;
private JPanel panelContendoOsPedidos;

private final List<CustomerOrder> customerOrders;
private JPanel panelTituloPedidos;
private JLabel lblPedidos;

private JTable tableOrders;
private JPanel panelPagination;
private JButton btnPrevious;
private JButton btnNext;
private JLabel lblPageSelection;

private int currentPage = 1;
private int maxPage = 3;

public JDViewCustomer(java.awt.Frame parent, boolean modal, List<CustomerOrder> customerOrders) {
super(parent, modal);
this.customerOrders = new ArrayList<>(Objects.requireNonNull(customerOrders));

getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));

panelContainingTheOtherPanels = new JPanel();
panelContainingTheOtherPanels.setLayout(new BoxLayout(panelContainingTheOtherPanels, BoxLayout.Y_AXIS));
getContentPane().add(panelContainingTheOtherPanels);

layoutCustomerOrdersSection();
updateCustomerOrdersTable();

updateCurrentPageTextField();
toggleButtonsPreviousAndNext();

initComponents();
}

private void layoutCustomerOrdersSection() {

jPanelCustomerOrders = new JPanel();
jPanelCustomerOrders.setBackground(new Color(255, 255, 255));
panelContainingTheOtherPanels.add(jPanelCustomerOrders);
jPanelCustomerOrders.setLayout(new BoxLayout(jPanelCustomerOrders, BoxLayout.Y_AXIS));


panelAbaixoDeCustomerOrders = new JPanel();
panelAbaixoDeCustomerOrders.setBorder(new LineBorder(new Color(0, 0, 0), 1, true));
jPanelCustomerOrders.add(panelAbaixoDeCustomerOrders);
panelAbaixoDeCustomerOrders.setLayout(new BoxLayout(panelAbaixoDeCustomerOrders, BoxLayout.Y_AXIS));

panelTituloPedidos = new JPanel();
panelAbaixoDeCustomerOrders.add(panelTituloPedidos);
panelTituloPedidos.setBorder(new LineBorder(new Color(0, 0, 0), 1, true));
panelTituloPedidos.setBackground(Color.LIGHT_GRAY);

lblPedidos = new JLabel("Pedidos");
panelTituloPedidos.add(lblPedidos);

panelContendoOsPedidos = new JPanel();
panelContendoOsPedidos.setBorder(new CompoundBorder(new LineBorder(new Color(0, 0, 0), 1, true), new EmptyBorder(10, 10, 10, 10)));
panelContendoOsPedidos.setBackground(Color.WHITE);
panelAbaixoDeCustomerOrders.add(panelContendoOsPedidos);
panelContendoOsPedidos.setLayout(new BoxLayout(panelContendoOsPedidos, BoxLayout.Y_AXIS));

panelPagination = new JPanel();
panelAbaixoDeCustomerOrders.add(panelPagination);

addPaginationComponentsToPaginationPanel();
}

private void addPaginationComponentsToPaginationPanel() {
btnPrevious = new JButton("<");
btnPrevious.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
performButtonPrevious(e);
}
});
btnPrevious.setFont(new Font("Tahoma", Font.BOLD, 11));
panelPagination.add(btnPrevious);

lblPageSelection = new JLabel("0");
panelPagination.add(lblPageSelection);

btnNext = new JButton(">");
btnNext.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
performButtonNext(e);
}
});
btnNext.setFont(new Font("Tahoma", Font.BOLD, 11));
panelPagination.add(btnNext);
}

private void performButtonPrevious(ActionEvent e) {

if (currentPage > 1) {
currentPage -= 1;
updateCurrentPageTextField();
}

toggleButtonsPreviousAndNext();

loadCustomerOrders();
}

private void performButtonNext(ActionEvent e) {
if (currentPage < maxPage) {
currentPage += 1;
updateCurrentPageTextField();
}

toggleButtonsPreviousAndNext();

loadCustomerOrders();
}

private void loadCustomerOrders() {
LoadCustomerOrdersWorker worker = new LoadCustomerOrdersWorker(customerOrders, this);
SINGLE_THREAD_POOL.execute(worker);
}

private void toggleButtonsPreviousAndNext() {
togglePreviousButton();
toggleNextButton();
}

private void togglePreviousButton() {
btnPrevious.setEnabled(currentPage > 1);
}

private void toggleNextButton() {
btnNext.setEnabled(currentPage < maxPage);
}

private void updateCurrentPageTextField() {
lblPageSelection.setText(String.valueOf(currentPage));
}

private void updateCustomerOrdersTable() {

TableModel tableModel = instantiateAbstractTableModel();

tableOrders = new JTable(tableModel) {
private static final long serialVersionUID = 1L;

public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
};

centralizeTextInTableCells();

//tableOrders.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnModel colModel = tableOrders.getColumnModel();
colModel.getColumn(2).setPreferredWidth(80);
colModel.getColumn(3).setPreferredWidth(250);

// Disables manual reordering of columns.
tableOrders.getTableHeader().setReorderingAllowed(false);

JScrollPane scrollPane = new JScrollPane(tableOrders);
panelContendoOsPedidos.add(scrollPane);
}

private AbstractTableModel instantiateAbstractTableModel() {
return new AbstractTableModel() {
private static final long serialVersionUID = 1L;

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

@Override
public int getRowCount() {
return customerOrders.size();
}

@Override
public int getColumnCount() {
return 5;
}

@Override
public String getColumnName(int column) {
switch(column) {
case 0: return "Status";
case 1: return "Número";
case 4: return "Total";
default: return "";
}
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
CustomerOrder customerOrder = customerOrders.get(rowIndex);
switch(columnIndex) {
case 0: return customerOrder;
case 1: return "#" + String.valueOf(customerOrder.getNumber());
case 4: return String.format("%.2f", customerOrder.getTotal());
default: return "";
}
}

@Override
public Class<?> getColumnClass(int columnIndex) {
switch(columnIndex) {
case 0: return CustomerOrder.class;
case 1: return String.class;
case 4: return String.class;
default: return Object.class;
}
}
};
}

private void centralizeTextInTableCells() {
DefaultTableCellRenderer stringCellRenderer = (DefaultTableCellRenderer)tableOrders.getDefaultRenderer(String.class);
stringCellRenderer.setHorizontalAlignment(JLabel.CENTER);
tableOrders.setDefaultRenderer(String.class, stringCellRenderer);
}

private void initComponents() {

setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Ver Cliente");

pack();

// Para centralizar o JDialog em relação a seu parent.
setLocationRelativeTo(getParent());

}
}

LoadCustomerOrdersWorker.java

package testrepaint;

public class LoadCustomerOrdersWorker extends SwingWorker<Void, Void> {

private final List<CustomerOrder> customerOrders;
private final JDViewCustomer jDialogViewCustomer;

public LoadCustomerOrdersWorker(List<CustomerOrder> customerOrders, JDViewCustomer jDialogViewCustomer) {
this.customerOrders = customerOrders;
this.jDialogViewCustomer = jDialogViewCustomer;
}

@Override
protected Void doInBackground() throws Exception {

this.customerOrders.clear();
Thread.sleep(300);
this.customerOrders.add(new CustomerOrder(15, 60.0f));
Thread.sleep(300);
this.customerOrders.add(new CustomerOrder(16, 280.0f));
Thread.sleep(300);
this.customerOrders.add(new CustomerOrder(17, 150.53f));
Thread.sleep(300);
this.customerOrders.add(new CustomerOrder(18, 280.0f));
Thread.sleep(300);
this.customerOrders.add(new CustomerOrder(19, 280.0f));
Thread.sleep(300);

return null;
}

@Override
protected void done() {
jDialogViewCustomer.revalidate();
jDialogViewCustomer.repaint();
}
}

CustomerOrder.java

package testrepaint;

public class CustomerOrder {

private final int number;
private final float total;


public CustomerOrder(int number, float total) {
this.number = number;
this.total = total;
}

public int getNumber() {
return number;
}

public float getTotal() {
return total;
}

@Override
public String toString() {
return "toString()";
}
}

最佳答案

您更新表格的基本概念是错误的:

  1. TableModel 应包含数据结构。也就是说 ArrayList 应该是 TableModel 的一部分。然后,TableModel 应该具有动态修改数据的方法。

  2. 应该对 TableModel 进行更新。然后 TableModel 将通知表重新绘制自身。

  3. 参见Table Row Model有关如何创建包含上述建议的自定义 TableModel 的分步示例。

  4. 对 Swing 组件(及其数据)的更新必须在事件调度线程 (EDT) 上完成。在 doInBackground() 方法中执行的代码不会在 EDIT 上运行。因此,您需要发布结果,然后使用 CustomOrder 更新 TableModel,而不是直接更新 ArrayList。

阅读 Swing 教程中关于 Tasks That Have Interim Results 的部分有关显示 publish() 方法如何工作的示例。 publish() 方法中执行的代码确实在 EDT 上执行。

  • 不需要在done()方法中调用revalidate()和repaint()。如前所述,当您更新 TableModel 时,它会导致表自动更新。
  • 关于java - 在不丢失同步的情况下加载 JTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56245000/

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