13 April 2015

(Java) SWTのテキスト表示ダイアログ作成法

SWTでテキストを表示するダイアログを実装する方法メモ

Textヴィジェットを使う(最も単純で簡単な方法)

20150413-swt-textview.jpg

public class TextViewerTest extends Shell {
    public static void main(String[] args) {
        try {
            Display display = new Display();
            Shell shell = new TextViewerTest(display, SWT.SHELL_TRIM);
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
            display.dispose();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * @param display
     * @param style
     */
    public TextViewerTest(Display display, int style) {
        super(display, style);
        final Shell shell = this.getShell();
        // レイアウトの定義
        shell.setSize(450, 350);
        this.setText("テキスト ビューワ");
        shell.setLayout(new GridLayout(2, false));
        // レイアウトに配置する要素(ヴィジェット)
        Label label1 = new Label(shell, SWT.NONE);
        label1.setText("Text");
        
        final Text t = new Text(shell, SWT.READ_ONLY | SWT.MULTI | SWT.V_SCROLL
                | SWT.H_SCROLL | SWT.WRAP);
        GridData gridData = new GridData();
        gridData.horizontalAlignment = SWT.FILL;
        gridData.grabExcessHorizontalSpace = true;
        gridData.verticalAlignment = SWT.FILL;
        gridData.grabExcessVerticalSpace = true;
        t.setLayoutData(gridData);
        t.setText("まだファイルが選択されていません");
        
        Composite composite = new Composite(shell, SWT.NONE);
        composite.setLayout(new FillLayout(SWT.HORIZONTAL));
        Button btnFileOpen = new Button(composite, SWT.NULL);
        btnFileOpen.setText("ファイルを開く");
        Button btnClose = new Button(composite, SWT.NULL);
        btnClose.setText("閉じる");
        gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
        gridData.horizontalSpan = 2;
        composite.setLayoutData(gridData);
        
        // 「ファイルを開く」ボタンの処理
        btnFileOpen.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                // 読み込み用ダイアログを開く
                FileDialog fileDlg = new FileDialog(shell, SWT.OPEN);
                String[] exts = { "*.txt", "*.*" };
                fileDlg.setFilterExtensions(exts);
                String[] filterNames = { "テキストファイル(*.txt)", "全てのファイル(*.*)" };
                fileDlg.setFilterNames(filterNames);
                fileDlg.setText("テキストファイルを開く");
                String selectedFilename = fileDlg.open();
                if (selectedFilename != null && !selectedFilename.isEmpty()) {
                    ReadFromTextFile(t, selectedFilename);
                }
            }
            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
        
        // 「閉じる」ボタンの処理
        btnClose.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                shell.dispose();
            }
            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
    }
    
    /**
     * テキストファイルを読み込み、Textヴィジェットに表示する
     * @param t
     * @param filename
     */
    private void ReadFromTextFile(Text t, String filename) {
        try {
            File file = new File(filename);
            BufferedReader br = new BufferedReader(new FileReader(file));
            // ファイル末端まで、各行をstrに読み込んでからTextヴィジェットに追加していく
            String str = br.readLine();
            t.setText("");
            while (str != null) {
                t.append(str + "\n");
                str = br.readLine();
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /*
     * (非 Javadoc)
     * 
     * @see org.eclipse.swt.widgets.Decorations#checkSubclass()
     */
    @Override
    protected void checkSubclass() {
        // super.checkSubclass();       // 自動作成後、手動でコメントアウト
    }
}

Browserヴィジェットを使う

20150413-swt-browserview.jpg

 〜 略 〜
        shell.setLayout(new GridLayout(2, false));
        // レイアウトに配置する要素(ヴィジェット)
        Label label1 = new Label(shell, SWT.NONE);
        label1.setText("Text");
        
        final Browser browser = new Browser(shell, SWT.NONE);
        GridData gridData = new GridData();
        gridData.horizontalAlignment = SWT.FILL;
        gridData.grabExcessHorizontalSpace = true;
        gridData.verticalAlignment = SWT.FILL;
        gridData.grabExcessVerticalSpace = true;
        browser.setLayoutData(gridData);
        
        Composite composite = new Composite(shell, SWT.NONE);
        composite.setLayout(new FillLayout(SWT.HORIZONTAL));
        Button btnFileOpen = new Button(composite, SWT.NULL);
        btnFileOpen.setText("ファイルを開く");
        Button btnClose = new Button(composite, SWT.NULL);
        btnClose.setText("閉じる");
        gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
        gridData.horizontalSpan = 2;
        composite.setLayoutData(gridData);
        
        // 「ファイルを開く」ボタンの処理
        btnFileOpen.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                // 読み込み用ダイアログを開く
                FileDialog fileDlg = new FileDialog(shell, SWT.OPEN);
                String[] exts = { "*.txt", "*.*" };
                fileDlg.setFilterExtensions(exts);
                String[] filterNames = { "テキストファイル(*.txt)", "全てのファイル(*.*)" };
                fileDlg.setFilterNames(filterNames);
                fileDlg.setText("テキストファイルを開く");
                String selectedFilename = fileDlg.open();
                if (selectedFilename != null && !selectedFilename.isEmpty()) {
                    ReadFromTextFile(t, selectedFilename);
                }
            }
            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
 〜 略 〜
    }
    
    private void ReadFromTextFile_Browser(Browser browser, String filename) {
        try {
            File file = new File(filename);
            BufferedReader br = new BufferedReader(new FileReader(file));
            // ファイルの各行を読み込み、StringBuilderに追加していく
            String str = br.readLine();
            StringBuilder strAll = new StringBuilder();
            while (str != null) {
                strAll.append(str);
                str = br.readLine();
            }
            br.close();
            // 全ての行が追加されたStringBuilderの内容をBrowserヴィジェットに流し込む
            browser.setText(strAll.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 〜 略 〜
}

わざわざ、ファイルを手動で読み込まなくても、Browser.setUrlメソッドにファイル名やURLを直接渡すのがスマートで簡単。

        // 「ファイルを開く」ボタンの処理
        btnFileOpen.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                // 読み込み用ダイアログを開く
                FileDialog fileDlg = new FileDialog(shell, SWT.OPEN);
                String[] exts = { "*.html", "*.*" };
                fileDlg.setFilterExtensions(exts);
                String[] filterNames = { "HTMLファイル(*.html)", "全てのファイル(*.*)" };
                fileDlg.setFilterNames(filterNames);
                fileDlg.setText("テキストファイルを開く");
                String selectedFilename = fileDlg.open();
                if (selectedFilename != null && !selectedFilename.isEmpty()) {
                    browser.setUrl("file://" + selectedFilename);
                }
            }

Browserヴィジェットでのエラー

現状で、おそらく避けることの出来ないエラーが発生しているようで、次に示すようなエラーがコンソールに書きだされる。将来このBugが解消されることを願っている…

(SWT:3495): GLib-GObject-CRITICAL **: g_closure_unref: assertion 'closure->ref_count > 0' failed
(SWT:3495): GLib-GObject-CRITICAL **: g_closure_unref: assertion 'closure->ref_count > 0' failed

StyledTextヴィジェットを使う

20150413-swt-styledtextview.jpg

文中の『ダキア』というキーワード全てを着色する例を示す

 〜 略 〜
        shell.setLayout(new GridLayout(2, false));
        // レイアウトに配置する要素(ヴィジェット)
        Label label1 = new Label(shell, SWT.NONE);
        label1.setText("Text");
        
        final StyledText styledText = new StyledText(shell, SWT.READ_ONLY
                | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.WRAP);
        GridData gridData = new GridData();
        gridData.horizontalAlignment = SWT.FILL;
        gridData.grabExcessHorizontalSpace = true;
        gridData.verticalAlignment = SWT.FILL;
        gridData.grabExcessVerticalSpace = true;
        styledText.setLayoutData(gridData);
        styledText.setText("まだファイルが選択されていません");
        
        Composite composite = new Composite(shell, SWT.NONE);
        composite.setLayout(new FillLayout(SWT.HORIZONTAL));
        Button btnFileOpen = new Button(composite, SWT.NULL);
        btnFileOpen.setText("ファイルを開く");
        Button btnClose = new Button(composite, SWT.NULL);
        btnClose.setText("閉じる");
        gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
        gridData.horizontalSpan = 2;
        composite.setLayoutData(gridData);
        
        // 「ファイルを開く」ボタンの処理
        btnFileOpen.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                // 読み込み用ダイアログを開く
                FileDialog fileDlg = new FileDialog(shell, SWT.OPEN);
                String[] exts = { "*.txt", "*.*" };
                fileDlg.setFilterExtensions(exts);
                String[] filterNames = { "テキストファイル(*.txt)", "全てのファイル(*.*)" };
                fileDlg.setFilterNames(filterNames);
                fileDlg.setText("テキストファイルを開く");
                String selectedFilename = fileDlg.open();
                if (selectedFilename != null && !selectedFilename.isEmpty()) {
                    ReadFromTextFile_StyledText(styledText, selectedFilename);
                }
            }
            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
 〜 略 〜
    }
    
    private void ReadFromTextFile_StyledText(StyledText t, String filename) {
        try {
            File file = new File(filename);
            BufferedReader br = new BufferedReader(new FileReader(file));
            // ファイル末端まで、各行をstrに読み込んでからStyledTextヴィジェットに追加していく
            String str = br.readLine();
            t.setText("");
            while (str != null) {
                t.append(str + "\n");
                str = br.readLine();
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 特定の文字に色を付けてみる
        String strFind = "ダキア";
        int startAt = t.getText().indexOf(strFind);
        while(startAt > 0){
            StyleRange styleRange = new StyleRange();
            styleRange.start = startAt;
            styleRange.length = strFind.length();
            styleRange.foreground = t.getDisplay().getSystemColor(SWT.COLOR_RED);
            styleRange.fontStyle = SWT.ITALIC|SWT.BOLD;
            t.setStyleRange(styleRange);
            
            startAt = t.getText().indexOf(strFind, startAt + 1);
        }
    }