图形未出现在 CardLayout 上

Graphic Not Appearing on CardLayout

我正在构建一个使用 CardLayout 在屏幕之间切换的 GUI。我希望其中一个屏幕上有图形。我已经成功地将一个矩形放到一个带有 GridLayout 的面板上,然后将该面板放到一个主面板上,并且一个矩形清晰可见。但是,当我将该面板放到 CardLayout 面板上时,该矩形无处可见。将图形添加到 CardLayout 面板时是否需要做一些不同的事情?

主要Class

import java.awt.CardLayout;
import java.awt.Container;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import javax.swing.JLabel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Dimension;

public class Window extends JFrame {
    public Window() {
        // Main Panel Configuration
        Container panel = this.getContentPane();
        panel.setLayout(new GridBagLayout());
        panel.setSize(1000,1000);
        GridBagConstraints gbc = new GridBagConstraints();

        // GridBag Constraints
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridheight = 1;
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.gridx = 0;
        gbc.gridy = 0;

        // Button Tabs
        JButton button1 = new JButton("button 1");
        panel.add(button1, gbc);

        JButton button2 = new JButton("button 2");
        gbc.gridx = 1;
        panel.add(button2, gbc);

        // Panels for CardLayout
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();

        // Set Layout of Panels
        panel1.setLayout(new GridBagLayout());
        panel2.setLayout(new GridBagLayout());

        // Set Dimensions of Panels
        panel1.setSize(new Dimension(900, 500));
        panel2.setSize(new Dimension(900, 500));

        // Labels for panels
        JLabel label1 = new JLabel("label 1");
        gbc.gridx = 1;
        gbc.gridy = 2;
        panel1.add(label1, gbc);

        JLabel label2 = new JLabel("label 2");
        gbc.gridy = 2;
        panel2.add(label2, gbc);

        // TextFields for Panels
        JTextField textField1 = new JTextField();
        gbc.gridx = 2;
        gbc.gridy = 2;
        panel1.add(textField1, gbc);

        JTextField textField2 = new JTextField();
        gbc.gridy = 2;
        panel2.add(textField2, gbc);


        // Add Graphic to panel1
        JPanel drawingPanel = new JPanel();
        DrawingComponent dc = new DrawingComponent();
        dc.setPreferredSize(new Dimension(100, 100));
        drawingPanel.add(dc);
        gbc.gridx = 0;
        gbc.gridy = 3;
        panel1.add(drawingPanel,gbc);


        // Set TextField Dimensions
        textField1.setPreferredSize(new Dimension(400, 20));
        textField2.setPreferredSize(new Dimension(400, 20));

        // CardLayout Panel for Entry Fields and Labels
        JPanel cardLayoutPanel = new JPanel();
        CardLayout c1 = new CardLayout();
        cardLayoutPanel.setLayout(c1);
        cardLayoutPanel.setSize(new Dimension(900, 600));

        // Add Panels to CardLayout Panel
        cardLayoutPanel.add("panel1",panel1);
        cardLayoutPanel.add("panel2", panel2);

        // Which panel to show First
        c1.show(cardLayoutPanel, "panel1");

        // Add CardLayout Panel to Main Panel
        gbc.gridy = 1;
        gbc.gridx = 0;
        panel.add(cardLayoutPanel, gbc);


        // Action Listeners Changing Between Tabs
        button1.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent arg0) {
                c1.show(cardLayoutPanel, "panel1");
            }
        });


        button2.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent arg0) {
                c1.show(cardLayoutPanel, "panel2");
            }
        });

        setSize(800,600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

    }


    public static void main(String[] args){
        Window window = new Window();

    }
}

绘图组件Class

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.awt.Rectangle;

public class DrawingComponent extends JComponent {
    public void paintComponent(Graphics g){
        Graphics2D g2 = (Graphics2D) g;

        Rectangle rect1 = new Rectangle(400, 400, 50, 50);
        g2.draw(rect1);
    }
}

本部分:

JPanel drawingPanel = new JPanel();
DrawingComponent dc = new DrawingComponent();
dc.setPreferredSize(new Dimension(100, 100));
drawingPanel.add(dc);

您将 DrawingComponent 的首选大小设置为 (100,100)。然后,在绘制组件时,使用构造函数 Rectangle(int x, int y, int width, int height).

Rectangle(400, 400, 50, 50) 中绘制矩形

话虽如此,我认为这是很明显的。您的组件是 100x100,但您尝试在第 400x400 个像素处绘制,这导致矩形绘制在组件边界之外。

我不知道矩形的坐标应该是什么,但如果您希望显示您的组件,请将矩形更改为 Rectangle rect1 = new Rectangle(0, 0, 50, 50);

此外,评论中提到的 VGR(他得到了我:P)当你 override paintComponent 方法时,确保你调用 super.paintComponent().

最后,使用 SwingUtilities#invokeLater 方法启动您的应用程序。

把我的意思总结成代码:

public static class DrawingComponent extends JComponent {
        public void paintComponent(Graphics g) {
            super.paintComponent(g); // Should always start with super method.
            Graphics2D g2 = (Graphics2D) g;

            Rectangle rect1 = new Rectangle(0, 0, 50, 50);
            g2.draw(rect1);
        }
    }

    public static void main(String[] args) {
        // All swing applications must run on their own thread named EDT (Event dispatch thread)
        SwingUtilities.invokeLater(() -> {
            Window window = new Window();
        });
    }

一个问题是您在组件边界之外绘制。在 (400, 400) 绘制一个矩形将导致什么都看不到,当组件本身被强制具有 100×100 的尺寸时。

另一个问题是您试图明确设置组件的大小和 window。但是 window 对于这些尺寸来说不够大。当 GridBagLayout 无法容纳其子项的首选尺寸时,它会“放弃”并将所有内容设置为其最小尺寸。由于 DrawingComponent 没有定义最小尺寸,它恢复为零宽度和零高度。 (您使用 fill=HORIZONTAL 强制它与其单元格一样宽,但高度仍然为零。)

设置所有这些尺寸是不正确的。几乎没有正当理由调用 setSize 或 setPreferredSize。

对于 JTextField,您需要使用其 setColumns 方法设置其大小。

DrawingComponent class 应该知道它想要的大小,并且它应该 return 通过覆盖它自己的 getPreferredSize 方法来确定该大小。显然它必须足够大才能容纳自己的画:

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

对于面板和 windows,根本不要设置大小。如果您构建整个 window 然后在其上调用 pack(),它们都将足够大以容纳它们的子组件。

同样,您的代码中应该没有 调用 setSize 或 setPreferredSize。你不需要它们。