当最大化 window 并且 JPanel 太大时,JPanel 只是一个黑色方块

JPanel is only a black square when maximize the window and the JPanel is too big

我是一个 Java 初学者,我正在编写一个即将完成的程序并执行此操作:

  1. 通过命令行读取图像的地址并加载 图片
  2. 将图像保存为 RGB 值数组

  3. 打开框架

用户可以按 3 个按钮以不同方式(原始、灰度、图案)显示加载的图像,然后按一个按钮退出应用程序。

加载图像的大小加倍(因此原始图像的一个像素在显示的图像中是一个 2x2 的正方形)。

我的问题:当图像(/JPanel) 对于屏幕来说太大并且用户最大化 window 时,图像只有一个黑色的小方块。

有没有一种方法可以设置图像仅部分显示的行为?

我的代码:

package uebung;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


/**
 * Klasse die das Erzeugen des Fensters ermöglicht (Konstruktor, Listener, JPanel-Klassen).
 * 
 * @author Christoph Lehmann
 * @version 1.0 (13.06.2015)
 */
class MyFrame extends JFrame {

    /**
     * Panel für den Bild-Container für die zentrierte Anzeige der Bild-Panels
     */
    JPanel content = new JPanel(new GridBagLayout());

    /**
     * Container der drei Bild-Panels
     */
    JPanel panelCont = new JPanel();

    /**
     * Originaldarstellung des Bildes
     */
    JPanel panelOriginal = new DrawOriginal();

    /**
     * Graustufendarstellung des Bildes
     */
    JPanel panelGrayscale = new DrawGrayscale();

    /**
     * Musterdarstellung des Bildes
     */
    JPanel panelPattern = new DrawPattern();

    /**
     *  Einreihung der oberen Buttons
     */
    JPanel panelTop = new JPanel(); 

    /**
     *  Einreihung des unteren Buttons
     */
    JPanel panelBot = new JPanel(); 

    /**
     *  Darstellung der drei Bild-Panels
     */
    CardLayout cl = new CardLayout();

    /**
     * Wechseln zum Originalbild
     */
    JButton buttonOriginal = new JButton ("Original");

    /**
     * Wechseln zum Graustufenbild
     */
    JButton buttonGrayscale = new JButton ("Grayscale");

    /**
     * Wechseln zum Musterbild
     */
    JButton buttonPattern = new JButton ("Pattern");

    /**
     * Beenden der Anwendung
     */
    JButton buttonExit = new JButton ("Exit");

    /**
     * Erkennt das Drücken der Buttons
     */
    MyActionListener myActionListener = new MyActionListener();

    /**
     * Breite des eingelesenen Bildes
     */
    int w = DrawPicture.image.getWidth();

    /**
     * Höhe des eingelesenen Bildes
     */
    int h = DrawPicture.image.getHeight();

    /**
     * Array mit RGB-Werten jedes einzelenen Pixels des eingelesenen Bildes
     */
    int [][] RGB = DrawPicture.imageRGB;

    /**
     * Farbe beim Zeichnen in den inneren Panelklassen
     */
    Color c;

    /**
     * Erzeugt das Fenster und seine Komponenten
     */
    public MyFrame(String title, int width, int height) {
        super(title);
        setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(width*2+30, height*2+120)); //+20 und +120 sind vage Werte für die Bereiche der Buttons oben und unten
        setLocation(30,30); //nicht direkt in der Ecke aber oben links
        setVisible(true);

        //Einrichten des Containers mit CardLayout
        panelCont.setLayout(cl);
        panelCont.add(panelOriginal, "O");
        panelCont.add(panelGrayscale, "G");
        panelCont.add(panelPattern, "P");
        cl.show(panelCont,"O");
        content.add(panelCont); //GradBagLayout -> Bild-Panels werden zentriert
        add(content);

        //Einrichten der Panels für die Buttons im FlowLayout (für links und rechts)
        panelTop.setLayout(new FlowLayout(FlowLayout.LEFT));
        add(panelTop, BorderLayout.NORTH);
        panelBot.setLayout(new FlowLayout(FlowLayout.RIGHT));
        add(panelBot, BorderLayout.SOUTH);

        //Hinzufügen der Buttons + Zuweisen der Listener
        buttonOriginal.addActionListener(myActionListener);
        panelTop.add(buttonOriginal);
        buttonGrayscale.addActionListener(myActionListener);
        panelTop.add(buttonGrayscale);
        buttonPattern.addActionListener(myActionListener);
        panelTop.add(buttonPattern);
        buttonExit.addActionListener(myActionListener);
        panelBot.add(buttonExit);

