0

JLabelを拡張するカスタムクラスがあります。そのクラスの特定のインスタンスについて、左側のテキストにスペースを追加したいと思います。このJLabelの背景を設定しているので、間隔が必要です。テキストが色付きの背景の端のすぐ隣にぶつからないようにします。私はかなり釣りをして、これを実装しました(ペイント機能内):

if (condition) {
    bgColor = Color.red;
    setBackground(bgColor);
    setOpaque(true);
    // This line merely adds some padding on the left
    setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
}
else {
    setOpaque(false);
}

これは、必要な間隔を追加するという点で機能しているように見えますが、アプリケーションの残りの部分全体の再描画を中断しているように見えるという不幸な副作用があります...その特定のコンポーネントのみが再描画されており、アプリケーションの残りの部分。私は最終的にそれをsetBorder呼び出しまで追跡しました...どんな種類の境界線を設定しても、同じ壊れた動作を引き起こすように見えます。アプリケーションには2つの異なるバージョンがあります。1つはJava1.5で実行され、もう1つはJava 1.6で実行されます。Java1.6バージョンは正しく機能しているように見えますが、Java1.5バージョンは機能していません。古いバージョンをJava1.6にアップグレードすることはできません...Java1.5で動作するものが必要です。また、私はこれを試しました(それがどのように見えるかを見るためだけに):

setHorizontalTextPosition(JLabel.CENTER);

そして、それもまったく同じように塗り直しを壊すように見えます。アプリケーションのソースを調べて、境界線を設定した他の場所(空の境界線を含む)を見つけましたが、JLabelには見つかりませんでした(パネル、ボタンなどのみ)。誰かが前にこのようなものを見ますか?それを修正する方法を知っていますか?または、バグを回避するために必要な間隔を取得する別の方法はありますか?ありがとう。

4

1 に答える 1

3

問題は、paintメソッド内でそのコードを呼び出していることです。スイングペインティングパイプラインの不要なループでEDTがフリーズするため、これを行うべきではありません。

そのコードをコンストラクターに配置し、アプリのライフサイクルの他の場所でコンポーネントの設計状態を変更する必要があります。

Swingペインティングについてもう少し詳しく知りたい場合は、pushing-pixels.orgの「Swingペインティングパイプライン」の投稿をお読みください。

BorderFactory.createCompoundBorderを使用して、任意の2つの境界線を組み合わせることができることに注意してください。次に、emptyBorderやその他の間隔を設定して、外側の境界線を描画できます。

編集:例が追加されました。

package com.stackoverflow.swing.paintpipeline;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.Border;


public class JLabelSetBorderPaintProblem extends JLabel {

    public JLabelSetBorderPaintProblem(String text) {
        super(text);
    }

    /*
     * @see javax.swing.JComponent paint(java.awt.Graphics)
     */
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // You can not call setBorder here.

        // Please check javadoc.
    }

    /*
     * @see javax.swing.JComponent paintBorder(java.awt.Graphics)
     */
    @Override
    protected void paintBorder(Graphics g) {
        super.paintBorder(g);
        // Here is where the Swing painting pipeline draws the current border
        // for the JLabel instance.

        // Please check javadoc.
    }

    // Start me here!
    public static void main(String[] args) {
        // SetBorder will dispatch an event to Event Dispatcher Thread to draw the
        // new border around the component - you must call setBorder inside EDT.
        // Swing rule 1.
        SwingUtilities.invokeLater(new Runnable() {

            @Override public void run() {
                // Inside EDT
                JFrame frame = new JFrame("JLabel setBorder example");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                // Add the JLabel
                final JLabelSetBorderPaintProblem label = new JLabelSetBorderPaintProblem("Just press or wait...");
                frame.add(label);

                // And change the border...
                label.addMouseListener(new MouseAdapter() {
                    @Override public void mousePressed(MouseEvent e) {
                        label.setBorder(BORDERS.get(new Random().nextInt(BORDERS.size())));
                    }
                });

                // ...whenever you want
                new Timer(5000, new ActionListener() {
                    @Override public void actionPerformed(ActionEvent e) {
                        label.setBorder(BORDERS.get(new Random().nextInt(BORDERS.size())));
                    }
                }).start();

                frame.pack();
                frame.setVisible(true);
            }
        });

    }

    public static final List<Border> BORDERS;
    static {
        BORDERS = new ArrayList<Border>();
        BORDERS.add(BorderFactory.createLineBorder(Color.BLACK));
        BORDERS.add(BorderFactory.createLineBorder(Color.RED));
        BORDERS.add(BorderFactory.createEtchedBorder());
        BORDERS.add(BorderFactory.createTitledBorder("A border"));
    }
}
于 2009-05-30T00:02:09.127 に答える