好的,那是对我不使用的API部分的一次有趣的冒险:首先,通读如何编写自定义Swing组件及其相关链接,这将为您提供基础知识,以了解什么是即将发生…
模型
介面
就个人而言,我总是从界面开始,界面使生活变得更好,并且它为您提供了更大的灵活性。现在,您应该从哪个模型扩展(根据您的要求)…?
好吧,我能找到的最佳选择是
BoundedRangeModel,它也被
JSlider…
使用…实际上,这意味着我不仅可以将此模型传递给视图,而且还可以传递给,而
JSlider无需任何额外的工作,就可以让滑块更改图像!! 双赢
import java.awt.Dimension;import java.awt.Image;import javax.swing.BoundedRangeModel;public interface ZoomModel extends BoundedRangeModel { public Image getImage(); public Dimension getScaledSize();}摘要
接下来,我想制作一个抽象版本,这是我放置“通用”功能的地方,对于大多数实现来说,它可能是相同的,在这种情况下,可能不需要,但是我有点像这样。 。
import java.awt.Dimension;import java.awt.Image;import javax.swing.DefaultBoundedRangeModel;public abstract class AbstractZoomModel extends DefaultBoundedRangeModel implements ZoomModel { public AbstractZoomModel() { super(100, 0, 0, 200); } @Override public Dimension getScaledSize() { Dimension size = new Dimension(0, 0); Image image = getImage(); if (image != null) { double scale = getValue() / 100d; size.width = (int) Math.round(image.getWidth(null) * scale); size.height = (int) Math.round(image.getHeight(null) * scale); } return size; }}因此,您可以在这里看到,我定义了一些基本属性,初始缩放级别为
100,最大级别为
200,最小级别为
0,此外,我还实现了
getScaledSize,使用了一点,使生活更轻松…
默认…
现在,因为我们喜欢,所以我们提供了该模型的“默认”实现。这是非常基本的,因为它所做的全部工作都是引用图像…
import java.awt.Image;public class DefaultZoomModel extends AbstractZoomModel { Image image; public DefaultZoomModel(Image image) { this.image = image; } @Override public Image getImage() { return image; }}您可以创建从
URL例如下载图像的实现…
风景
好的,这是实际的组件本身,已添加到您的UI中。它包含构造和准备UI委托以及管理模型所需的基本功能。这里感兴趣的关键是使用属性更改支持来提供对模型更改的通知,这很重要,如您所见…
import java.awt.Color;import java.awt.Dimension;import javax.swing.JComponent;import javax.swing.UIManager;public class ZoomComponent extends JComponent { private static final String uiClassID = "ZoomComponentUI"; private ZoomModel model; public ZoomComponent() { setBackground(Color.black); setFocusable(true); updateUI(); } public void setModel(ZoomModel newModel) { if (model != newModel) { ZoomModel old = model; this.model = newModel; firePropertyChange("model", old, newModel); } } public ZoomModel getModel() { return model; } @Override public Dimension getPreferredSize() { ZoomModel model = getModel(); Dimension size = new Dimension(100, 100); if (model != null) { size = model.getScaledSize(); } return size; } public void setUI(BasicZoomUI ui) { super.setUI(ui); } @Override public void updateUI() { if (UIManager.get(getUIClassID()) != null) { ZoomUI ui = (ZoomUI) UIManager.getUI(this); setUI(ui); } else { setUI(new BasicZoomUI()); } } public BasicZoomUI getUI() { return (BasicZoomUI) ui; } @Override public String getUIClassID() { return uiClassID; }}UI委托
现在还有其他有趣的东西…如果遵循标准约定,通常您会提供
abstractUI委托的概念,例如…
import javax.swing.plaf.ComponentUI;public abstract class ZoomUI extends ComponentUI { }由此,其他代表将会增长。
基本UI委托
常规通常会建议您提供一个“基本”实施,完成许多繁重的工作,但允许其他实施有机会跳到那里进行更改
import java.awt.Dimension;import java.awt.Graphics;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseWheelEvent;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import javax.swing.AbstractAction;import javax.swing.Action;import javax.swing.ActionMap;import javax.swing.InputMap;import javax.swing.JComponent;import javax.swing.KeyStroke;import javax.swing.event.ChangeEvent;import javax.swing.event.ChangeListener;import javax.swing.plaf.ComponentUI;public class BasicZoomUI extends ZoomUI { private ZoomComponent zoomComponent; private MouseAdapter mouseHandler; private ChangeListener changeHandler; private Action zoomIn; private Action zoomOut; private PropertyChangeListener propertyChangeHandler; protected ChangeListener getChangeHandler() { if (changeHandler == null) { changeHandler = new ChangeHandler(); } return changeHandler; } protected void installMouseListener() { mouseHandler = new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { zoomComponent.requestFocusInWindow(); } @Override public void mouseWheelMoved(MouseWheelEvent e) { int amount = e.getWheelRotation(); ZoomModel model = zoomComponent.getModel(); if (model != null) { int value = model.getValue(); model.setValue(value + amount); } } }; zoomComponent.addMouseListener(mouseHandler); zoomComponent.addMouseWheelListener(mouseHandler); } protected void installModelPropertyChangeListener() { propertyChangeHandler = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { ZoomModel old = (ZoomModel) evt.getOldValue(); if (old != null) { old.removeChangeListener(getChangeHandler()); } ZoomModel newValue = (ZoomModel) evt.getNewValue(); if (newValue != null) { newValue.addChangeListener(getChangeHandler()); } } }; zoomComponent.addPropertyChangeListener("model", propertyChangeHandler); } protected void installKeyBindings() { zoomIn = new ZoomInAction(); zoomOut = new ZoomOutAction(); InputMap inputMap = zoomComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0), "zoomIn"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0), "zoomOut"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, 0), "zoomIn"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, 0), "zoomOut"); ActionMap actionMap = zoomComponent.getActionMap(); actionMap.put("zoomIn", zoomIn); actionMap.put("zoomOut", zoomOut); } protected void installModelChangeListener() { ZoomModel model = getModel(); if (model != null) { model.addChangeListener(getChangeHandler()); } } @Override public void installUI(JComponent c) { zoomComponent = (ZoomComponent) c; installMouseListener(); installModelPropertyChangeListener(); installKeyBindings(); installModelChangeListener(); } protected void uninstallModelChangeListener() { getModel().removeChangeListener(getChangeHandler()); } protected void uninstallKeyBindings() { InputMap inputMap = zoomComponent.getInputMap(JComponent.WHEN_FOCUSED); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0), "donothing"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0), "donothing"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, 0), "donothing"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, 0), "donothing"); AbstractAction blank = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { } }; ActionMap actionMap = zoomComponent.getActionMap(); actionMap.put("zoomIn", blank); actionMap.put("zoomOut", blank); } protected void uninstallModelPropertyChangeListener() { zoomComponent.removePropertyChangeListener(propertyChangeHandler); propertyChangeHandler = null; } protected void uninstallMouseListener() { zoomComponent.removeMouseWheelListener(mouseHandler); mouseHandler = null; } @Override public void uninstallUI(JComponent c) { uninstallModelChangeListener(); uninstallModelPropertyChangeListener(); uninstallKeyBindings(); uninstallMouseListener(); mouseHandler = null; zoomComponent = null; } @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); paintImage(g); } protected void paintImage(Graphics g) { if (zoomComponent != null) { ZoomModel model = zoomComponent.getModel(); Image image = model.getImage(); Dimension size = model.getScaledSize(); int x = (zoomComponent.getWidth() - size.width) / 2; int y = (zoomComponent.getHeight() - size.height) / 2; g.drawImage(image, x, y, size.width, size.height, zoomComponent); } } public static ComponentUI createUI(JComponent c) { return new BasicZoomUI(); } protected ZoomModel getModel() { return zoomComponent == null ? null : zoomComponent.getModel(); } protected class ChangeHandler implements ChangeListener { @Override public void stateChanged(ChangeEvent e) { zoomComponent.revalidate(); zoomComponent.repaint(); } } protected class ZoomAction extends AbstractAction { private int delta; public ZoomAction(int delta) { this.delta = delta; } @Override public void actionPerformed(ActionEvent e) { ZoomModel model = getModel(); if (model != null) { model.setValue(model.getValue() + delta); } } } protected class ZoomOutAction extends ZoomAction { public ZoomOutAction() { super(-5); } } protected class ZoomInAction extends ZoomAction { public ZoomInAction() { super(5); } }}From here you could go and devise platform specific implementations, but I’ve
decided to stick with the basic delegate…
Putting it all together
If that wasn’t enough, before you can use any of it, you must install the
delegate…
UIManager.getDefaults().put("ZoomComponentUI", "your.awesome.package.name.BasicZoomUI");nb: Change
your.awesome.package.nameto reflect your actual package name…
Runnable Example
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.Jframe; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class TestZoom100 { public static void main(String[] args) {new TestZoom100(); } public TestZoom100() {EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } UIManager.getDefaults().put("ZoomComponentUI", "your.awesome.package.name.BasicZoomUI"); try { DefaultZoomModel model = new DefaultZoomModel(ImageIO.read(new File("/your/awesome/image.jpg"))); model.setValue(50); ZoomComponent zoomComp = new ZoomComponent(); zoomComp.setModel(model); JSlider slider = new JSlider(model); Jframe frame = new Jframe("Testing"); frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); frame.add(new JScrollPane(zoomComp)); frame.add(slider, BorderLayout.SOUTH); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } catch (IOException exp) { exp.printStackTrace(); } }}); } }Don’t forget to change the package name for the
BasicZoomUIto the package
name you have it stored in and actually specify a image file ;)



