【问题标题】:Position Image in any Screen Resolution以任何屏幕分辨率定位图像
【发布时间】:2013-07-24 17:51:09
【问题描述】:

我的程序有问题。每次更改屏幕分辨率时,我的图像都会开始移动。即使我更改为任何其他分辨率,有关如何使我的图像保持在同一位置的任何建议?

p2 = new JPanel();
p2.setLayout(new FlowLayout());      
ImageIcon img2 = new ImageIcon("C:\\Drum\\Invisible4.png");             
jbtn2 = new JLabel(img2);
p2.add(jbtn2);                      
add(jbtn2);
jbtn2.setSize(jbtn2.getPreferredSize());
jbtn2.setLocation(140, 380);

【问题讨论】:

  • 不要尝试手动定位,而是使用布局管理器...例如GridBagLayoutBorderLayout。真正的问题是,你真正想要它在哪里
  • 如何使用布局管理器?我正在创建一个鼓程序。我需要将鼓镲和嗵鼓放在特定位置,使其看起来像套鼓。上面的代码只是显示一个鼓图像。
  • 好的,它需要扩展吗?那么当窗口大小发生变化时,图片是否需要按比例缩放?
  • 是的,它也需要按比例缩放
  • 请参阅this answer 了解可能的提示。

标签: java swing awt layout-manager


【解决方案1】:

创建“正常”屏幕大小与其当前大小的百分比/比率,并将其乘以 pos。例如,如果您使用的屏幕尺寸是 400x600

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
double widthRat = width/600
double heightRat = height/400

然后

jbtn2.setLocation(140*widthRat, 380*heightRat);

这样说屏幕尺寸加倍到 1200x800 widthRat = 2 并且位置加倍。这是一个草率的例子,但给出了想法

【讨论】:

  • 恕我直言,您最好设计一个比例布局管理器,该管理器能够根据首选大小和实际容器的大小定义组件的大小和位置。这样您就无需添加大量侦听器来保持所有更新,因为您将在 Swing 框架中工作
  • 真的,我并没有真正考虑按需增加尺寸。
【解决方案2】:

我更喜欢使用绝对布局。以下是适合您的代码。

Toolkit toolkit=Toolkit.getDefaultToolkit();
JPanel1.setSize(toolkit.getScreenSize().width, toolkit.getScreenSize().height);
int w=toolkit.getScreenSize().width;
int h=toolkit.getScreenSize().height;
JPanel1.setBounds(0, 0, w, h);

此代码将获取您计算机的当前分辨率...

【讨论】:

    【解决方案3】:

    我更喜欢总是在我可以的框架范围内尝试和工作,从长远来看,这通常会让生活更轻松。

    Swing 已开始设计为与 LayoutManagers 一起使用,这意味着 Swing 更新其组件和传达这些更改的方式是基于对 LayoutManagers 的使用(或多或少)。

    以下示例使用来自Java: maintaining aspect ratio of JPanel background image 的片段来缩放图像和PropertionalLayoutManager,它旨在尝试不仅缩放大小,还根据父容器的大小缩放组件的位置。

    这里演示的PropertionalLayoutManager 将尝试围绕父容器的中心布置组件。你可以改变它,但它看起来很奇怪 - 恕我直言

    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.LayoutManager2;
    import java.awt.RenderingHints;
    import java.awt.Transparency;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.Map;
    import java.util.WeakHashMap;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Drums {
    
        protected static BufferedImage SYMBOL;
        protected static BufferedImage DRUM;
    
        public static void main(String[] args) {
            new Drums();
        }
    
        public Drums() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new PropertionalLayoutManager(400, 400));
                add(new Symbol(), new PropertionalConstraint(0f, 0));
                add(new Symbol(), new PropertionalConstraint(0.67f, 0));
                add(new Symbol(), new PropertionalConstraint(0f, 0.4675f));
                add(new Symbol(), new PropertionalConstraint(0.67f, 0.4675f));
                add(new Drum(), new PropertionalConstraint(0.205f, 0.1f));
                add(new Drum(), new PropertionalConstraint(0.5f, 0.1f));
                add(new Drum(), new PropertionalConstraint(0f, 0.33f));
                add(new Drum(), new PropertionalConstraint(0.705f, 0.33f));
            }
        }
    
        public class PropertionalConstraint {
    
            private float x;
            private float y;
    
            public PropertionalConstraint(float x, float y) {
                this.x = x;
                this.y = y;
            }
    
            public float getX() {
                return x;
            }
    
            public float getY() {
                return y;
            }
        }
    
        public class PropertionalLayoutManager implements LayoutManager2 {
    
            private Map<Component, PropertionalConstraint> constraints;
            private Dimension defaultSize;
    
            public PropertionalLayoutManager(int defaultWidth, int defaultHeight) {
                constraints = new WeakHashMap<>(25);
                defaultSize = new Dimension(defaultWidth, defaultHeight);
            }
    
            @Override
            public void addLayoutComponent(Component comp, Object constraint) {
                if (constraint instanceof PropertionalConstraint) {
                    constraints.put(comp, ((PropertionalConstraint) constraint));
                }
            }
    
            @Override
            public Dimension maximumLayoutSize(Container target) {
                return preferredLayoutSize(target);
            }
    
            @Override
            public float getLayoutAlignmentX(Container target) {
                return 0.5f;
            }
    
            @Override
            public float getLayoutAlignmentY(Container target) {
                return 0.5f;
            }
    
            @Override
            public void invalidateLayout(Container target) {
            }
    
            @Override
            public void addLayoutComponent(String name, Component comp) {
            }
    
            @Override
            public void removeLayoutComponent(Component comp) {
                constraints.remove(comp);
            }
    
            @Override
            public Dimension preferredLayoutSize(Container parent) {
    
                return defaultSize;
    
            }
    
            @Override
            public Dimension minimumLayoutSize(Container parent) {
                return preferredLayoutSize(parent);
            }
    
            @Override
            public void layoutContainer(Container parent) {
    
                int width = parent.getWidth();
                int height = parent.getHeight();
    
                double dScaleWidth = getScaleFactor(defaultSize.width, width);
                double dScaleHeight = getScaleFactor(defaultSize.height, height);
    
                double scaleSize = Math.min(dScaleHeight, dScaleWidth);
                int minRange = Math.min(width, height);
    
                if (width > 0 && height > 0) {
    
                    int maxY = 0;
                    int maxX = 0;
    
                    for (Component comp : parent.getComponents()) {
                        PropertionalConstraint p = constraints.get(comp);
                        if (p != null) {
                            Dimension prefSize = comp.getPreferredSize();
    
                            prefSize.width *= scaleSize;
                            prefSize.height *= scaleSize;
    
                            int x = Math.round(minRange * p.getX());
                            int y = Math.round(minRange * p.getY());
    
                            comp.setBounds(x, y, prefSize.width, prefSize.height);
    
                            maxX = Math.max(maxX, x + prefSize.width);
                            maxY = Math.max(maxY, y + prefSize.height);
                        } else {
                            comp.setBounds(0, 0, 0, 0);
                        }
                    }
    
                    for (Component comp : parent.getComponents()) {
                        System.out.println("maxX = " + maxX);
                        System.out.println("maxY = " + maxY);
                        if (comp.getWidth() > 0 && comp.getHeight() > 0) {
                            int x = ((width - maxX) / 2) + comp.getX();
                            int y = ((height - maxY) / 2) + comp.getY();
                            comp.setLocation(x, y);
                        }                    
                    }
    
                } else {
    
                    for (Component comp : parent.getComponents()) {
                        comp.setBounds(0, 0, 0, 0);
                    }
    
                }
    
            }
        }
    
        public abstract class AbstractKitPiecePane extends JPanel {
    
            private BufferedImage scaled;
    
            public AbstractKitPiecePane() {
                setOpaque(false);
            }
    
            public abstract BufferedImage getKitImage();
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(getKitImage().getWidth(), getKitImage().getHeight());
            }
    
            @Override
            public void invalidate() {
                super.invalidate();
                if (getWidth() > 0 && getHeight() > 0) {
                    scaled = getScaledInstanceToFit(getKitImage(), getSize());
                } else {
                    scaled = null;
                }
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (scaled != null) {
                    int x = (getWidth() - scaled.getWidth()) / 2;
                    int y = (getHeight() - scaled.getHeight()) / 2;
                    g.drawImage(scaled, x, y, this);
                }
            }
        }
    
        public class Drum extends AbstractKitPiecePane {
    
            @Override
            public BufferedImage getKitImage() {
                return DRUM;
            }
        }
    
        public class Symbol extends AbstractKitPiecePane {
    
            @Override
            public BufferedImage getKitImage() {
                return SYMBOL;
            }
        }
    
        protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {
    
            BufferedImage imgScale = img;
    
            int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
            int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);
    
            if (dScaleFactor <= 1.0d) {
    
                imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    
            } else {
    
                imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    
            }
    
            return imgScale;
    
        }
    
        protected static BufferedImage getScaledDownInstance(BufferedImage img,
                int targetWidth,
                int targetHeight,
                Object hint) {
    
    //        System.out.println("Scale down...");
            int type = (img.getTransparency() == Transparency.OPAQUE)
                    ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
    
            BufferedImage ret = (BufferedImage) img;
    
            if (targetHeight > 0 || targetWidth > 0) {
                int w, h;
                w = img.getWidth();
                h = img.getHeight();
    
                do {
    
                    if (w > targetWidth) {
                        w /= 2;
                        if (w < targetWidth) {
                            w = targetWidth;
                        }
                    }
    
                    if (h > targetHeight) {
                        h /= 2;
                        if (h < targetHeight) {
                            h = targetHeight;
                        }
                    }
    
                    BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
                    Graphics2D g2 = tmp.createGraphics();
                    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
                    g2.drawImage(ret, 0, 0, w, h, null);
                    g2.dispose();
    
                    ret = tmp;
    
                } while (w != targetWidth || h != targetHeight);
            } else {
                ret = new BufferedImage(1, 1, type);
            }
    
            return ret;
        }
    
        protected static BufferedImage getScaledUpInstance(BufferedImage img,
                int targetWidth,
                int targetHeight,
                Object hint) {
    
            int type = BufferedImage.TYPE_INT_ARGB;
    
            BufferedImage ret = (BufferedImage) img;
            int w, h;
            w = img.getWidth();
            h = img.getHeight();
    
            do {
                if (w < targetWidth) {
                    w *= 2;
                    if (w > targetWidth) {
                        w = targetWidth;
                    }
                }
    
                if (h < targetHeight) {
                    h *= 2;
                    if (h > targetHeight) {
                        h = targetHeight;
                    }
                }
    
                BufferedImage tmp = new BufferedImage(w, h, type);
                Graphics2D g2 = tmp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
                g2.drawImage(ret, 0, 0, w, h, null);
                g2.dispose();
    
                ret = tmp;
                tmp = null;
            } while (w != targetWidth || h != targetHeight);
    
            return ret;
        }
    
        public static BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) {
            double scaleFactor = getScaleFactorToFit(img, size);
            return getScaledInstance(img, scaleFactor);
        }
    
        public static double getScaleFactorToFit(BufferedImage img, Dimension size) {
            double dScale = 1;
    
            if (img != null) {
                int imageWidth = img.getWidth();
                int imageHeight = img.getHeight();
                dScale = getScaleFactorToFit(new Dimension(imageWidth, imageHeight), size);
            }
    
            return dScale;
        }
    
        public static double getScaleFactorToFit(Dimension original, Dimension toFit) {
            double dScale = 1d;
    
            if (original != null && toFit != null) {
                double dScaleWidth = getScaleFactor(original.width, toFit.width);
                double dScaleHeight = getScaleFactor(original.height, toFit.height);
                dScale = Math.min(dScaleHeight, dScaleWidth);
            }
    
            return dScale;
        }
    
        public static double getScaleFactor(int iMasterSize, int iTargetSize) {
            double dScale = 1;
            if (iMasterSize > iTargetSize) {
                dScale = (double) iTargetSize / (double) iMasterSize;
            } else {
                dScale = (double) iTargetSize / (double) iMasterSize;
            }
    
            return dScale;
        }
    
        static {
    
            try {
                SYMBOL = ImageIO.read(new File("Symbol.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            try {
                DRUM = ImageIO.read(new File("Drum.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
    
        }
    }
    

    以及程序中使用的图像,供您欣赏。它们位于运行程序的同一目录中

    【讨论】:

    • 我尝试运行该程序,但它显示此错误:javax.imageio.IIOException: Can't read input file!在 javax.imageio.ImageIO.read(ImageIO.java:1301) 在 test.(test.java:405) javax.imageio.IIOException: 无法读取输入文件!在 javax.imageio.ImageIO.read(ImageIO.java:1301) 在 test.(test.java:410) 线程“AWT-EventQueue-0”中的异常 java.lang.NullPointerException
    • 当然,您需要提供自己的符号和鼓的图像:P
    • @mKorbel 是的,找不到:P
    • 感谢工作代码。任何想法我可以将 mouseListener 插入以下图像
    • 最好的方法是将它附加到组件本身。如果您想在顶级面板上使用单个侦听器,可以在鼠标侦听器中使用 getComponentAt(Point) 来查找被点击的组件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    相关资源
    最近更新 更多