        pack();
    }

    /**
     * Listener für die vier Buttons Original, Grayscale, Pattern und Exit
     */
    class MyActionListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            //e.getSource ermöglicht die Verwendung eines einzigen Listeners, anstatt für jeden Button einen eigenen erzeugen zu müssen
            if (e.getSource() == buttonExit){ 
                System.exit(0);
            } else if (e.getSource() == buttonOriginal){
                //durch cl.show kommt das CardLayout zum Einsatz, damit alle 3 Bildpanels übereinander gelegt werden aber abwechselnd angezeigt werden können
                cl.show(panelCont,"O"); 
            } 
            else if (e.getSource() == buttonGrayscale){
                cl.show(panelCont,"G");
            } 
            else if (e.getSource() == buttonPattern){
                cl.show(panelCont,"P");
            } 
        }   
    }

    /**
     * Klasse für die Darstellung des Bildes im Original.
     */
    class DrawOriginal extends JPanel {
        @Override
        public Dimension getPreferredSize () {
             return new Dimension (w*2 ,h*2);
         }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //alle Pixel des eingelesenen Bildes (anhand des RGB-Arrays) werden durchlaufen
            for (int i=0; i<w;i++){
                for (int k=0; k<h;k++){
                    c= new Color(RGB[i][k]);
                    g.setColor(c); 
                    //da das zu zeichnende Bild doppelt so groß werden muss, stellen die zu zeichnenden Koordinaten die Originalkoordinaten mal zwei dar
                    int x=i*2;
                    int y=k*2;
                    //ein Rechteck der Größe 2x2 wird in der eingelesenen Farbe (=der Farbe des Originals) gezeichnet
                    g.drawLine(x, y, x, y);
                    g.drawLine(x+1, y, x+1, y);
                    g.drawLine(x, y+1, x, y+1);
                    g.drawLine(x+1, y+1, x+1, y+1);
                }
            }
        }
    }

    /**
     * Klasse für die Darstellung des Bildes in Graustufen.
     */
    class DrawGrayscale extends JPanel {
        @Override
        public Dimension getPreferredSize () {
             return new Dimension (w*2 ,h*2);
         }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //alle Pixel des eingelesenen Bildes (anhand des RGB-Arrays) werden durchlaufen
            for (int i=0; i<w;i++){
                for (int k=0; k<h;k++){
                    c= new Color(RGB[i][k]);
                    //die einzelnen Farbwerte werden ausgelesen
                    int red = c.getRed();
                    int green = c.getGreen();
                    int blue = c.getBlue();
                    //der Mittelwert wird bestimmt
                    int avg = (red + green + blue)/3;
                    //die verwendete Farbe ist nun ein Grauwert
                    c = new Color(avg, avg, avg);
                    g.setColor(c); 
                    //da das zu zeichnende Bild doppelt so groß werden muss, stellen die zu zeichnenden Koordinaten die Originalkoordinaten mal zwei dar
                    int x=i*2;
                    int y=k*2;
                    //ein Rechteck der Größe 2x2 wird in der entsprechenden Graustufe gezeichnet
                    g.drawLine(x, y, x, y);
                    g.drawLine(x+1, y, x+1, y);
                    g.drawLine(x, y+1, x, y+1);
                    g.drawLine(x+1, y+1, x+1, y+1);
                }
            }
        }
    }

    /**
     * Klasse für die Darstellung des Bildes in Musterform.
     */
    class DrawPattern extends JPanel {
        @Override
        public Dimension getPreferredSize () {
             return new Dimension (w*2 ,h*2);
         }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //alle Pixel des eingelesenen Bildes (anhand des RGB-Arrays) werden durchlaufen
            for (int i=0; i<w;i++){
                for (int k=0; k<h;k++){
                    c= new Color(RGB[i][k]);
                    //die einzelnen Farbwerte werden ausgelesen
                    int red = c.getRed();
                    int green = c.getGreen();
                    int blue = c.getBlue();
                    //der Mittelwert wird bestimmt
                    int avg = (red + green + blue)/3;
                    // es werden die Farben Schwarz und Weiß für den Zeichenvorgang zur Verfügung gestellt
                    Color white = new Color(0, 0, 0);
                    Color black = new Color(255, 255, 255);
                    //da das zu zeichnende Bild doppelt so groß werden muss, stellen die zu zeichnenden Koordinaten die Originalkoordinaten mal zwei dar
                    int x=i*2;
                    int y=k*2;
                    //je nachdem welcher Mittelwert für den Originalpixel bestimmt wird, wird eines der fünf zu zeichnenden 2x2 Rechtecke gewählt
                    // w= white b=black
                    if (avg<=50){
                        // w w
                        // w w
                        g.setColor(white);
                        g.drawLine(x, y, x, y);
                        g.drawLine(x+1, y, x+1, y);
                        g.drawLine(x, y+1, x, y+1);
                        g.drawLine(x+1, y+1, x+1, y+1);
                    }
                    else if (avg >=51 && avg<=101){
                        // b w
                        // w w
                        g.setColor(black);
                        g.drawLine(x, y, x, y);

                        g.setColor(white);
                        g.drawLine(x+1, y, x+1, y);
                        g.drawLine(x, y+1, x, y+1);
                        g.drawLine(x+1, y+1, x+1, y+1);
                    } 
                    else if (avg >=102 && avg<=152){
                        // b w
                        // w b
                        g.setColor(black);
                        g.drawLine(x, y, x, y);
                        g.drawLine(x+1, y+1, x+1, y+1);

                        g.setColor(white);
                        g.drawLine(x+1, y, x+1, y);
                        g.drawLine(x, y+1, x, y+1);
                    } 
                    else if (avg >=153 && avg<=203){
                        // w b
                        // b b
                        g.setColor(black);
                        g.drawLine(x+1, y, x+1, y);
                        g.drawLine(x, y+1, x, y+1);
                        g.drawLine(x+1, y+1, x+1, y+1);

                        g.setColor(white);
                        g.drawLine(x, y, x, y);
                    }
                    else {
                        // b b
                        // b b
                        g.setColor(black);
                        g.drawLine(x, y, x, y);
                        g.drawLine(x+1, y, x+1, y);
                        g.drawLine(x, y+1, x, y+1);
                        g.drawLine(x+1, y+1, x+1, y+1);         
                    }
                }
            }
        }
    }
}

