4

Swingでデータを編集するためのダイアログボックスを作成しました。これには、、JTextArea2つのJButtonインスタンス(OKCancel)とJCheckBoxWrap Text)が含まれます。私がやりたかったのは、ユーザーがチェックボックスをクリックするたびにテキスト領域のテキストを折り返すことです。最初は、を使用してテキストをラップしていsetLineWrap(true)ます。

私は次のコードを使用しています:

    Runnable r1=new Runnable() {
        @Override
        public void run() {
            System.out.println("True");
            keyField.setLineWrap(true);
            keyField.requestFocus();
        }
    };

    Runnable r2=new Runnable() {
            @Override
            public void run() {
               System.out.println("FALSE");
               keyField.setLineWrap(false);
               keyField.repaint();
               keyField.requestFocus();
            }
     };
    final Thread t1=new Thread(r1) ;
    final Thread t2=new Thread(r2);

    final JCheckBox chkSwing = new JCheckBox("Word Wrap",true);

    chkSwing.addItemListener(
            new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    //To change body of implemented methods use File | Settings | File Templates.
                    if (e.getStateChange() == ItemEvent.SELECTED) {
                        t1.start();
                    } else if (e.getStateChange() != ItemEvent.SELECTED){
                        t2.start();
                    }
                }
            });

    panel.add(chkSwing);

問題

問題は、チェックボックスの選択を解除するとテキストの折り返しが解除されますが、チェックボックスを再度オンにしてもテキストが折り返されないことです。コンソールは、スレッドが呼び出されていることを示しています。テキスト領域のワードラップ動作を設定/設定解除するためにチェックボックスを機能させるにはどうすればよいですか?

4

4 に答える 4

6

これが動作するコードです。(いくつかの回答が指摘し損ねたものを強調するコメント付きのかわいいアニメーションのスクリーンショット付き。)

TextAreaWrapChooser

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;

class TextAreaWrapChooser {

    private JTextArea text = new JTextArea(8,30);

    TextAreaWrapChooser() {
        final JScrollPane scroll = new JScrollPane(text);

        JToolBar tb = new JToolBar();

        JCheckBox wrap = new JCheckBox("Line wrap", false);
        tb.add(wrap);
        wrap.addItemListener(new ItemListener() {
            // this method is called on the EDT
            public void itemStateChanged(ItemEvent ie) {
                boolean doWrap = ie.getStateChange() == ItemEvent.SELECTED;
                System.out.println("Wrap text: " + doWrap);
                text.setLineWrap( doWrap );
            }
        });

        // fill the text area
        try {
            File f = new File("TextAreaWrapChooser.java");
            FileReader fr = new FileReader(f);
            text.read( fr, f );
        } catch(Exception weTried) {
        }

        JPanel gui = new JPanel(new BorderLayout(2,2));
        gui.add(tb, BorderLayout.NORTH);
        gui.add(scroll, BorderLayout.CENTER);

        JOptionPane.showMessageDialog(null, gui);
    }

    public static void main(String[] args) {
        // construct/start the GUI on the EDT.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TextAreaWrapChooser();
            }
        });
    }
}
于 2012-04-25T09:49:52.257 に答える
5

別々に開始する理由はありませんThread。さらに悪いことに、非EDTのSwingコンポーネントを変更しないでください。Swingチュートリアルの同時実行性を参照してください

chkSwing.addItemListener(
  new ItemListener() {
    @Override
    public void itemStateChanged(ItemEvent e) {
       keyField.setLineWrap( e.getStateChange() == ItemEvent.SELECTED );
    }
  } );

それをします。

于 2012-04-25T08:12:51.250 に答える
4

なぜラップセットを別のスレッドで呼び出すのですか?それを呼んでもSwingUtilities.invokeLater()いいですか?

于 2012-04-25T08:10:29.820 に答える
4

Swingでは、グラフィカルコンポーネントに加えるすべての変更は、EventDispatchThreadで行う必要があります。

任意のスレッドからこれを行うには、メソッドを使用するのが最も簡単なSwingUtilities.invokeLater()方法です。

あなたの場合、Swingリスナーコールバックからコンポーネントを変更したいのですが、これはすでにEventDispatchThreadにいることを意味します。setLineWrapしたがって、リスナーからメソッドを呼び出すことができます。

于 2012-04-25T08:15:50.310 に答える