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

时间:2015-06-23 11:21:58

标签: java image swing jpanel

我是一名Java初学者,我正在开发一个几乎完成的程序,并且这样做:

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

  3. 打开框架

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

    加载图像的大小加倍(因此原始图像的一个像素在所示图像中为2x2方格)。

    我的问题:当图像(/ JPanel)对于屏幕来说太大而用户最大化窗口时,图像只是一个小黑方块。

    有没有办法可以设置行为,图像只能部分显示?

    我的代码:

    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:

    谢谢:)

1 个答案:

答案 0 :(得分:1)

修复此问题更改此

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

添加组件的正确方法

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

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