« 2009年10月 | トップページ | 2009年12月 »

2009年11月

2009年11月30日 (月)

jconsole による解析(Java 1.6)

jconsole が java 1.6 で新しくなっていた。ある日の OpenDolphin を解析してみたが,java 1.5 の時と大分違う結果になった。

 

Photo

    ヒープメモリは,-Xms 設定値(128M)に達してから大きな GC が起きるようである。-Xms 設定値に達しない場合は 1時間で GC が起きているように見える。

Par_eden_space

    Eden 領域

Par_survivor_space

    Survivor 領域

Photo_2

    ライブスレッドが 27個。

 

いずれにしてもメモリ不足と言うことはなさそう。

2009年11月27日 (金)

検査データの印刷

ラボデータを印刷できるようにできないかとのお問い合わせを頂いた。とりあえず印刷できるようにするためには以下のような改造をすればよい。

 

client/AbstractChartDocument.java

JPanel() のかわりに,プリントに対応した Panel2() を組み込む
public AbstractChartDocument() {
//pns   setUI(new JPanel());
  setUI(new Panel2());
  logger = ClientContext.getBootLogger();
 ・
 ・

 

plugin/LaboTestBean.java

enter() を作成し,プリントメニューがアクティブになるようにする。start() 時に,enter() を呼ぶようにする。これで LaboTestBean 起動時にプリントメニューがアクティブになり,プリントすると print() が呼ばれる。
@Override
public void start() {
  initialize();
  NameValuePair pair = (NameValuePair) extractionCombo.getSelectedItem();
  String value = pair.getValue();
  int addValue = Integer.parseInt(value);
  GregorianCalendar today = new GregorianCalendar();
  today.add(GregorianCalendar.MONTH, addValue);
  searchLaboTest(MMLDate.getDate(today));
//pns
  enter();
}
//pns^
@Override
public void enter() {
  super.enter();
  getContext().enabledAction(GUIConst.ACTION_PRINT, true);
}

@Override
public void print() {
  String name = getContext().getPatient().getFullName();
  PageFormat pageFormat = getContext().getContext().getPageFormat();
  int height = getUI().getSize().height;
  ((Panel2)getUI()).printPanel(pageFormat, 1, true, name, height);
}
//pns$

2009年11月13日 (金)

JSheet 導入

Sheet

Mac OS X のダイアログは,タイトルバーのところからアニメーションで降りてくる。これを,「シート」と呼ぶらしい。Mac OS X らしい微妙に半透明のダイアログで素敵である。
 Quaqua には JSheet というクラスがあって,Mac OS X のシートっぽいことが Java でもできる。JSheet を継承した MyJSheet を作って,いくつかダイアログを,シートに置き換えてみた。Mac っぽくなっていい感じになった。JSheet が出てくるスピードは,デフォルトだと遅めなので,default コマンドで 0.05 にセットしている。

$ defaults write NSGlobalDomain NSWindowResizeTime 0.05

client/MyJSheet.java

package open.dolphin.client;

import ch.randelshofer.quaqua.*;
import java.awt.*;
import javax.swing.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * JOptionPane を quaqua の JSheet で置き換える
 * Sheet の表示スピード調節:e.g. defaults write NSGlobalDomain NSWindowResizeTime 0.05 (default=0.2)
 * @author pinus
 */
public class MyJSheet extends JSheet {
  static int answer;

  public MyJSheet(Frame frame) {
    super(frame);
  }
  public MyJSheet(Dialog dialog) {
    super(dialog);
  }

  // JOptionPane.showConfirmDialog 互換
  public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType) {
    return showOptionDialog(parentComponent, message, title, optionType, messageType, null, null, null);
  }

  // JOptionPane.showMessageDialog 互換
  public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) {
    showOptionDialog(parentComponent, message, title, JOptionPane.DEFAULT_OPTION, messageType, null, null, null);
  }

  // JOptionPane.showOptionDialog 互換
  public static int showOptionDialog(Component parentComponent, Object message, String title,
      int optionType, int messageType, Icon icon, final Object[] options, Object initialValue) {

    JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, options, initialValue);
    pane.setInitialValue(initialValue);
    JSheet sheet = createDialog(pane, parentComponent);
    pane.selectInitialValue();
    sheet.addSheetListener(new SheetListener(){
      public void optionSelected(SheetEvent e) {
        answer = e.getOption();
      }
    });
    sheet.show();
    sheet.dispose();
    return answer;
  }

  // dialog = jop.createDialog を dialog = MyJSheet.createDialog(jop, parent) と置き換えるだけで JSheet になる
  public static MyJSheet createDialog(final JOptionPane pane, Component parentComponent) {
    Window window = getWindowForComponent(parentComponent);
    final MyJSheet sheet;
    if (window instanceof Frame) {
      sheet = new MyJSheet((Frame) window);
    } else {
      sheet = new MyJSheet((Dialog) window);
    }
    JComponent contentPane = (JComponent) sheet.getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(pane, BorderLayout.NORTH);
    sheet.setResizable(false);
    sheet.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentShown(ComponentEvent ce) {
        // reset value to ensure closing works properly
        pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
        Object object = pane.getInitialValue();
        if (object instanceof Component) {
          ((Component) object).requestFocusInWindow();
        }
      }
    });
    pane.addPropertyChangeListener(new PropertyChangeListener() {

      public void propertyChange(PropertyChangeEvent event) {
        if (sheet.isVisible() && event.getSource() == pane &&
            (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) &&
            event.getNewValue() != null &&
            event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
          sheet.setVisible(false);
          sheet.fireOptionSelected(pane);
        }
      }
    });
    sheet.pack();
    return sheet;
  }

  /**
   * その component に既に JSheet が表示されているかどうか
   * @param parentComponent
   * @return
   */
  public static boolean isAlreadyShown(Component parentComponent) {
    Window window = getWindowForComponent(parentComponent);
    Window[] windowList = window.getOwnedWindows();
    for (Window w : windowList) {
      if (w instanceof MyJSheet && w.isVisible()) {
        // すでに JSheet が表示されている
        return true;
      }
    }
    return false;
  }

  private static Window getWindowForComponent(Component parentComponent) {
    if (parentComponent == null) {
      return JOptionPane.getRootFrame();
    }
    if (parentComponent instanceof Frame || parentComponent instanceof Dialog) {
      return (Window) parentComponent;
    }
    return getWindowForComponent(parentComponent.getParent());
  }
}

