java - 需要帮助在 Graphics2D 中调整缩放系统 - Java
问题描述
这是我在这里的第一个问题。我正在尝试构建一个可通过缩放调整的白页。它位于 JScrollPane 内部,因此 JScrollPane 的 ScrollBars 的大小可在该 JPanel 的 Dimension 中调整。
我想将这些 ScrollBars 的大小调整为页面的大小(代码中的变量宽度和高度)+ 2 边框大小,因此完整大小等于页面 + 其周围边框大小的边距。如果缩放 = 1.0,它可以工作。
如果 zoom < 1.0,则滚动条小于 Page 并切掉它的一部分。如果缩放 > 1,则 Dimension 大小比页面大得多,在其右下角留下更大的边框,比borderSize 大。
我该怎么做呢?
PS:我是自学java的,去年在隔离区,从来没有老师,只有网络,所以有什么批评或建议,请告诉我。
这是JPanel的代码:
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import javax.swing.JSlider;
import javax.swing.JScrollPane;
import javax.swing.JLabel;
public class Main2 {
private MyPanel mp = new MyPanel();
private JFrame frame;
private JSlider zoomSlider = new JSlider();
private JLabel zoomLabel = new JLabel("Zoom: XXX");
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main2 window = new Main2();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Main2() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 619, 403);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SpringLayout springLayout = new SpringLayout();
frame.getContentPane().setLayout(springLayout);
springLayout.putConstraint(SpringLayout.SOUTH, zoomSlider, 40, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, zoomSlider, -115, SpringLayout.EAST, frame.getContentPane());
zoomSlider.setValue(100);
zoomSlider.setSnapToTicks(true);
zoomSlider.setPaintTicks(true);
zoomSlider.setMaximum(200);
zoomSlider.setMinorTickSpacing(5);
zoomSlider.setMinimum(5);
springLayout.putConstraint(SpringLayout.NORTH, zoomSlider, 0, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, zoomSlider, 0, SpringLayout.WEST, frame.getContentPane());
frame.getContentPane().add(zoomSlider);
JScrollPane scrollPane = new JScrollPane(mp);
springLayout.putConstraint(SpringLayout.NORTH, scrollPane, 10, SpringLayout.SOUTH, zoomSlider);
springLayout.putConstraint(SpringLayout.WEST, scrollPane, 10, SpringLayout.WEST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.SOUTH, scrollPane, -10, SpringLayout.SOUTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, scrollPane, -10, SpringLayout.EAST, frame.getContentPane());
frame.getContentPane().add(scrollPane);
springLayout.putConstraint(SpringLayout.NORTH, zoomLabel, 10, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, zoomLabel, 6, SpringLayout.EAST, zoomSlider);
frame.getContentPane().add(zoomLabel);
frame.addWindowStateListener(new WindowStateListener() {
@Override
public void windowStateChanged(WindowEvent arg0) {
// TODO Auto-generated method stub
mp.draw();
}
});
zoomSlider.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
int temp = (zoomSlider.getValue())-zoomSlider.getValue()%5;
setZoom(temp);
mp.draw();
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
int temp = (zoomSlider.getValue())-zoomSlider.getValue()%5;
setZoom(temp);
mp.draw();
}
});
mp.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getPreciseWheelRotation() < 0) {
setZoom(zoomSlider.getValue()- 5);
} else {
setZoom(zoomSlider.getValue()+ 5);
}
// zoom += e.getPreciseWheelRotation();
if (mp.getZoom()*100 < 10) {
setZoom(10);
}
mp.draw();
}
});
AdjustmentListener adj = new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
setZoom(zoomSlider.getValue());
mp.draw();
}
};
scrollPane.getVerticalScrollBar().addAdjustmentListener(adj);
scrollPane.getHorizontalScrollBar().addAdjustmentListener(adj);
}
public void setZoom(int n) {
mp.setZoom(n);
zoomSlider.setValue(n);
zoomLabel.setText("Zoom: "+mp.getZoom()+"x");
}
}
class MyPanel extends JPanel{
private static final long serialVersionUID = -716735372803790424L;
int borderSize=28;
int zoom=100;
int height = 3565;
int width = 2537;
int widthz, heightz;
public MyPanel() {
setBackground(Color.DARK_GRAY);
}
@Override
public Dimension getPreferredSize() {
int a, b;
String temp;
Float x, y;
x=(getZoom()*width); //Size of the page adjusted by zoom
y=(getZoom()*height);
temp = x.toString();
String temp1[] = temp.split("\\."); // converted to string to convert it to int
a = Integer.valueOf(temp1[0])+2*borderSize; //that value + 2 BorderSize
temp = y.toString();
String temp2[] = temp.split("\\.");
b = Integer.valueOf(temp2[0])+2*borderSize;
return new Dimension (a,b);
}
@Override
public void paintComponent (Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d = putZoom(g2d);
g2d.setColor(Color.WHITE);
g2d.fillRect(this.getX(),this.getY(), width, height);
g2d.setColor(Color.BLACK);
g2d.drawRect(this.getX()+borderSize,this.getY()+borderSize,width-2*borderSize,height-2*borderSize);
g2d.dispose();
}
public Graphics2D putZoom(Graphics2D g) {
AffineTransform at = new AffineTransform();
at.translate(borderSize,borderSize); // put the page a borderSize from the upper-left corner
at.scale(getZoom(),getZoom()); //adjust the page as zoom
Graphics2D g2d = g;
g2d.setTransform(at);
return g2d;
}
public void draw() { //this method is to update the draw from the main
repaint();
}
public Float getZoom() {
return Float.valueOf(zoom)/100;
}
public void setZoom(int zom) { //this method is to update Zoom from the main
zoom=zom;
String zoomheight []= (String.valueOf(getZoom()*height)).split("\\.");
heightz = Integer.valueOf(zoomheight[0]);
String zoomwidth []= (String.valueOf(getZoom()*width)).split("\\.");
widthz = Integer.valueOf(zoomwidth[0]);
}
public int getZoomInt() {
return this.zoom;
}
}
缩放(值从 0.1 到 2.0)。
我该如何改进呢?另外,我不知道如何更新 JScrollPane 的滚动条和缩放。感谢您的帮助。
更新:我创建了一个最小的可重现示例。
解决方案
介绍
在您更新您的问题之前,我已经开始着手解决这个问题。我使用了缩放百分比而不是缩放因子。
我创建了以下 GUI 并将初始状态设置为 30%。
我把内部做成了JPanel
一个棋盘格,这样你就可以更容易地看到缩放。我修改了您的初始值,因此内部JPanel
将代表一张 8 1/2 x 11 的纸,每英寸 50 像素。
这是 100% 的相同 GUI。
这是 10% 的相同 GUI。
解释
我创建了一个JFrame
和一个控件JPanel
来保存JSlider
. 我用一个GridLayout
来创建控件JPanel
。
我创建了一个JPanel
用于保存绘图的内部和一个JPanel
用于保存JScrollPane
. 我使显示JPanel
与内部的大小成比例,JPanel
所以我不会有任何拉伸问题。
让 GUI 重新验证/重绘原来是最大的挑战。我最后不得不去invalidate
,JScrollPane
两者JScrollBars
,和显示器JPanel
。JScrollBars
每次更改缩放百分比时,我还必须将其重置为零。
代码
这是完整的可运行代码。我把所有的类都做成了内部类,所以我可以把它作为一个代码块发布。
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ZoomJPanelGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ZoomJPanelGUI());
}
private int zoomPercentage = 30;
private DisplayPanel displayPanel;
private JFrame frame;
@Override
public void run() {
frame = new JFrame("Zoom JPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createControlPanel(), BorderLayout.BEFORE_FIRST_LINE);
this.displayPanel = new DisplayPanel(zoomPercentage);
frame.add(displayPanel.getPanel(), BorderLayout.AFTER_LAST_LINE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createControlPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
JLabel label = new JLabel("Zoom Percentage");
label.setFont(panel.getFont().deriveFont(Font.BOLD, 24f));
panel.add(label);
JSlider slider = new JSlider(
JSlider.HORIZONTAL, 10, 100, zoomPercentage);
slider.setFont(panel.getFont().deriveFont(16f));
slider.setMajorTickSpacing(30);
slider.setMinorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent event) {
JSlider slider = (JSlider) event.getSource();
if (!slider.getValueIsAdjusting()) {
zoomPercentage = (int) slider.getValue();
displayPanel.setZoomPercentage(zoomPercentage);
displayPanel.repaint();
frame.pack();
}
}
});
panel.add(slider);
return panel;
}
public class DisplayPanel {
private InnerPanel innerPanel;
private final JPanel panel;
private JScrollPane scrollPane;
private int zoomPercentage;
public DisplayPanel(int zoomPercentage) {
this.zoomPercentage = zoomPercentage;
this.panel = createDisplayPanel();
}
private JPanel createDisplayPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
this.innerPanel = new InnerPanel(zoomPercentage);
scrollPane = new JScrollPane(innerPanel);
scrollPane.setPreferredSize(new Dimension(475, 600));
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
public void setZoomPercentage(int zoomPercentage) {
this.zoomPercentage = zoomPercentage;
innerPanel.setZoomPercentage(zoomPercentage);
}
public JPanel getPanel() {
return panel;
}
public void repaint() {
innerPanel.repaint();
scrollPane.invalidate();
JScrollBar hScrollBar = scrollPane.getHorizontalScrollBar();
JScrollBar vScrollBar = scrollPane.getVerticalScrollBar();
hScrollBar.setValue(0);
vScrollBar.setValue(0);
hScrollBar.invalidate();
vScrollBar.invalidate();
panel.invalidate();
}
}
public class InnerPanel extends JPanel {
private static final long serialVersionUID = 1L;
private int maximumBorderSize = 25;
private int maximumCellSize = 50;
private int maximumHeight = 5500;
private int maximumWidth = 4250;
private int zoomPercentage;
public InnerPanel(int zoomPercentage) {
this.zoomPercentage = zoomPercentage;
}
public void setZoomPercentage(int zoomPercentage) {
this.zoomPercentage = zoomPercentage;
}
@Override
public Dimension getPreferredSize() {
int width = maximumWidth * zoomPercentage / 100;
int height = maximumHeight * zoomPercentage / 100;
return new Dimension(width, height);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int borderSize = maximumBorderSize * zoomPercentage / 100;
paintBackground(g2d);
paintBorder(g2d, borderSize);
paintCheckerboard(g2d, borderSize);
}
private void paintBackground(Graphics2D g2d) {
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
private void paintBorder(Graphics2D g2d, int borderSize) {
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(3f));
g2d.drawRect(borderSize, borderSize, getWidth() - 2 * borderSize,
getHeight() - 2 * borderSize);
}
private void paintCheckerboard(Graphics2D g2d, int borderSize) {
int cellSize = maximumCellSize * zoomPercentage / 100;
int width = maximumWidth - maximumBorderSize * 2 - 2;
int height = maximumHeight - maximumBorderSize * 2 - 2;
int cellWidth = width / maximumCellSize;
int cellHeight = height / maximumCellSize;
boolean isBlue = true;
int x = borderSize;
int y = borderSize;
int heightRemainder = height - cellHeight * cellSize;
for (int i = 0; i < cellHeight; i++) {
int widthRemainder = width - cellWidth * cellSize;
for (int j = 0; j < cellWidth; j++) {
if (isBlue) {
g2d.setColor(Color.BLUE);
} else {
g2d.setColor(Color.YELLOW);
}
isBlue = !isBlue;
g2d.fillRect(x, y, cellSize, cellSize);
x += cellSize;
if (widthRemainder > 0) {
x++;
widthRemainder--;
}
}
// isBlue = !isBlue;
x = borderSize;
y += cellSize;
if (heightRemainder > 0) {
y++;
heightRemainder--;
}
}
}
}
}
推荐阅读
- c - 是否有一种标准化的方法来解析 C 中的命令行参数?
- python - .sendmail 函数试图转换为 ASCII,我必须转换吗?
- python - 添加到一类列表
- json - 从需要登录的 java 中的 Jenkins API 获取 JSON 响应
- android - 初始化一个片段中的按钮,但设置单击另一个片段
- android - 点击广告会打开浏览器,但我无法返回 Android 应用的启动活动屏幕
- performance - 线程二叉搜索树,其中每个节点都必须保留对其后继节点的引用
- reactjs - Ant Design - 垂直的复选框组
- python - 使用 Python 和 Selenium 进行抓取 - 如果元素不存在,我应该如何返回“null”
- excel - Powershell:将日期导入 Excel 更改格式