/**
 * Anwendung die das Bild aus der Kommandozeile ausliest, das Bild in einem intRGB-Array speichert und das Fenster öffnet.
 */
public class DrawPicture {

    static BufferedImage image = null;
    static int [][] imageRGB;

    public static void main(String[] args) {
        System.out.println("Bitte geben sie den Pfad des gewünschten Bildes ein.\nMit der Eingabe von EXIT können sie die Eingabe abbrechen und das Programm beenden.");
        System.out.print("Pfad: ");

        String path = "";

        //verlangt so lange eine Eingabe vom Nutzer, bis erfolgreich ein Bild eingelsen wurde, oder der Nutzer die Eingabe abbricht
        while (true) {
            try {
                BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
                path = bufferRead.readLine();

                if (path.equals("EXIT")){
                    System.exit(0);
                }

                image = ImageIO.read(DrawPicture.class.getResource(path));
                break;
            } catch (Exception e) { //IOException, InvalidArgumentException, ...
                System.out.println("Das Bild konnte nicht geladen werden. Versuchen sie es erneut.");
                System.out.print("Pfad: ");
            }
        }

        //Speichert das eingelesene Bild in einem Array (RGB-Werte)
        imageRGB = new int[image.getWidth()][image.getHeight()];

        for (int x=0; x<image.getWidth();x++){
            for (int y=0; y<image.getHeight();y++){
                imageRGB[x][y]=image.getRGB(x, y);
            }
        }

        //öffnet das Fenster
        new MyFrame("DrawPicture", image.getWidth(), image.getHeight());
    }
}

这里有两张图片:

Startup

Maximized windows:

谢谢:)

要解决此问题,请更改此

JPanel content = new JPanel(new GridBagLayout()); // about line 30 

至此

JPanel content = new JPanel(new GridLayout(1, 1));


问题是这一行

JPanel content = new JPanel(new GridBagLayout());//

和这一行

content.add(panelCont); 

这不是向 gridBag layout

添加组件的正确方法

因为您应该在 content 面板中显示整个 panelCont,我将 gridbag 布局更改为 new GridLayout(1, 1) 并且问题已解决。

无论如何,如果你想使用 gridbag 布局,请阅读此 http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html