1

3 つのコンポーネントが一列に並んだ JPanel を作成しようとしています。色付きのボックス、ラベル、削除ボタンが必要です。

カラーボックス用のJPanel、ラベル用のJLabel、およびカスタムImageIconを持つJButtonを格納するGridLayoutとしてJPanelセットを取得しました。

問題は、色付きのボックスとラベルの間に空白があることです。各コンポーネントの境界線を強調表示しましたが、過度に引き伸ばされているコンポーネントはないようです。

ここに私が意味するもののスクリーンショットがあります:

ここに画像の説明を入力

ここに私が取り組んでいるコードがあります: ラベルクラス:

public class Label extends JPanel {

    JButton btnDeleteObject;
    // Delete icon
    ImageIcon delIcon = new ImageIcon("Delete.png"); 
    Image img = delIcon.getImage();
    Image newimg = img.getScaledInstance(28, 28,  java.awt.Image.SCALE_SMOOTH);  
    ImageIcon scaledDelIcon = new ImageIcon(newimg);

    Color labelColour;

    public Label(String labelName, Color labelColour) {
        this.labelColour = labelColour;

        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

        addComponents(labelName);

    }   

    private void addComponents(String labelName) {

        JPanel innerContainer = new JPanel(new GridLayout(1, 3));
        JLabel name = new JLabel(labelName);

        LabelColourBox cBox = new LabelColourBox();

        name.setMaximumSize(new Dimension(80, 40));
        name.setPreferredSize(new Dimension(80, 40));
        name.setSize(new Dimension(80, 40));

        name.setBorder(BorderFactory.createLineBorder(Color.blue));

        setBorder(BorderFactory.createLineBorder(Color.black));

//      name.setBorder(new EmptyBorder(5, 5, 5, 5));

        // Add action to delete button for Icon
        Action action = new AbstractAction("Button Label", scaledDelIcon) {
            // This method is called when the button is pressed
            public void actionPerformed(ActionEvent evt) {
                System.out.println("delete");
            }
        };

        btnDeleteObject = new JButton(action);

        // Remove label, background
        btnDeleteObject.setText("");
        btnDeleteObject.setContentAreaFilled(false);

        setAlignmentX(LEFT_ALIGNMENT);

        innerContainer.add(cBox);
        innerContainer.add(name);
        innerContainer.add(btnDeleteObject);

        add(innerContainer);

    }
}

そしてここにLabelColourBoxがあります:

public class LabelColourBox extends JPanel{

    public LabelColourBox() {
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    }


    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        setBorder(BorderFactory.createLineBorder(Color.green));

        setMaximumSize(new Dimension(40, 40));
        setPreferredSize(new Dimension(40, 40));
        setSize(new Dimension(40, 40));

        g.setColor(Color.RED);
        g.fillRect(0, 0, 40, 40);
    }


}
4

2 に答える 2

4
  1. setSize / setPreferredSize / setMaximumSize / setMinimumSize / setBounds / setLocationのいずれも呼び出さず、適切なLayoutManagerを使用してください。
  2. これらのメソッドをpaintComponentで呼び出さないでください。paintComponent()=コンポーネントをペイントするため、ペイント操作(drawLine、drawRect、...)のみを実行する必要があります。
  3. GridLayoutは、最大の推奨サイズに基づいて、すべての子コンポーネントを同じサイズでレイアウトするため、通常、あまり柔軟なレイアウトではありません。したがって、このような単純なケースでは、BorderLayout、GridBagLayout、さらにはBoxLayoutとFlowLayoutを見てください。サードパーティのライブラリを使用できる場合は、MigLayoutが最適です。
于 2012-10-11T21:03:14.763 に答える
2

Guillaumeが指摘しているように、コードにはいくつかの深刻な問題があります。

paintXxxメソッド内からUIコンポーネントに変更を加えないでください

protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    // This is INCREDIBLY bad
    setBorder(BorderFactory.createLineBorder(Color.green));
    setMaximumSize(new Dimension(40, 40));
    setPreferredSize(new Dimension(40, 40));
    setSize(new Dimension(40, 40));
    //------------

    g.setColor(Color.RED);
    g.fillRect(0, 0, 40, 40);
}

これを行うと、再描画要求が再描画マネージャーに送信され、最終的にはあなたpaintComponentを呼び出して再描画要求をトリガーします...そしてCPUが100%まで循環し、プログラムが応答しなくなるので、CPUに別れを告げます。

