0

そのため、メニュー、ツールバー、およびパネルを備えた JFrame があります。パネル内に画像をロードしましたが、何らかの奇妙な理由で (少なくとも私には) パネルに正しく表示されません。ツールバーの下から開始することもあれば、上から開始することもあります。さらに画像は下がカットされています。このコードは、コンパイルしてテストできる完全なものからクリーンな例です。前もって感謝します。

含まれるフレームのクラス:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FileDialog;

    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.zip.ZipInputStream;

    import javax.imageio.ImageIO;
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JFileChooser;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JToolBar;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.Border;
    public class SSCE extends JFrame {
        private JComicPanel panel;
        private JToolBar toolbar;
        private JButton buttonZoom;
        private JButton buttonPrev;
        private JButton buttonNext;
        private JMenuBar menuBar;

        private Dimension dim;
        private BufferedImage img;
        private int currentPage;
        private JFrame parentFrame;




                public SSCE(){

                    super("JComic");
                    BorderLayout layout = new BorderLayout();
                    setLayout(layout);

                    dim = Toolkit.getDefaultToolkit().getScreenSize();

                    setSize((int)(dim.width /2.5),dim.height);

                    this.setPreferredSize(new Dimension((int) (dim.width /2.5),dim.height));

                    createToolbar();
                    createPanel();

                    add(toolbar,BorderLayout.NORTH);    

                    add(panel,BorderLayout.CENTER);


                    createMenu();
                    add(menuBar);
                    setJMenuBar(menuBar);
                    panel.setVisible(true);
                    img = null;
                    pack();
                    parentFrame = this;

                }


                private void createPanel(){
                    Border raisedbevel, loweredbevel;
                    raisedbevel = BorderFactory.createRaisedBevelBorder();
                    loweredbevel = BorderFactory.createLoweredBevelBorder();
                    panel = new JComicPanel(img);
                    panel.setBorder(BorderFactory.createCompoundBorder(raisedbevel,loweredbevel));


                }
                private void createToolbar(){
                    toolbar = new JToolBar();
                    toolbar.setPreferredSize(new Dimension(dim.width,45));  
                    toolbar.setFloatable(false);
                    buttonZoom = new JButton("+");

                    toolbar.add(buttonZoom);
                    buttonPrev = new JButton("<-");
                    toolbar.add(buttonPrev);
                    buttonNext = new JButton("->");
                    toolbar.add(buttonNext);
                    toolbar.setBackground(Color.RED);


                }
                private void createMenu(){
                    JMenu menuFile,menuJComic;
                    JMenuItem fileOpen; 
                    JMenuItem quitJComic,aboutJComic;


                    menuBar = new JMenuBar();
                    menuJComic = new JMenu("JComic");
                    aboutJComic = new JMenuItem("About JComic...");
                    menuJComic.add(aboutJComic);
                    quitJComic = new JMenuItem("Quit");
                    quitJComic.addActionListener(
                            new ActionListener(){
                                public void actionPerformed(ActionEvent e) {
                                    System.exit(0);
                                }
                            }
                            );
                    menuJComic.add(quitJComic);

                    menuBar.add(menuJComic);

                    menuFile = new JMenu("File");

                    fileOpen = new JMenuItem("Open...");
                    fileOpen.addActionListener(
                            new ActionListener(){
                                public void actionPerformed(ActionEvent e) {
                                    try {


                                        img = ImageIO.read(new File("superman.jpg"));
                                        currentPage = 1;

                                        int offset = menuBar.getHeight() + toolbar.getHeight();
                                        panel.setImage(img,parentFrame,offset);


                                    }
                                    catch (IOException e1) {
                                        System.out.println(e1.getMessage());
                                    }

                                }
                            }
                            );

                    menuFile.add(fileOpen);
                    menuBar.add(menuFile);


                }

        /**
         * @param args
         */
        @SuppressWarnings("deprecation")
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            SSCE f = new SSCE();
            f.show();

        }

    }

