JAVAはServletといったもので触っていて、デスクトップ用のアプリを作ることはありませんでした。
そんなわけでJAVAでGUIを作る練習をしようと思い立ちました。
ツールを作るときですとGUIのインターフェイスのほうが使いやすいですからねw
よぅし、ウィンドウを表示させるところまで頑張ってみますっ!
ウィンドウを出すところまで…………。
ウィンドウ……。
…………。
……。
……ど……。
どうしてこうなったっ!?
このようなわけで、ウィンドウを出すのでも、画像の形のウィンドウを作っていましたw
デスクトップマスコットの雛形といったところです。
デスクトップマスコットを作った、というより非矩形ウィンドウを作った、といったほうが正確です(^-^;
JAVAで非矩形ウィンドウを作った話。
参照は以下の方のツイートです。
大いに参考していますのでご了承ください><
https://twitter.com/ysrken/status/650986044486082560
本当はもっと汎用的にウィンドウを作れるようにしようと思ったのですが、再描画を考えた時にいろいろ問題点が出てきてしまって(^-^;
今のところこの形です。
では簡単に説明をはさみたいと思います。
App.java
メインの関数です。
MakeWindowでインスタンスを作ります。
MakeWindow p = new MakeWindow();
makeImageWindow(画像のパス)で、メインのウィンドウ(ほっぽちゃん)を作りますw
JFrame mainFrame = p.makeImageWindow("picture4.png");
viewImage(JFrame, 画像のパス)で、メインのウィンドウを書き換えます(表情替え大事!)
p.viewImage(mainFrame, "picture.png");
makeMessageWindow(画像パス)で、もう一つのウィンドウを作ります。(メッセージウィンドウ)
JFrame frame = p.makeMessageWindow("8.png");
redrawLabel(String)で、メッセージウィンドウの中のメッセージを変えます。(台詞だじ!)
p.redrawLabel("コナイデ……ッ");
こんな感じで、簡単に絵とメッセージを変えられるようにしています。
MakeWindow.java
//画像window作成
public JFrame makeImageWindow(String imagePath){
JFrame frame = new JFrame();
frame.setUndecorated(true);
//各種リスナー追加
addListener(frame);
frame = viewImage(frame, imagePath);
return frame;
}
//Window表示メイン
public JFrame viewImage(JFrame frame, String imagePath){
ImageIcon icon = new ImageIcon(imagePath);
frame.setSize(icon.getIconWidth(), icon.getIconHeight());
setImagePosition(frame, icon.getIconWidth(), icon.getIconHeight());
Shape shape = getImageShape(icon);
frame.setShape(shape);
frame.setBackground(new Color(0,0,0,0));
Image image = icon.getImage();
contentPane = frame.getContentPane();
//canvasがないときは作成
if(canvas == null){
canvas = new Canvas(image);
contentPane.add(canvas);
frame.setVisible(true);
}
else{
//canvasがあるときは再描画
canvas.image = image;
canvas.repaint();
}
//setAlwaysOnTop(true);
return frame;
}
JFrameを作った後にウィンドウがドラッグできるようにイベントリスナーを追加します。
あとダブルクリックで消えるのも追加です。
その後、読み込んだイメージでウィンドウのshapeを作ります。
setShapeはJaveのversion1.7から使えます。その前ですとAWTUtilitiesというものを使うようです。(詳しく調べてない)
Shape shape = getImageShape(icon);
frame.setShape(shape);
背景を透過しておきます。これをやらないとジャギが目立ちますw(私絵描きですので、気にするタイプですw)
frame.setBackground(new Color(0,0,0,0));
Canvasを使って画像を書き込みます。
canvas = new Canvas(image);
contentPane.add(canvas);
で、最後は以下で表示させます。
frame.setVisible(true);
問題点
JPanelなど、ラベルといったものを載せちゃうと画像が見えなくなってしまいます><
現在はまだそれは未解決なのです(^-^;
ソース
App.java
import javax.swing.JFrame; public class App { public static void main( String[] args ) { System.out.println( "StandBy" ); MakeWindow p = new MakeWindow(); JFrame mainFrame = p.makeImageWindow("picture4.png"); JFrame frame = p.makeMessageWindow("8.png"); //メッセージ変更する時 p.redrawLabel("カエレ……ッ"); //別画像で再描画する時 //p.viewImage(mainFrame, "picture.png"); //p.redrawLabel("コナイデ……ッ"); } }
MakeWindow.java
import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.image.*; import javax.swing.*; import com.sun.awt.AWTUtilities; class MakeWindow extends JWindow{ JLabel label = null; Canvas canvas = null; Container contentPane = null; MakeWindow(){ } ////////////////////////////////////////////////////////////////////////// //通常のwindow作成 public JFrame makeWindow(int width, int height){ JFrame mainFrame = new JFrame("サンプル"); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.setSize(width,height); mainFrame.setLocationRelativeTo(null); // JFrameよりContentPaneを取得 Container contentPane = mainFrame.getContentPane(); // ラベルのインスタンスを生成 label = new JLabel("これはラベルです"); // ラベルをContentPaneに配置 contentPane.add(label, BorderLayout.CENTER); mainFrame.setVisible(true); return mainFrame; } ///////////////////////////////////////////////////////////////////////// //画像window作成 public JFrame makeImageWindow(String imagePath){ JFrame frame = new JFrame(); frame.setUndecorated(true); //各種リスナー追加 addListener(frame); frame = viewImage(frame, imagePath); return frame; } //Window表示メイン public JFrame viewImage(JFrame frame, String imagePath){ ImageIcon icon = new ImageIcon(imagePath); frame.setSize(icon.getIconWidth(), icon.getIconHeight()); setImagePosition(frame, icon.getIconWidth(), icon.getIconHeight()); Shape shape = getImageShape(icon); frame.setShape(shape); frame.setBackground(new Color(0,0,0,0)); Image image = icon.getImage(); contentPane = frame.getContentPane(); //canvasがないときは作成 if(canvas == null){ canvas = new Canvas(image); contentPane.add(canvas); frame.setVisible(true); } else{ //canvasがあるときは再描画 canvas.image = image; canvas.repaint(); } //setAlwaysOnTop(true); return frame; } //ポップアップ作成 //画像window作成 public JFrame makeMessageWindow(String imagePath){ JFrame frame = new JFrame("new"); frame.setUndecorated(true); addListener(frame); ImageIcon icon = new ImageIcon(imagePath); frame.setSize(icon.getIconWidth(), icon.getIconHeight()); setImagePosition(frame, icon.getIconWidth(), icon.getIconHeight() + 40); Shape shape = getImageShape(icon); frame.setShape(shape); //Image image = icon.getImage(); //Canvas canvas = new Canvas(image); JPanel p = new JPanel(); label = new JLabel("ジングルベー♪ ジングルベー♪"); p.add(label); p.setBackground(Color.WHITE); frame.getContentPane().add(p); frame.setVisible(true); return frame; } /////////////////////////////////////////////////////////////////// //各種処理系 // ドラッグ可能にして、ダブルクリックで終了するようにする class DragWindowListener extends MouseAdapter{ private MouseEvent start; private Point loc; private Window window; public DragWindowListener(Window w){ super(); window = w; } @Override public void mousePressed(MouseEvent me){ if(me.getClickCount() >= 2){ System.exit(0); } start = me; } @Override public void mouseDragged(MouseEvent me){ loc = window.getLocation(loc); int x = loc.x- start.getX() + me.getX(); int y = loc.y - start.getY() + me.getY(); window.setLocation(x, y); } } //ラベルの再描画 public void redrawLabel(String message){ label.setText(message); repaintWindowAncestor(label); } //再描画 public void repaintWindowAncestor(JComponent c) { JRootPane root = c.getRootPane(); if (root == null) { return; } Rectangle r = SwingUtilities.convertRectangle(c, c.getBounds(), root); root.repaint(100, r.x, r.y, r.width, r.height); } //各種リスナー追加 private void addListener(JFrame frame){ DragWindowListener dwl = new DragWindowListener(frame); frame.addMouseListener(dwl); frame.addMouseMotionListener(dwl); } //画面端に配置 private void setImagePosition(JFrame frame, int width, int height){ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); frame.setBounds(screenSize.width - width, screenSize.height - height, width, height); } // アルファ値が0である箇所以外を全てshapeに追加してそれを返す public Shape getImageShape(ImageIcon icon){ GeneralPath shape = new GeneralPath(); final BufferedImage bi = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); icon.paintIcon(null, bi.createGraphics(), 0, 0); ColorModel cm = bi.getColorModel(); for(int y = 0; y < bi.getHeight(); y++){ for(int x = 0; x < bi.getWidth(); x++){ // 完全に透過していなければshapeに追加 if(cm.getAlpha(bi.getRGB(x, y)) > 0){ int start = x; int width = 0; while((x < bi.getWidth()) && (cm.getAlpha(bi.getRGB(x++, y)) > 0)){ width++; } shape.append(new Rectangle(start, y, width, 1), true); } } } return shape; } // Canvasクラスを改造する private class Canvas extends JPanel{ private static final long serialVersionUID = 1L; private Image image = null; public Canvas(Image image){ super(); this.image = image; } public void paintComponent(Graphics g){ if(image == null) return; g.drawImage(image, 0, 0, this); } } }