В этом примере показано диалоговое окно JDViewCustomer
, содержащее две кнопки <
и >
для асинхронной перезагрузки JTable
(я добавил несколько вызовов Thread.sleep()
для имитации загрузки сети).
Быстрое нажатие кнопок приводит к потере синхронизации приложения с экраном (см. Класс LoadCustomerOrdersWorker.java
, который также выполняет повторную проверку / перерисовку после загрузки данных).
Как я могу предотвратить это?
Test.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()";
}
}