質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.00%

JLabel paintComponentが呼ばれない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,337

otftrough

score 394

JLabelを継承したクラスを作って、paintComponent()の中でラベルに表示する画像の大きさを計算させています。
具体的な使い方は、

FLabel label = new FLabel(); //JLabelを継承させたクラス
label.alpha = 255;

label.setIconAndImage(new ImageIcon("pict.jpg")); //setIcon()のかわり
label.setIconSize(500, 500); //表示するサイズ


という感じです。
普通に使えば問題なく表示されますが、
setIconSize(int w, int h)を使ったとき、どちらかの値が1未満だとpaintComponent()が呼び出されません。
困ります。
なぜでしょうか?

下記 FLabelクラス

public class FLabel extends JLabel{

        private Image img;
        public int alpha; //表示する画像の不透明度
        public int iwidth; //画像のwidth
        public int iheight; //画像のheight
        //int widthと int heightは既に存在していたので、変数名を変えました。
        private boolean size;

        public FLabel(){}
        public FLabel(String str){ this.setText(str); }
        public FLabel(ImageIcon icon){

            setIconAndImage(icon);
        }

        public void setIconAndImage(ImageIcon icon){

            setIcon(icon);
            //あ、もしかしてsetIcon()の中身に書けば良かった?
            if(icon != null) img = icon.getImage();
            else img = null;
        }

        public void setIconSize(int w, int h){

            iwidth = w;
            iheight = h;
            size = true;
        }

        @Override
        public void paintComponent(Graphics g){System.out.println("paintComponent");
            System.out.println("paintComponentが呼ばれたよ!");

            Graphics2D g2 = (Graphics2D)g;
            if(img != null){

                g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)alpha / (float)255));

                //サイズ変更がない場合
                if(!size) g2.drawImage(img, 0, 0, getIcon().getIconWidth(), getIcon().getIconHeight(), this);

                //サイズ変更がある場合
                else if(iwidth > 0 || iheight > 0){

                    //iwidthまたはiheightが0以下なら、画像の比率をそのままで拡大or縮小
                    if(iwidth <= 0) iwidth = (int)(getIcon().getIconWidth() * ((double)iheight / (double)getIcon().getIconHeight()));
                    else if(iheight <= 0) iheight = (int)(getIcon().getIconHeight() * ((double)iwidth / (double)getIcon().getIconWidth()));
                    g2.drawImage(img, 0, 0, iwidth, iheight, this);
                }
            }
        }
    }

追記:
実際に作っているプログラムの一部です。
setIconSize(w, h);のあとにsetBounds();を使っているのでrepaintされていると思います。
念のためsetBoundsのあとにrepaint()を入れてみてもなにも変わりませんでした。
wとh両方が自然数ならば正常に動きますが、100%毎回ではないようです。
どちらか片方、又は両方が0以下なら100%paintComponentは呼ばれません。

JTextArea text;
ImageIcon dispImage;
FLabel imgLabel;
/*****************************************************/
if(text.getText().startsWith("image:")){ //画像

    String str = text.getText().substring(6);
    if(!str.equals("null")){

        str = "img/" + str;
        File img = new File(str);
        if(img.exists()){

            dispImage = new ImageIcon(str);
            imgLabel.setIconAndImage(dispImage);
            if(!imgLabel.size) imgLabel.setBounds(50, 50, dispImage.getIconWidth(), dispImage.getIconHeight());
            else imgLabel.setBounds(50, 50, imgLabel.iwidth, imgLabel.iheight);
        } else{

            text.setText("\"" + str + "\" is not found!");
        }
    } else if(imgLabel.getIcon() != null){

        imgLabel.setIconAndImage(null);
        dispImage = null;
    }
} else if(text.getText().startsWith("image.")){

    String txt = text.getText().substring(6);
    if(txt.startsWith("position:")){

        txt = txt.substring(9);
        int w = number(txt);
        txt = txt.substring(new String(w + "").length() + 1);
        int h = number(txt);
        //wとhには幅と高さの整数が入っています。
        imgLabel.setBounds(w - imgLabel.getWidth() / 2, h - imgLabel.getHeight() / 2, imgLabel.getWidth(), imgLabel.getHeight());
    }else if(txt.startsWith("size:")){ //表示サイズの指定

        txt = txt.substring(5);
        int w = number(txt);
        txt = txt.substring(new String(w + "").length() + 1);
        int h = number(txt);
        //wとhには幅と高さの整数が入っています。

        imgLabel.setIconSize(w, h);
        imgLabel.setBounds(w - imgLabel.getWidth() / 2, h - imgLabel.getHeight() / 2, imgLabel.iwidth, imgLabel.iheight);
        imgLabel.setIconAndImage(dispImage);
    } else if(txt.equals("bounds")){

        text.setText("X:" + (imgLabel.getX() + imgLabel.getWidth() / 2) + ", Y:" + (imgLabel.getY() + imgLabel.getHeight() / 2) + ", width:" + imgLabel.getWidth() + ", height:" + imgLabel.getHeight());
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • argius

    2016/06/15 17:46

    どちらかの値が1未満ということは、intなので0以下ということですよね。
    ということは例えばlabel.setIconSize(0, 400)
    とした場合は呼ばれないということですか?
    その場合でもrepaintや画面の再描画があれば呼ばれると思います。
    逆にsetIconSizeだけではrepaint()を呼ばないとpaintComponentが呼ばれないと思います。
    他にも発生条件がありそうですけど、何かありませんか?

    キャンセル

回答 1

checkベストアンサー

0

setBoundsでゼロ以下の幅か高さを指定した場合は、描画領域が無くなるため、
repaintしてもpaintComponentが呼ばれないようです。

少なくともComponent#repaintメソッドの中身はそうなっています。

java.awt.Component (L.3371) - GrepCode Class Source  
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/awt/Component.java#3371

なので、そういう「仕様」ということですね。
(本当に仕様かどうかは確認していません。)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/15 22:47

    ありがとうございます、setIconSize()のあとrepaint()して、paintComponentの一番最後にsetBounds()を移動させたら思い通りに動きました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる