2

だから私はJavaで画像を変更する方法を見つけようとしています。つまり、ユーザーが画像をクリックすると、ユーザーがクリックした場所にマークが付けられます。JLabelに入れたImageIconがあります。これまでのところ、私が採用したアプローチは、JLayeredPanelを使用して別のJPanelをJLabelの上に配置し、このJPanelを利用することでした。

//...
ImageIcon icon = new ImageIcon("foo.jpg");
JLabel lb = new JLabel(icon);
JPanel glass = new JPanel();
lb.setBounds(0, 0, 100, 100);
glass.setBounds(0, 0, 100, 100);
glass.setOpaque(false);
LayeredPane container = new LayeredPane();
container.add(lb, 1);
container.add(glass, 2);

//...

しかし、この方法はうまくいかないようです。背景画像(ポンド単位の画像)が表示されません。それで、私は私がまったく正しい軌道に乗っているのかどうか疑問に思いましたか?または、これを達成するためのよりクリーンな方法はありますか?

4

2 に答える 2

3

別のペインを使用したいということで、あなたは正しい方向に進んでいます。Javaには、実際には、この目的のためだけに設計されたガラス板がすでにあります。このチュートリアルhttp://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.htmlを読むと、理解に役立つはずです。

于 2013-01-11T20:58:52.433 に答える
3

個人的には、このようなものにまたはガラス板を使用するJLayeredPaneことに問題はありません。大規模なアプリケーションでは、これらのレイヤーをさまざまな用途に使用する傾向があるため、非常に複雑になります。

私はそれをいわば「家族の中で」保つことを好みます...

個人的には、カスタムコンポーネントを使用します。これにより、ワークフローが非常に特定の場所に分離され、必要なカスタマイズを簡単に提供できるようになります...

ここに画像の説明を入力してください

public class MarkImage {

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

    public MarkImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                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 {

        private BufferedImage background;
        private List<Point> clickPoints;

        public TestPane() {
            clickPoints = new ArrayList<>(25);
            try {
                background = ImageIO.read(getClass().getResource("/Miho_Small.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    clickPoints.add(e.getPoint());
                    repaint();
                }
            });
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g.drawImage(background, x, y, this);
            }
            g.setColor(Color.RED);
            for (Point p : clickPoints) {
                g.fillOval(p.x - 4, p.y - 4, 8, 8);
            }
        }

    }

}

( Java 7ではJXLayerAKA )の使用も検討します。JLayerこれは、コンポーネント用のガラス板(ステロイド上)として最もよく説明されています。詳細については、コンポーネントを装飾する方法を確認してください...

JLayerの例で更新

これは、Java7を使用した例JLayerです。JLayerとの間には若干の違いがありますがJXLayer、変換するのにそれほど時間はかかりません...

(申し訳ありませんが、前に持っているという誘惑に抵抗できませんでした)

ここに画像の説明を入力してください

public class MarkLayer {

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

    public MarkLayer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new GridBagLayout());

                    JLabel label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/Miho_Small.png"))));
                    LayerUI<JLabel> layerUI = new MarkLayerUI();
                    JLayer<JLabel> layer = new JLayer<>(label, layerUI);

                    frame.add(layer);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class MarkLayerUI extends LayerUI<JLabel> {

        private Map<JLayer, List<Point>> mapPoints;

        public MarkLayerUI() {
            mapPoints = new WeakHashMap<>(25);
        }

        @Override
        public void installUI(JComponent c) {
            System.out.println("install");
            super.installUI(c);
            JLayer layer = (JLayer) c;
            layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
        }

        @Override
        public void uninstallUI(JComponent c) {
            super.uninstallUI(c);
            mapPoints.remove((JLayer) c);
        }

        @Override
        protected void processMouseEvent(MouseEvent e, JLayer<? extends JLabel> l) {
            if (e.getID() == MouseEvent.MOUSE_CLICKED) {

                List<Point> points = mapPoints.get(l);
                if (points == null) {
                    points = new ArrayList<>(25);
                    mapPoints.put(l, points);
                }
                Point p = e.getPoint();
                p = SwingUtilities.convertPoint(e.getComponent(), p, l);
                points.add(p);
                l.repaint();

            }
        }

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2d = (Graphics2D) g.create();
            super.paint(g2d, c);
            g2d.setColor(Color.BLUE);
            g2d.drawRect(0, 0, c.getWidth() - 1, c.getHeight() - 1);
            List<Point> points = mapPoints.get((JLayer) c);
            if (points != null && points.size() > 0) {
                g2d.setColor(Color.RED);
                for (Point p : points) {
                    g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
                }
            }
            g2d.dispose();
        }
    }
}

青い境界線はレイヤーの一部としてレンダラーです。これにより、クリックできる場所に関するガイドが提供されます。これは、テストとデモンストレーションの目的で行いました。

于 2013-01-11T22:09:59.937 に答える