パネルのクラス

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.RenderingHints;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.awt.image.BufferedImage;
    import java.io.File;

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

    public class JComicPanel extends JPanel{
        private BufferedImage img;
        private int offset;
        private final float scaling = 0.5f;
        public JComicPanel(BufferedImage img){
            super();
            this.img = img;
            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e)
                {
                    repaint();
                }
            });

        }




         public void setImage(BufferedImage img,JFrame parentFrame,int offset){



             try{

                 int w = img.getWidth();
                 int h = img.getHeight();
                 int newW = (int)(w * scaling);
                 int newH = (int)(h * scaling);
                 BufferedImage dimg =  new BufferedImage(newW, newH, img.getType());  
                 Graphics2D g = dimg.createGraphics();  
                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);  
                 g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);  
                 this.img = img;
                 System.out.printf("dim %d x %d",newW,newH);


                 this.setSize(new Dimension(newW,newH+offset));

                 parentFrame.pack();
             }
             catch(Exception e){
             }


         }

         public Dimension getPreferredSize(){

             return new Dimension(img.getWidth(),img.getHeight());
         }

        public void paintComponent(Graphics g){

               // Draw our Image object.
               super.paintComponent(g);
               g.drawImage(img,0,0,getSize().width,getSize().height, this); // at location 50,10
               System.out.println("painting 2");
              }

    }

画像 superman.jpg はhttp://i50.tinypic.com/2yxnc3n.jpgにあります。ご覧のとおり、画像はツールバーの下にありますが、私の完全なコードでは上にも表示されます。

4

2 に答える 2

5

ここから始めましょう...

public void setImage(BufferedImage img,JFrame parentFrame,int offset){
    try{
        // You're scaling the incoming image, which means you no longer
        // have a reference to the original image should you want to 
        // change that scale...
        // You're previous code...

        // Don't do this.  The parent container's layout manager will simple
        // override it, so it's useless...
        this.setSize(newW,newH);
        repaint();

        // This is a bad idea (personally)...
        parentFrame.setSize(newW,newH+offset);
    } catch(Exception e){
    }
 }

この方法で呼び出すsetSizeと、コンポーネントが設定したサイズを一時的に想定できるようになります。その後に呼び出すinvalidate()と、コンポーネントは実際にはレイアウト マネージャーの要件を満たすようにサイズ変更されます。

より大きな問題は、親フレームのサイズを設定しているという事実ですが、ツールバー、メニューバー、フレームなどの他のコンポーネントに関するフレームのレイアウト要件がわかりません(たとえば)

原画の比率を考えずに描いています

g.drawImage(img,0,0,getSize().width,getSize().height, this);

提案されているように、画像をスケーリングした後、を使用して画像ペインに追加された JLabel のアイコンとして画像を設定する方が簡単な場合があります。BorderLayout

パネルのサイズが正しいと仮定していますが、パネルのレイアウト マネージャーが引き継ぐため、そうではありません。

コンポーネントのサイズが変更されると、Swing はコンポーネントを自動的に再描画するため、これは冗長です。

addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e)
    {
        repaint();
    }
});

画像ペインをスクロール ペインにドロップするか、ペインのサイズに動的に収まるように画像を再スケーリングすることをお勧めします。

例えば...

スケーラブルなページ

ここに画像の説明を入力ここに画像の説明を入力

public class ComicPage {

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

    public ComicPage() {
        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) {
                }