setPreferred/Minimum/MaximumSizeできるだけ電話をかけないようにする必要があります。個々のコンポーネントでうまくいきましょう。コンポーネントをカスタマイズしている場合は、これらのメソッドをオーバーライドすると、邪悪な開発者があなたの下のコンポーネントのサイズを変更するのを防ぐことができます。

特にペイントするときは、絶対値を避ける必要があります。

g.fillRect(0, 0, 40, 40);

これは非常に危険です。このコンポーネントがに追加された場合はどうなりBorderLayoutますか?コンポーネントの左上隅にのみ正方形をペイントします...実際には有用ではありません。代わりに、効果を上げる必要のある領域のベースとして使用getWidthします。また、コンテンツが使用可能な視覚的範囲内にペイントされていることを確認するためにgetHeight、コンポーネントを考慮する必要があります。Insets

これは、コードのセクション全体を書き直すことなく、コンポーネントのサイズを変更できることも意味します:P

あなたのプログラムに関して。より柔軟なレイアウトマネージャーを使用します。 GridLayoutコンポーネントをレイアウトするための均一なグリッドを作成します。

ここに画像の説明を入力してください

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridLayout(3, 1));
                frame.add(new Label("One", Color.BLACK));
                frame.add(new Label("Two", Color.BLACK));
                frame.add(new Label("Three", Color.BLACK));
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class Label extends JPanel {

        JButton btnDeleteObject;
        // Delete icon
        ImageIcon delIcon = new ImageIcon("Delete.png");
        Image img = delIcon.getImage();
        Image newimg = img.getScaledInstance(28, 28, java.awt.Image.SCALE_SMOOTH);
        ImageIcon scaledDelIcon = new ImageIcon(newimg);
        Color labelColour;

        public Label(String labelName, Color labelColour) {
            this.labelColour = labelColour;

//            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
            // Not sure why you want to do this, but this would
            // be a more useful layout manager in the this context
            // Personally, I would just layout the components directly onto
            // this container...
            setLayout(new BorderLayout());

            addComponents(labelName);

        }

        private void addComponents(String labelName) {

//            JPanel innerContainer = new JPanel(new GridLayout(1, 3));
            JPanel innerContainer = new JPanel(new GridBagLayout());
            JLabel name = new JLabel(labelName);

            LabelColourBox cBox = new LabelColourBox();

//            name.setMaximumSize(new Dimension(80, 40));
//            name.setPreferredSize(new Dimension(80, 40));
//            name.setSize(new Dimension(80, 40));

            name.setBorder(BorderFactory.createLineBorder(Color.blue));

            setBorder(BorderFactory.createLineBorder(Color.black));

//      name.setBorder(new EmptyBorder(5, 5, 5, 5));

            // Add action to delete button for Icon
            Action action = new AbstractAction("Button Label", scaledDelIcon) {
                // This method is called when the button is pressed
                public void actionPerformed(ActionEvent evt) {
                    System.out.println("delete");
                }
            };

            btnDeleteObject = new JButton(action);

            // Remove label, background
            btnDeleteObject.setText("");
            btnDeleteObject.setContentAreaFilled(false);

            setAlignmentX(LEFT_ALIGNMENT);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.BOTH;

            innerContainer.add(cBox, gbc);
            gbc.gridx++;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.WEST;
            innerContainer.add(name, gbc);
            gbc.gridx++;
            gbc.weightx = 0;
            innerContainer.add(btnDeleteObject, gbc);

            add(innerContainer);

        }

        public class LabelColourBox extends JPanel {

            public LabelColourBox() {
                setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(40, 40);
            }

            @Override
            public Dimension getMinimumSize() {
                return getPreferredSize();
            }

            @Override
            public Dimension getMaximumSize() {
                return getPreferredSize();
            }

            @Override
            protected void paintComponent(Graphics g) {

                super.paintComponent(g);

                // DON'T DO THIS, THIS IS A VERY BAD IDEA, THIS WILL RESULT
                // IN A NEW REPAINT REQUEST BEING SENT TO THE REPAINT MANAGER
                // CAUSE THIS METHOD TO BE CALLED AND NEW REPAINT REQUEST BEING...
                // you get the idea..
                //setBorder(BorderFactory.createLineBorder(Color.green));
                //setMaximumSize(new Dimension(40, 40));
                //setPreferredSize(new Dimension(40, 40));
                //setSize(new Dimension(40, 40));

                g.setColor(Color.RED);
                g.fillRect(0, 0, getWidth() - 1, getHeight() - 1);
                g.setColor(Color.GREEN);
                g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
            }
        }
    }
}
于 2012-10-11T22:04:14.427 に答える