gpt4 book ai didi

java - 自定义java Swing组件模型,UIDelegate,组件格式

转载 作者:行者123 更新时间:2023-12-02 07:27:15 25 4
gpt4 key购买 nike

我的任务是创建一个自定义的 Swing 组件。我的组件在包含用于放大和缩小图像的 JSlider 的测试应用程序中正常运行。但是,我需要以 Model、UIDelegate 和 Component 类格式呈现我的自定义组件,我完全不知道如何转换我的代码以使其遵循这种格式。这是我的测试应用程序的代码。

package test;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;

import java.io.File;
import java.net.URL;

import javax.imageio.ImageIO;

public class ZoomDemo extends JComponent implements ChangeListener {

JPanel gui;
/**
* Displays the image.
*/
JLabel imageCanvas;
Dimension size;
double scale = 1.0;
private BufferedImage image;

public ZoomDemo() {
size = new Dimension(10, 10);
setBackground(Color.black);
try {
image = ImageIO.read(new File("car.jpg"));
} catch (Exception ex) {
ex.printStackTrace();
}
}

public void setImage(Image image) {
imageCanvas.setIcon(new ImageIcon(image));
}

public void initComponents() {
if (gui == null) {
gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(5, 5, 5, 5));
imageCanvas = new JLabel();
JPanel imageCenter = new JPanel(new GridBagLayout());
imageCenter.add(imageCanvas);
JScrollPane imageScroll = new JScrollPane(imageCenter);
imageScroll.setPreferredSize(new Dimension(300, 100));
gui.add(imageScroll, BorderLayout.CENTER);
}
}

public Container getGui() {
initComponents();
return gui;
}

public void stateChanged(ChangeEvent e) {
int value = ((JSlider) e.getSource()).getValue();
scale = value / 100.0;
paintImage();
}

protected void paintImage() {

int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
BufferedImage bi = new BufferedImage(
(int)(imageWidth*scale),
(int)(imageHeight*scale),
image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform at = AffineTransform.getTranslateInstance(0, 0);
at.scale(scale, scale);
g2.drawRenderedImage(image, at);
setImage(bi);
}

public Dimension getPreferredSize() {
int w = (int) (scale * size.width);
int h = (int) (scale * size.height);
return new Dimension(w, h);
}

private JSlider getControl() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 1, 500, 50);
slider.setMajorTickSpacing(50);
slider.setMinorTickSpacing(25);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(this);
return slider;
}

public static void main(String[] args) {
ZoomDemo app = new ZoomDemo();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(app.getGui());
app.setImage(app.image);

// frame.getContentPane().add(new JScrollPane(app));
frame.getContentPane().add(app.getControl(), "Last");
frame.setSize(700, 500);
frame.setLocation(200, 200);
frame.setVisible(true);
}
}

以下代码是我需要遵循的类格式

组件类
package component;

import javax.swing.JComponent;

import javax.swing.JSlider;
import javax.swing.plaf.ComponentUI;

public class ProgressBar extends JComponent {

public static ComponentUI createUI(JComponent c) {
return new ZoomUI();
}

public void installUI(JComponent c){



}

public void uninstallUI (JComponent c){

}
}

模型类
public class ZoomModel extends JSLider  {



}

UIDelegate 类
public class ZoomUI extends ComponentUI implements ChangeListener{

}

任何有关如何以这种格式实现自定义组件的帮助将不胜感激。我对 Swing 非常陌生,我在自定义组件上找到的文档非常困惑,而且帮助不大。

测试申请
package test;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.*;

import java.io.File;
import java.net.URL;

import javax.imageio.ImageIO;

import component.ZoomComponent;

public class ZoomDemo extends JPanel implements PropertyChangeListener, ActionListener {

ZoomComponent zoomer;
JPanel board;
private BufferedImage image;

public ZoomDemo( ) {
super(true);
setLayout(new BorderLayout( ));
board = new JPanel(true);
board.setPreferredSize(new Dimension(300, 300));
board.setBorder(new LineBorder(Color.black, 5));

zoomer = new ZoomComponent();
add(board, BorderLayout.NORTH);
add(zoomer, BorderLayout.SOUTH);



}


@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub

}

@Override
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub

}

public static void main(String[] args) {

UIManager.getDefaults().put("ZoomComponentUI", "component.BasicZoomUI");
ZoomDemo s= new ZoomDemo();
JFrame frame = new JFrame("Sample Sketch Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(s);
frame.pack( );
frame.setVisible(true);
}

}

最佳答案

好的,这是我不使用的 API 部分的一次有趣的冒险:),首先阅读 How to Write a Custom Swing Component它是相关的链接,这将为您提供了解即将发生的事情的基础工作......

模型

界面

就个人而言,我总是从界面开始,界面让生活更美好,它给你更多的灵 active 。现在,您应该从哪个模型扩展(根据您的要求)...?

嗯,我能找到的最佳选择是BoundedRangeModel , JSlider 也使用它...这实际上意味着我不仅可以将此模型传递给 View ,还可以传递给 JSlider无需任何额外工作,让 slider 更改图像!双赢

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 委托(delegate)和管理模型所需的基本功能。这里感兴趣的关键是使用属性更改支持来提供模型更改的通知,这很重要,正如您将看到的......
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 代表

现在其他有趣的东西...如果我们遵循标准约定,您通常会提供 abstract UI委托(delegate)的概念,例如......
import javax.swing.plaf.ComponentUI;

public abstract class ZoomUI extends ComponentUI {
}

由此,其他代表将成长......

基本 UI 委托(delegate)

惯例通常会建议你提供一个“基本”实现,做很多繁重的工作,但允许其他实现有机会跳进去改变事情
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);
}

}

}

从这里你可以去设计特定于平台的实现,但我决定坚持使用基本委托(delegate)......

把它们放在一起

如果这还不够,在你可以使用它之前,你必须安装委托(delegate)......
UIManager.getDefaults().put("ZoomComponentUI", "your.awesome.package.name.BasicZoomUI");

注意:更改 your.awesome.package.name以反射(reflect)您的实际包裹名称...

可运行示例
 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();
}
}
});
}

}

不要忘记更改 BasicZoomUI 的包名到您存储它的包名称并实际指定一个图像文件;)

关于java - 自定义java Swing组件模型,UIDelegate,组件格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26792529/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com