読者です 読者をやめる 読者になる 読者になる
WEB拍手ぱちぱちっと
Clap/拍手

01.MENU
Blog  / ブログ
Videos  / 動画
Pictures  / 絵
Game Materials  / 素材
SS(ShortStory)  / 小ネタ

02.MENU
Novels  / 小説
Chat  / チャット
BBS  / 掲示板
Others  / その他
Old Top  / 旧Top

Traffic Jam Products


【JAVA】JAVAでデスクトップマスコットを作った話【非矩形window作成】

プログラム 技術 解説系

JAVAServletといったもので触っていて、デスクトップ用のアプリを作ることはありませんでした。

そんなわけでJAVAGUIを作る練習をしようと思い立ちました。

ツールを作るときですとGUIインターフェイスのほうが使いやすいですからねw

よぅし、ウィンドウを表示させるところまで頑張ってみますっ!

ウィンドウを出すところまで…………。

ウィンドウ……。

…………。

……。

……ど……。

どうしてこうなったっ!?

f:id:m_training:20151223161650p:plain

 

このようなわけで、ウィンドウを出すのでも、画像の形のウィンドウを作っていました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);
		}
	}


}

 

 

 

Official LINE Account
友だち追加
@hgf7288s