2009年11月 6日 (金)

Magic Mouse 購入

Scroll_speed

    Magic Mouse を購入した。なんか重たくて使いにくいけど,デザインが素敵なので,がんばって使って慣れようと思う。慣性スクロールがいい感じなのだが,スクロール速度が速すぎるとうまく使えない。Magic Mouse 用に,スクロール速度を調節できるようにした。【追記】慣れたらかなりいい感じに使えるようになった。慣性スクロールを使う場合,スクロール速度はすべて 1 で OK。

client/KarteSettingPanel.java

private void initComponents() {
 ・
 ・

//pns^  スクロール速度設定
  JPanel uiPanel = new JPanel();
  uiPanel.setLayout(new BoxLayout(uiPanel, BoxLayout.Y_AXIS));
  row = 0;
  gbb = new GridBagBuilder("スクロール速度");

  // カルテスクロール速度
  label = new JLabel("カルテ :", SwingConstants.RIGHT);
  JPanel slider = GUIFactory.createSliderPanel(1,32, prefs.getInt(Project.SCROLL_UNIT_KARTE, 15));
  scrollUnitKarte = (JSpinner) slider.getComponent(1);
  gbb.add(label, 0, row, 1, 1, GridBagConstraints.EAST);
  gbb.add(slider, 1, row++, 1, 1, GridBagConstraints.WEST);

  // テーブルのスクロール速度
  label = new JLabel("テーブル :", SwingConstants.RIGHT);
  slider = GUIFactory.createSliderPanel(1,32, prefs.getInt(Project.SCROLL_UNIT_TABLE, 15));
  scrollUnitTable = (JSpinner) slider.getComponent(1);
  gbb.add(label, 0, row, 1, 1, GridBagConstraints.EAST);
  gbb.add(slider, 1, row++, 1, 1, GridBagConstraints.WEST);

  // スタンプのスクロール速度
  label = new JLabel("スタンプ :", SwingConstants.RIGHT);
  slider = GUIFactory.createSliderPanel(1,32, prefs.getInt(Project.SCROLL_UNIT_STAMP, 15));
  scrollUnitStamp = (JSpinner) slider.getComponent(1);
  gbb.add(label, 0, row, 1, 1, GridBagConstraints.EAST);
  gbb.add(slider, 1, row++, 1, 1, GridBagConstraints.WEST);

  uiPanel.add(gbb.getProduct());
  uiPanel.add(Box.createVerticalStrut(500));
  uiPanel.add(Box.createVerticalGlue());

//pns$
  JTabbedPane tabbedPane = new JTabbedPane();
  tabbedPane.addTab("インスペクタ", inspectorPanel);
  tabbedPane.addTab("文 書", docPanel);
  tabbedPane.addTab("スタンプ", stampPanel);
  tabbedPane.addTab("診療行為", sendPanel);
  tabbedPane.addTab("確認ダイアログ", confirmPanel);
//pns^  スクロール速度設定
  tabbedPane.addTab("UI", uiPanel);
//pns$
 ・
 ・

private void bindViewToModel() {
 ・
 ・
//pns^
  // スクロール速度を pref に書き戻す
  val = scrollUnitKarte.getValue().toString();
  prefs.putInt(Project.SCROLL_UNIT_KARTE, Integer.parseInt(val));
  val = scrollUnitTable.getValue().toString();
  prefs.putInt(Project.SCROLL_UNIT_TABLE, Integer.parseInt(val));
  val = scrollUnitStamp.getValue().toString();
  prefs.putInt(Project.SCROLL_UNIT_STAMP, Integer.parseInt(val));
//pns$

client/GUIFactory.java

public static JPanel createSliderPanel(int min, int max, final int initValue) {
  JPanel ret = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0));
  // スライダー
  final JSlider slider = new JSlider(min, max, initValue);
  slider.setFont(new Font("SansSerif", Font.PLAIN, 9)); // 大きさ調節

  // スピナー
  SpinnerModel fetchModel = new SpinnerNumberModel(initValue, min, max, 1);
  final JSpinner spinner = new JSpinner(fetchModel);
  spinner.setEditor(new JSpinner.NumberEditor(spinner, "#"));

  // お互いにリスン
  slider.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
      spinner.setValue(slider.getValue());
    }
  });
  spinner.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
      slider.setValue((Integer)spinner.getValue());
    }
  });
 
  ret.add(slider);
  ret.add(spinner);
  return ret;
}

