且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何将 MouseListener 添加到 Java Swing Canvas 上的项目

更新时间:2023-12-03 14:24:22

不要覆盖 paint 组件,使用 paintComponent 并且不要忘记调用 super.paintComponent

Don't override paint components, use paintComponent and don't forget to call super.paintComponent

一个组件已经有了位置"的概念,所以在绘制的时候,你的组件的左上角位置实际上是0x0

A component already has a concept of "location", so when painting, the top left position of your component is actually 0x0

你所做的实际上是超出了你的组件边界

What you are doing is actually painting beyond the boundaries of you component

例如,如果您将 Circle 放在 100x100 处,然后...

For example, if you place your Circle at 100x100 and then did...

g2.fillOval(x, y, DIMENSION, DIMENSION); 

您实际上会从 200x200 开始绘制(100 表示组件的实际位置,100 表示附加定位).

You would actually start painting at 200x200 (100 for the actual location of the component and 100 for you additional positioning).

改为使用

g2.fillOval(x, y, DIMENSION, DIMENSION); 

然后返回并尝试使用 JLayeredPane.

And go back and try using JLayeredPane.

您实际上可以编写自己的布局管理器,获取组件的位置及其首选大小并更新组件边界,然后将其应用到 JLayeredPane.这为您提供了绝对布局的好处",但让您了解 Swing 如何在情况发生变化时更新其组件.

You could actually write your own layout manager that takes the location of the component and it's preferred size and updates the components bounds and then apply this to a JLayeredPane. This gives you the "benefits" of an absolute layout, but keeps you within how Swing works to update its components when things change.

你在做任何事情时也应该小心......

You should also be careful with doing anything like...

Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

Graphics 上下文是共享资源.这意味着,您应用的任何内容在绘制下一个组件时仍然有效.这可能会产生一些奇怪的结果.

The Graphics context is a shared resource. That means, anything you apply to, will still be in effect when the next component is painted. This may produce some strange results.

而是尝试使用...

Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//...
g2.dispose();

更新

对于缩放,我会仔细查看 JXLayer(或 Java 7 中的 JLayer)

For zooming I would take a closer look at JXLayer (or JLayer in Java 7)

JXLayer(和优秀的 PBar 扩展)已经在网上流行了,所以你可以从 这里

The JXLayer (and excellent PBar extensions) have gone quite on the net, so you can grab a copy from here

(我试图找到一个更好的例子,但这是我在有限的时间里能做的***的)

(I tried finding a better example, but this is the best I could do with the limited time I have available)

更新了工作缩放示例

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;

public class TestJLayerZoom {

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

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

        private JXLayer<JComponent> layer;
        private DefaultTransformModel transformModel;
        private JPanel content;

        public TestPane() {

            content = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridy = 0;

            JLabel label = new JLabel("Hello");
            JTextField field = new JTextField("World", 20);

            content.add(label, gbc);
            content.add(field, gbc);

            gbc.gridy++;
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            final JSlider slider = new JSlider(50, 200);
            slider.addChangeListener(new ChangeListener() {

                @Override
                public void stateChanged(ChangeEvent e) {
                    int value = slider.getValue();
                    double scale = value / 100d;
                    transformModel.setScale(scale);
                }
            });
            content.add(slider, gbc);

            transformModel = new DefaultTransformModel();
            transformModel.setScaleToPreferredSize(true);

            Map<RenderingHints.Key, Object> hints = new HashMap<>();
            //hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            //hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

            layer = TransformUtils.createTransformJXLayer(content, transformModel, hints);
            setLayout(new BorderLayout());
            add(layer);


        }

    }

}

我已经留下了渲染提示来演示它们的使用,但我发现它们在文本字段中定位光标的问题,但您可能想玩玩

I've left the rendering hints in to demonstrate their use, but I found that they screwed with the positing of the cursor within the text field, but you might like to have a play