Масштабирование JLayeredPane через JLayer и LayerUI
В этом вопросе о переполнении стека было предложено, чтобы наилучшим способом реализации масштабирования в приложениях Swing было использование JLayer
декораторы предоставляются с Java 7.
Я следую руководству по Oracle и думаю, что лучший способ сделать это - создать свой собственный ZoomUI
что расширяет LayerUI
, Пока я думаю, что у этого класса будет zoom
переменная-член, которая применяется до рисования фактического компонента.
Затем позже я смогу использовать этот же класс, чтобы перехватывать события мыши и отправлять их в координаты без увеличения.
У меня небольшие проблемы с первым шагом, и я не могу понять, почему g2.scale(zoom, zoom)
звонок не имеет никакого эффекта в моем SSCCE ниже.
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
public class Demo {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JLayeredPane panel = new JLayeredPane();
final ZoomUI layerUI = new ZoomUI();
final JLayer<JComponent> jLayer = new JLayer<JComponent>(panel, layerUI);
Button zoomIn = new Button("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom += 0.1;
jLayer.repaint();
}
});
zoomIn.setBounds(0,0,100,50);
panel.add(zoomIn);
Button zoomOut = new Button("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom -= 0.1;
jLayer.repaint();
}
});
zoomOut.setBounds(100,0,100,50);
panel.add(zoomOut);
frame.setPreferredSize(new Dimension(400,200));
frame.add(jLayer);
frame.pack();
frame.setVisible(true);
}
});
}
private static class ZoomUI extends LayerUI<JComponent> {
public int zoom = 1.5; // Changing this value seems to have no effect
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D) g.create();
g2.scale(zoom, zoom);
super.paint(g2, c);
g2.dispose();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
JLayer jlayer = (JLayer)c;
jlayer.setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.ACTION_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK
);
}
@Override
public void uninstallUI(JComponent c) {
JLayer jlayer = (JLayer)c;
jlayer.setLayerEventMask(0);
super.uninstallUI(c);
}
}
}
В этом примере я ожидаю, что кнопки увеличения / уменьшения будут увеличиваться в размерах при нажатии и при увеличении, чтобы правильно реагировать на события мыши. Это не нужно щелкать, где они жили, чтобы вызвать событие.
К сожалению, я даже не могу заставить их масштабировать, пока не нажму, изменив закомментированную строку, так что я действительно ценю некоторую помощь!
1 ответ
Ваша непосредственная проблема в том, что вы смешиваете тяжелые компоненты / компоненты AWT с легкими компонентами / компоненты Swing...
Button
является нативным компонентом, что означает, что его рисование находится вне контроля Swing и поэтому не подвержено его влиянию.
Вместо этого используйте JButton
вместо.
public class TestJLayerZoom {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
final ZoomUI layerUI = new ZoomUI();
final JLayer<JComponent> jLayer = new JLayer<JComponent>(panel, layerUI);
JButton zoomIn = new JButton("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom += 0.1;
jLayer.repaint();
}
});
panel.add(zoomIn);
JButton zoomOut = new JButton("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom -= 0.1;
jLayer.repaint();
}
});
panel.add(zoomOut);
frame.setPreferredSize(new Dimension(400, 200));
frame.add(jLayer);
frame.pack();
frame.setVisible(true);
}
});
}
private static class ZoomUI extends LayerUI<JComponent> {
public double zoom = 2; // Changing this value seems to have no effect
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D) g.create();
g2.scale(zoom, zoom);
super.paint(g2, c);
g2.dispose();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
JLayer jlayer = (JLayer) c;
jlayer.setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.ACTION_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK
);
}
@Override
public void uninstallUI(JComponent c) {
JLayer jlayer = (JLayer) c;
jlayer.setLayerEventMask(0);
super.uninstallUI(c);
}
}
}
Ваша следующая задача будет проработать, как переводить события мыши;)