java - 在另一个线程中更新 JScrollPane 中的表

标签 java

我正在制作一个动画,当我按下按钮时,相应表格的每一行都会从上到下逐一突出显示。但是,当动画开始时,表格无法正确重绘,表格的用户界面以某种方式损坏。下面是我的代码。

/*

* 要更改此模板,请选择“工具” | “模板 * 并在编辑器中打开模板。 */

/* * 表格框架.java * * 创建于2010/8/5 下午 04:07:10 */

封装测试; 导入 javax.swing.; 导入 javax.swing.table.; /** * * @author 管理员 */ 公共(public)类 TableFrame 扩展 javax.swing.JFrame { StringThread1 t = null;

公共(public) JTable 表; 公共(public) JScrollPane getScrollPane(){ 返回 this.jScrollPane1; } /** 创建新表单TableFrame */ 公共(public)表框架(){ 初始化组件(); 表 = new JTable(new javax.swing.table.DefaultTableModel(100, 2)); this.jScrollPane1.setViewportView(table); for(int i = 0; i < 100; i++){ for(int j = 0; j < 2; j++){ table.setValueAt(new Integer(i), i, j); } } t = new StringThread1(this); }

/** This method is called from within the constructor to
 * initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is
 * always regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jScrollPane1 = new javax.swing.JScrollPane();
    jButton1 = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jScrollPane1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

    jButton1.setText("jButton1");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                .addGroup(layout.createSequentialGroup()
                    .addGap(32, 32, 32)
                    .addComponent(jButton1)))
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jButton1)
            .addGap(18, 18, 18)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 201, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(48, Short.MAX_VALUE))
    );

    pack();
}// </editor-fold>                        

boolean play = false;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    this.t.start();
        play = !play;
}                                        

class StringThread1 extends Thread
{
    private TableFrame str;

    StringThread1 (TableFrame s)
    {
        str=s;
    }

    public void run() {
        int y = 0;
        while(true){
            try{
                System.out.println("y " + String.valueOf(y));
                this.sleep(500);
                this.str.table.setRowSelectionInterval(y, y);
                int rp = y * this.str.table.getRowHeight();
                int halfHeight = this.str.getScrollPane().getHeight() / 2 - this.str.table.getRowHeight();
                if(rp + this.str.table.getRowHeight() * 2 >= this.str.getScrollPane().getVerticalScrollBar().getValue() + this.str.getScrollPane().getHeight()){
                    this.str.getScrollPane().getVerticalScrollBar().setValue((y) * this.str.table.getRowHeight());
                }

                else{
                    this.str.getScrollPane().getVerticalScrollBar().setValue(0);
                }


                if(y == 99){
                    y = 0;
                }y+= 1;
            } catch(InterruptedException e){}
        }
    }
}

/**
* @param args the command line arguments
*/
public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new TableFrame().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JButton jButton1;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration                   

}

最佳答案

有一条黄金法则 - 不要在事件调度线程之外的线程中操作显示的 GUI 项目。因此,您需要使用 SwingUtilities.invokeLater() 来执行这些调用:

this.str.table.setRowSelectionInterval(y, y);

this.str.getScrollPane().getVerticalScrollBar().setValue((y) * this.str.table.getRowHeight());

this.str.getScrollPane().getVerticalScrollBar().setValue(0);

您可以将每个都包装起来,或者将它们全部包装在一次调用中。

关于java - 在另一个线程中更新 JScrollPane 中的表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3446643/

相关文章:

java - 哪个类继承了Java的main方法?

java - layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) 方法中的 offsets.length 或 spans.length 是什么?

java - Java中设计模式的类库?

java - 如何从 Android 手机读取 Java 中的 CPU "stats"?

java - Android:使录制的pcm原始数据可播放

java - 如何在 Android 中每天中午 12 点到下午 6 点之间安排一些工作,间隔为 60 分钟?

java - Apache Commons Email v1.1 更改超时时间

java - 通过不带Thread.sleep()的Runtime.getRuntime()。exec解密文件

Java executorService.shutdownNow() 不取消或中断线程

java - 使用 BoofCV 跟踪快速移动的基准点