                try {
                    BufferedImage page = ImageIO.read(getClass().getResource("/1346.gif"));
                    ComicPagePane comicPagePane = new ComicPagePane();
                    comicPagePane.setComicPage(page);

                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(comicPagePane);
                    frame.setSize(200, 200);
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class ComicPagePane extends JPanel {

        private BufferedImage comicPage;
        private Image scaledInstance;

        public void setComicPage(BufferedImage page) {
            if (page != comicPage) {
                comicPage = page;
                scaledInstance = null;
                repaint();
            }
        }

        @Override
        public void invalidate() {
            scaledInstance = null;
            super.invalidate(); 
        }

        public BufferedImage getComicPage() {
            return comicPage;
        }

        public double getScaleFactor(int iMasterSize, int iTargetSize) {
            return (double) iTargetSize / (double) iMasterSize;
        }

        public double getScaleFactorToFit(BufferedImage img) {
            double dScale = 1d;

            double dScaleWidth = getScaleFactor(img.getWidth(), getWidth());
            double dScaleHeight = getScaleFactor(img.getHeight(), getHeight());

            dScale = Math.min(dScaleHeight, dScaleWidth);

            return dScale;
        }

        protected Image getScaledInstance(BufferedImage master) {
            if (scaledInstance == null) {
                double scaleFactor = getScaleFactorToFit(master);
                System.out.println("scaleFactor = " + NumberFormat.getNumberInstance().format(scaleFactor));

                // This is not the best scaling alorithm
                scaledInstance = master.getScaledInstance(
                        (int) Math.round(master.getWidth() * scaleFactor),
                        (int) Math.round(master.getHeight() * scaleFactor), Image.SCALE_SMOOTH);
            }
            return scaledInstance;
        }

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

            BufferedImage comicPage = getComicPage();
            if (comicPage != null) {
                Graphics2D g2d = (Graphics2D) g.create();

                int width = getWidth();
                int height = getHeight();

                // Normally, I would put this into a background worker as this
                // operation can be expensive....
                Image scaledInstance = getScaledInstance(comicPage);

                int x = (width - scaledInstance.getWidth(this)) / 2;
                int y = (height - scaledInstance.getHeight(this)) / 2;
                g2d.drawImage(scaledInstance, x, y, this);
                g2d.dispose();
            }
        }
    }
}

スクロール可能なページ

ここに画像の説明を入力

public class ScrollableComicPage {

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

    public ScrollableComicPage() {
        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) {
                }

                try {
                    BufferedImage page = ImageIO.read(getClass().getResource("/1346.gif"));
                    ComicPagePage comicPagePane = new ComicPagePage();
                    comicPagePane.setComicPage(page);

                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JScrollPane(comicPagePane));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class ComicPagePage extends JPanel {

        private BufferedImage comicPage;

        @Override
        public Dimension getPreferredSize() {
            return comicPage != null ? new Dimension(comicPage.getWidth(), comicPage.getHeight()) : new Dimension(0, 0);
        }

        public void setComicPage(BufferedImage page) {
            if (page != comicPage) {

                comicPage = page;
                invalidate();
                repaint();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (comicPage != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(comicPage, 0, 0, this);
                g2d.dispose();
            }
        }
    }
}

スケーリング手法の詳細については、Java: JPanel 背景画像の縦横比の維持を参照してください。

于 2012-10-31T22:11:48.853 に答える
2

技術的な理由は、menuBar を contentPane の中央に一時的に追加しているためです。これは、以前に追加したパネルと同じ論理的な場所です。

add(panel, BorderLayout.CENTER);
// following line is wrong - must be removed!!! 
add(menuBar); // no constraint == BorderLayout.CENTER
setJMenuBar(menuBar);

そうすることで、パネルは LayoutManager のコントロールから外されますが、パネルの外には押し出されません。最終的な効果は、制約がないということです。

これは menuBar であることには特別なことではありません (contentPane ではなく、rootPane の layeredPane に追加する必要があります。そのため、独自の特殊化されたメソッド setJMenuBar があります)。中央にある他の任意のコンポーネントでも同じ混乱が発生します。

それとは別に、コードをクリーンアップすることをお勧めします。

  • すべてのsetXXSizeを削除します (いくつかの理由)
  • フレームを優先 (pack を使用) するか、任意の固定サイズ (setSize を使用) で表示するかを決定します。ほとんどの場合、前者は正しいことですが、後者にはユースケースがありますが、両方を行うことは意味がありません
  • コンポーネントはデフォルトで表示されます
于 2012-11-01T10:57:24.883 に答える