JAR Bundler using OSXAdapter causing application to lag or terminate

前端 未结 3 958
温柔的废话
温柔的废话 2020-11-22 14:36

I\'ve created a simple Java application that each second for for 10 seconds consecutive seconds adds a new row to a JTable. It consists of three classes.

3条回答
  •  攒了一身酷
    2020-11-22 15:03

    It looks like you're blocking the event dispatch thread(EDT). SwingWorker would be a better choice, but this example implements Runnable.

    Addendum: You might look at this project for an example of MVC architecture. It also shows how to construct a Mac OS application bundle without using JAR Bundler. More on MVC may be found here.

    As an aside, this example shows one approach to auto-scrolling a JTable. Click on the thumb to suspend scrolling; release to resume.

    Addendum: Your application lags for 10 seconds on startup. As this is the exact time for which the Controller sleeps, it's surely sleeping on the EDT. An sscce would be dispositive. Instead, do the work on another thread and update the model on the EDT. SwingWorker has a process() method that does so automatically, or you can use invokeLater() as shown below. Until your application is correctly synchronized, there's little hope of getting Apple events to work.

    Addendum: You can invoke isDispatchThread() in the Controller to check. The project cited includes a .dmg with a Mac application and an ant file that builds the bundle in situ via target dist2.

    Addendum: See also the alternate approaches shown here.

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.AdjustmentEvent;
    import java.awt.event.AdjustmentListener;
    import javax.swing.AbstractAction;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.DefaultTableModel;
    
    /** @seehttps://stackoverflow.com/questions/7519244 */
    public class TableAddTest extends JPanel implements Runnable {
    
        private static final int N_ROWS = 8;
        private static String[] header = {"ID", "String", "Number", "Boolean"};
        private DefaultTableModel dtm = new DefaultTableModel(null, header) {
    
            @Override
            public Class getColumnClass(int col) {
                return getValueAt(0, col).getClass();
            }
        };
        private JTable table = new JTable(dtm);
        private JScrollPane scrollPane = new JScrollPane(table);
        private JScrollBar vScroll = scrollPane.getVerticalScrollBar();
        private JProgressBar jpb = new JProgressBar();
        private int row;
        private boolean isAutoScroll;
    
        public TableAddTest() {
            this.setLayout(new BorderLayout());
            jpb.setIndeterminate(true);
            this.add(jpb, BorderLayout.NORTH);
            Dimension d = new Dimension(320, N_ROWS * table.getRowHeight());
            table.setPreferredScrollableViewportSize(d);
            for (int i = 0; i < N_ROWS; i++) {
                addRow();
            }
            scrollPane.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            vScroll.addAdjustmentListener(new AdjustmentListener() {
    
                @Override
                public void adjustmentValueChanged(AdjustmentEvent e) {
                    isAutoScroll = !e.getValueIsAdjusting();
                }
            });
            this.add(scrollPane, BorderLayout.CENTER);
            JPanel panel = new JPanel();
            panel.add(new JButton(new AbstractAction("Add Row") {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    addRow();
                }
            }));
            this.add(panel, BorderLayout.SOUTH);
        }
    
        private void addRow() {
            char c = (char) ('A' + row++ % 26);
            dtm.addRow(new Object[]{
                    Character.valueOf(c),
                    String.valueOf(c) + String.valueOf(row),
                    Integer.valueOf(row),
                    Boolean.valueOf(row % 2 == 0)
                });
        }
    
        private void scrollToLast() {
            if (isAutoScroll) {
                int last = table.getModel().getRowCount() - 1;
                Rectangle r = table.getCellRect(last, 0, true);
                table.scrollRectToVisible(r);
            }
        }
    
        @Override
        public void run() {
            while (true) {
                EventQueue.invokeLater(new Runnable() {
    
                    @Override
                    public void run() {
                        addRow();
                    }
                });
                EventQueue.invokeLater(new Runnable() {
    
                    @Override
                    public void run() {
                        scrollToLast();
                    }
                });
                try {
                    Thread.sleep(1000); // simulate latency
                } catch (InterruptedException ex) {
                    System.err.println(ex);
                }
            }
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    JFrame f = new JFrame();
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    TableAddTest nlt = new TableAddTest();
                    f.add(nlt);
                    f.pack();
                    f.setLocationRelativeTo(null);
                    f.setVisible(true);
                    new Thread(nlt).start();
                }
            });
        }
    }
    

提交回复
热议问题