Swing介面重新整理問題(轉)

來源:互聯網
上載者:User

標籤:

 

 

在Java Swing編程中,往往會遇到需要動態重新整理介面的時候,例如動態重新整理JLabel的文本,JTextField裡的文本等等。但是往往卻沒有達到我們預期的效果,我相信很多朋友都遇到過本文將要說的這個問題。

如的Swing介面中,我們期望在點擊按鈕時,Jlabel和JTextField裡的文本能不斷的變化,並即時地顯示出來。

這個例子中,我們期望點擊按鈕後,JLabel和JTextField中每隔一秒鐘重新整理一下文本,順序的顯示以下的幾句文本:

Button clickedStart to change text...接著顯示數字1到10action end


很多人都會像下面的代碼這樣實現這個功能:

MainFrame.java
package com.longyg.test;public class MainFrame extends javax.swing.JFrame {    public MainFrame() {        initComponents();    }    @SuppressWarnings("unchecked")    // <editor-fold defaultstate="collapsed" desc="Generated Code">                              private void initComponents() {        jLabel = new javax.swing.JLabel();        labelText = new javax.swing.JLabel();        jTextField = new javax.swing.JLabel();        fieldText = new javax.swing.JTextField();        button = new javax.swing.JButton();        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);        jLabel.setText("JLabel:");        labelText.setBorder(javax.swing.BorderFactory.createEtchedBorder());        jTextField.setText("JTextField: ");        button.setText("click");        button.addActionListener(new java.awt.event.ActionListener() {            public void actionPerformed(java.awt.event.ActionEvent evt) {                buttonActionPerformed(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()                .addGap(10, 10, 10)                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)                    .addComponent(button)                    .addGroup(layout.createSequentialGroup()                        .addComponent(jLabel)                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)                        .addComponent(labelText, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE))                    .addGroup(layout.createSequentialGroup()                        .addComponent(jTextField)                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)                        .addComponent(fieldText, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)))                .addContainerGap(17, Short.MAX_VALUE))        );        layout.setVerticalGroup(            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)            .addGroup(layout.createSequentialGroup()                .addGap(20, 20, 20)                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)                    .addComponent(jLabel)                    .addComponent(labelText, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))                .addGap(18, 18, 18)                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)                    .addComponent(jTextField)                    .addComponent(fieldText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)                .addComponent(button)                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))        );        pack();    }// </editor-fold>                            private void buttonActionPerformed(java.awt.event.ActionEvent evt) {                                               changeText("Button clicked");        try {            Thread.sleep(1000);        } catch (InterruptedException ex) {            ex.printStackTrace();        }        changeText("Start to change text...");        try {            Thread.sleep(1000);        } catch (InterruptedException ex) {            ex.printStackTrace();        }        for (int i = 0; i < 10; i++) {            changeText((i+1)+"");            try {                Thread.sleep(1000);            } catch (InterruptedException ex) {                ex.printStackTrace();            }        }        changeText("action end");    }                                          private void changeText(String text) {        labelText.setText(text);        fieldText.setText(text);    }        /**     * @param args the command line arguments     */    public static void main(String args[]) {        java.awt.EventQueue.invokeLater(new Runnable() {            public void run() {                new MainFrame().setVisible(true);            }        });    }    // Variables declaration - do not modify                         private javax.swing.JButton button;    private javax.swing.JTextField fieldText;    private javax.swing.JLabel jLabel;    private javax.swing.JLabel jTextField;    private javax.swing.JLabel labelText;    // End of variables declaration                   }

可以看到,在buttonActionPerformed方法中,我們多次調用了setText來期望改變JLabel和JTextField中的文本。

當我們運行這段代碼,你會很遺憾的發現,點擊click後,JLabel和JTextField中並沒有如我們所期望的不斷的更新並顯示不同的文本。而是點擊按鈕後,介面彷彿被卡住一樣,等過了一段時間後,顯示出最後一句文本“action end”。

為什麼會發生這樣奇怪的現象呢?

Java Swing中,介面重新整理是線程同步的,也就是說同一時間,只有一個線程能執行重新整理介面的代碼。如果要多次不斷地重新整理介面,必須在多線程中調用重新整理的方法。

本例中,在buttonActionPerformed方法中多次調用了setText方法來試圖重新整理JLabel和JTextField的文本。buttonActionPerformed方法運行在主線程中,所以每次調用setText都是運行在主線程中,而且是順序的執行的。在前面幾次調用setText後,線程並沒有退出,所以介面重新整理線程不能獲得執行重新整理的機會。而當最後一次setText後,線程退出,介面才能執行重新整理。所以我們只能看到最後一次setText的值。

因此,要解決這個問題,我們必須把buttonActionPerformed方法中的程式碼片段放到一個單獨的線程中執行。這樣它就不會使線程阻塞,當每次setText後,介面重新整理線程也能得到執行的機會,從而重新整理介面。

下面是修改後的代碼,只有buttonActionPerformed方法的代碼被修改,其他部分的代碼與上面的完全一致。

private void buttonActionPerformed(java.awt.event.ActionEvent evt) {                                               new Thread(new Runnable() {            @Override            public void run() {                changeText("Button clicked");                try {                    Thread.sleep(1000);                } catch (InterruptedException ex) {                    ex.printStackTrace();                }                changeText("Start to change text...");                try {                    Thread.sleep(1000);                } catch (InterruptedException ex) {                    ex.printStackTrace();                }                for (int i = 0; i < 10; i++) {                    changeText((i+1)+"");                    try {                        Thread.sleep(1000);                    } catch (InterruptedException ex) {                        ex.printStackTrace();                    }                }                changeText("action end");            }        }).start();    }

我們可以看到,新的buttonActionPerformed方法中,僅僅是把整個程式碼片段放在了一個線程中,並啟動了線程。

我們在每次setText後,都睡眠了1秒鐘,是為了看到介面真的即時的變化了,如果不睡眠,介面重新整理會一閃而過,不利於觀察。

再次運行代碼,會發現,終於得到了我們期望的效果:JLabel和JTextField中的文本動態變化了!

 

http://www.cnblogs.com/longyg/archive/2012/07/03/2575482.html

Swing介面重新整理問題(轉)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.