project/Project.java

//pns^  スクロール速度設定
public static final String SCROLL_UNIT_KARTE = "scroll.unit.karte";
public static final String SCROLL_UNIT_TABLE = "scroll.unit.table";
public static final String SCROLL_UNIT_STAMP = "scroll.unit.stamp";
//pns$

client/DocumentBridgeImpl.java

scroller = new JScrollPane();
//pns^  MagicMouse 購入に合わせて,スクロールスピードを調節できるようにした
getUI().setLayout(new BorderLayout());
scroller.getVerticalScrollBar().setUnitIncrement(Project.getPreferences().getInt(Project.SCROLL_UNIT_KARTE, 15));

client/Kartepanel3.java

public KartePanel3() {
  initComponents();
//pns^  スクロール増分設定
  java.util.prefs.Preferences prefs = open.dolphin.project.Project.getPreferences();
  int unit = prefs.getInt(open.dolphin.project.Project.SCROLL_UNIT_KARTE, 15);
  pScrollPane.getVerticalScrollBar().setUnitIncrement(unit);
  soaScrollPane.getVerticalScrollBar().setUnitIncrement(unit);
//pns$

client/ImagePalette.java

private void initComponent(int columnCount) {
 ・
 ・
//pns^  スクロール増分の調整
  JScrollPane scroller = new JScrollPane();
  scroller.getVerticalScrollBar().setUnitIncrement(Project.getPreferences().getInt(Project.SCROLL_UNIT_STAMP, 15));

client/StampTree.java

//pns^  MagicMouse 購入に合わせて,スクロールスピードを調節できるようにした
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
  return Project.getPreferences().getInt(Project.SCROLL_UNIT_STAMP, 15);
}
//pns$

plugin/RowTipsTable.java
plugin/AddressTipsTable.java

//pns^  MagicMouse 購入に合わせて,スクロールスピードを調節できるようにした
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
  return Project.getPreferences().getInt(Project.SCROLL_UNIT_TABLE, 15);
}
//pns$

