« 2012年5月 | トップページ | 2012年7月 »

2012年6月

2012年6月23日 (土)

java: mac 上で JProgressBar に出る波を消す

進度(進捗)バーには以下の3つの機能が必要だと思います。
 1. 進度を表す                (最終的には100%になる)
 2. 量を表す                  (増減し、100%になるとは限らない)
 3. タスク実行中だがその進度は不明

JProgressBar のメソッドでは 1, 2が setValue(int n) で、 3が setIndeterminate(boolean b)に相当します。

windowsでは問題なかったのですが、mac の JProgressBar はバーの模様が波打って動いているため、2の目的には不都合であることが分かりました。

mac上で2の目的で JProgressBar を使うには、setUI() メソッドを使用すれば良いことが分かりました。

Jprogressbar_20120623_2

package test;

import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicProgressBarUI;

// サンプルコード
public class TestProgressBar extends javax.swing.JFrame {

    private final JProgressBar jProgressBar1 = new javax.swing.JProgressBar();
    private final JProgressBar jProgressBar2 = new javax.swing.JProgressBar();
    private final JProgressBar jProgressBar3 = new javax.swing.JProgressBar();
    private final JPanel jPanel1 = new javax.swing.JPanel();
    private final JPanel jPanel2 = new javax.swing.JPanel();

    public TestProgressBar() {
        initComponents();
        jProgressBar1.setStringPainted(true);
        jProgressBar2.setStringPainted(true);
        jProgressBar3.setStringPainted(true);
        jProgressBar1.setString("Bar1");
        jProgressBar2.setString("Bar2");
        jProgressBar3.setString("Bar3");
        jProgressBar1.setValue(100);
        jProgressBar2.setValue(60);
        jProgressBar3.setValue(60);

        jProgressBar3.setForeground(new java.awt.Color(153, 153, 255));
        jProgressBar3.setUI(
new BasicProgressBarUI() ); // new MetalProgressBarUI()
        System.out.println("" + jProgressBar1.getUI().getClass());
    }

    private void initComponents() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.CardLayout(20, 20));
        getContentPane().add(jPanel1, "card1");
        jPanel1.setLayout(new java.awt.GridLayout(3, 0));
        jPanel1.add(jProgressBar1);
        jPanel1.add(jProgressBar2);
        jPanel1.add(jPanel2);
        jPanel2.setLayout(new java.awt.BorderLayout());
        jPanel2.add(jProgressBar3, java.awt.BorderLayout.PAGE_START);
        setSize(320, 150);
        setLocationRelativeTo(null);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
//                try {
//                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
//                } catch (Exception ex) {
//                    ex.printStackTrace();
//                }

                new TestProgressBar().setVisible(true);
            }
        });
    }
}

■Ref
 ・クラス BasicProgressBarUI      ( sun java6 docs 日本語 )
 ・BasicProgressBarUI ソースコード  ( ttp://grepcode.com>JDK/ jdk / openjdk/ 6-b14 )
 ・BasicProgressBarUI ソースコード  ( ttp://opensource.apple.com )
 ・AquaProgressBarUI ソースコード  ( hg.openjdk.java.net 、src/macosx/classes/com/apple/laf )
 ・Nice looking progress bar in java

■備考
 ちなみに「HTML5」では progress 要素と meter要素が 上記1,2 に対応します。
  ・input要素だけじゃない HTML5のフォーム新機能

2012年6月 2日 (土)

java: GlassPane で JPopupMenu を使用する方法

GlassPane で JPopupMenu を利用しようとしたらメニューが選択出来なかった。
解決方法が分かったのでメモしておきます。

原因は 最上層のGlassPane がマウスのイベントを 奪っていたためでした。
contains メソッドオーバーライドで解決できました。

import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
 

public class MyFrame extends javax.swing.JFrame {
    public MyFrame() {
        initComponents();
        setLocationRelativeTo(null);

        setGlassPane(new MyGlassPane());
        getGlassPane().setVisible(true);

    }
 
    private void initComponents() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(null);
        setBounds(0, 0, 400, 300);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MyFrame().setVisible(true);
            }
        });
    }

}

class MyGlassPane extends JComponent {
    private final JPopupMenu mPopup = new JPopupMenu(); 
    MyGlassPane() {
        mPopup.add(new JMenuItem("Item1"));
        mPopup.add(new JMenuItem("Item2"));
        setComponentPopupMenu(mPopup);
    }

    @Override
    public boolean contains(int x, int y) {
        return !mPopup.isShowing();
// 本当はpopup 表示の内外で返値を変えた方が良い
    }

}

« 2012年5月 | トップページ | 2012年7月 »