2009年11月 3日 (火)

検索結果ファイル保存

患者検索画面で検索した結果をファイルに書き出せるようにした。検索結果リストで右クリックすると,結果を保存するメニューが出る。(//pns^ から //pns$ までが変更内容)

plugin/PatientSearchImpl.java

class ContextListener extends AbstractContextListener {
 ・
 ・
  JCheckBoxMenuItem item = new JCheckBoxMenuItem("年齢表示");
  contextMenu.add(item);
  item.setSelected(ageDisplay);
  item.addActionListener(EventHandler.create(ActionListener.class, PatientSearchImpl.this, "switchAgeDisplay"));
//pns^
  // 検索結果をファイル保存
  if (view.getTable().getRowCount() > 0) {
    contextMenu.add(new JMenuItem(new ReflectAction("検索結果ファイル保存", PatientSearchImpl.this, "exportSearchResult")));
  }
//pns$
 ・
 ・
//pns^
/**
 * 検索結果をファイルに書き出す
 */
public void exportSearchResult() {
  JFileChooser fileChooser = new JFileChooser();
  if (fileChooser.showSaveDialog(view) == JFileChooser.APPROVE_OPTION) {
    File file = fileChooser.getSelectedFile();

    if (!file.exists() || isOverwriteConfirmed(file)) {

      try {
      FileWriter writer = new FileWriter(file);
      JTable table = view.getTable();
      // 書き出す内容
      StringBuilder sb = new StringBuilder();
      for (int row = 0; row < table.getRowCount(); row++) {
        for (int column = 0; column < table.getColumnCount(); column++) {
          sb.append(column==0?"":',');
          sb.append('"');
          sb.append(table.getValueAt(row, column));
          sb.append('"');
        }
        sb.append('\n');
      }
      writer.write(sb.toString());
      // close
      writer.close();

      } catch (IOException ex) {
        System.out.println("PatientSearchImpl.java: " + ex);
      }
    }
  }
}
/**
 * ファイル上書き確認ダイアログを表示する。
 * @param file 上書き対象ファイル
 * @return 上書きOKが指示されたらtrue
 */
private boolean isOverwriteConfirmed(File file){
  String title = "上書き確認";
  String message = "既存のファイル「" + file.toString() + "」\n"
          +"を上書きしようとしています。続けますか?";

  int confirm = JOptionPane.showConfirmDialog(
      view, message, title,
      JOptionPane.WARNING_MESSAGE,
      JOptionPane.OK_CANCEL_OPTION );

  if(confirm == JOptionPane.OK_OPTION) return true;

  return false;
}
//pns$

« 2009年10月 | トップページ | 2009年12月 »