Java 如何在子地块上共享DomainAxis/RangeAxis,而不在每个地块上绘制它们?
好吧,我几乎整天都在做这个,但没有成功。我试图使用JFreeChart创建一个由Java 如何在子地块上共享DomainAxis/RangeAxis,而不在每个地块上绘制它们?,java,plot,jfreechart,Java,Plot,Jfreechart,好吧,我几乎整天都在做这个,但没有成功。我试图使用JFreeChart创建一个由XYPlots组成的网格,其中域轴和范围轴分别链接到绘图的每一列和每一行。也就是说,同一行中的图具有相同的范围轴范围,而一列中的图具有相同的域轴范围 我能够通过使用CombinedDomainXYPlot的CombinedRangeXYPlots的XYPlots来实现该功能。基本上,我制作了一些XYPlot对象并将它们添加到CombinedRangeXYPlot对象中,然后将那些CombinedRangeXYPlot
XYPlot
s组成的网格,其中域轴和范围轴分别链接到绘图的每一列和每一行。也就是说,同一行中的图具有相同的范围轴范围,而一列中的图具有相同的域轴范围
我能够通过使用CombinedDomainXYPlot
的CombinedRangeXYPlot
s的XYPlot
s来实现该功能。基本上,我制作了一些XYPlot
对象并将它们添加到CombinedRangeXYPlot
对象中,然后将那些CombinedRangeXYPlot
对象添加到一个不绘制域轴的CombinedDomainXYPlot
实例中。(可能有另一种方法来堆叠绘图,而不是CombinedDomainXYPlot
,因为我没有使用合并域轴功能。)
正如预期的那样,每行的范围都会一起缩放。通过将相同的域轴添加到列中的每个子图中,我能够为每个列将域缩放到一起。结果如下所示
我现在有两个问题-首先,我想去掉每行下面的轴标签,只把它们放在底部,但保持比例链接
第二,范围轴的标签位于窗口边缘-如何将其取回
通常,我想了解CombinedRangeXYPlot
和CombinedRangeXYPlot
如何在多个图中使用相同的轴范围,而不在每个图下方绘制轴
编辑:以下是工作演示的代码:
主类
public class GridBlockPlotFrameExample {
private final JFrame frame;
private final XYPlot[][] phiPhiPlots;
private final XYPlot[] phiDPlots;
public GridBlockPlotFrameExample() {
frame = new JFrame("Density Plot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
phiDPlots = new XYPlot[4];
phiPhiPlots = new XYPlot[4][4];
createSubPlots();
CombinedRangeXYPlot[] rowPlots = new CombinedRangeXYPlot[phiDPlots.length + 1];
for (int i = 0; i < phiPhiPlots.length; i++) {
rowPlots[i + 1] = new CombinedRangeXYPlot();
for (int j = 0; j < phiPhiPlots[i].length; j++) {
if (phiPhiPlots[i][j] != null) {
rowPlots[i + 1].add(phiPhiPlots[i][j]);
} else {
rowPlots[i + 1].add(new XYPlot());
}
}
}
rowPlots[0] = new CombinedRangeXYPlot();
for (XYPlot phiDPlot : phiDPlots) {
rowPlots[0].add(phiDPlot);
}
StackedXYPlot gridPlot = new StackedXYPlot();
for (int i = rowPlots.length - 1; i >= 1; i--) {
XYPlot rowPlot = rowPlots[i];
gridPlot.add(rowPlot, 2);
}
gridPlot.add(rowPlots[0], 1);
JFreeChart chart = new JFreeChart("gridplot", JFreeChart.DEFAULT_TITLE_FONT, gridPlot, false);
chart.setBackgroundPaint(Color.WHITE);
ChartPanel panel = new ChartPanel(chart);
panel.setPreferredSize(new Dimension(300, 300));
panel.setMouseWheelEnabled(false);
panel.setRangeZoomable(true);
panel.setDomainZoomable(true);
frame.setContentPane(panel);
frame.pack();
RefineryUtilities.centerFrameOnScreen(frame);
}
private void createSubPlots() {
for (int i = 0; i < phiDPlots.length; i++) {
phiDPlots[i] = createPlot(createDataset());
}
XYPlot tempPlot;
for (int i = 0; i < phiPhiPlots.length; i++) {
for (int j = 0; j < phiPhiPlots.length; j++) {
tempPlot = createPlot(createDataset());
phiPhiPlots[j][i] = tempPlot; // (sic) YES this inversion is intentional
tempPlot.setDomainAxis((NumberAxis) phiDPlots[i].getDomainAxis());
}
}
}
private XYPlot createPlot(XYZDataset data) {
NumberAxis xAxis = new NumberAxis("X");
xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
xAxis.setLowerMargin(0.0);
xAxis.setUpperMargin(0.0);
xAxis.setAxisLinePaint(Color.white);
xAxis.setTickMarkPaint(Color.white);
NumberAxis yAxis = new NumberAxis("Y");
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
yAxis.setLowerMargin(0.0);
yAxis.setUpperMargin(0.0);
yAxis.setAxisLinePaint(Color.white);
yAxis.setTickMarkPaint(Color.white);
XYBlockRenderer renderer = new XYBlockRenderer();
PaintScale scale = new GrayPaintScale(-2.0, 1.0);
renderer.setPaintScale(scale);
XYPlot plot = new XYPlot(data, xAxis, yAxis, renderer);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinesVisible(false);
plot.setRangeGridlinePaint(Color.white);
plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5));
plot.setOutlinePaint(Color.blue);
return plot;
}
private XYZDataset createDataset() {
return new XYZDataset() {
@Override
public int getSeriesCount() {
return 1;
}
@Override
public int getItemCount(int series) {
return 10000;
}
@Override
public Number getX(int series, int item) {
return new Double(getXValue(series, item));
}
@Override
public double getXValue(int series, int item) {
return item / 100 - 50;
}
@Override
public Number getY(int series, int item) {
return new Double(getYValue(series, item));
}
@Override
public double getYValue(int series, int item) {
return item - (item / 100) * 100 - 50;
}
@Override
public Number getZ(int series, int item) {
return new Double(getZValue(series, item));
}
@Override
public double getZValue(int series, int item) {
double x = getXValue(series, item);
double y = getYValue(series, item);
return Math.sin(Math.sqrt(x * x + y * y) / 5.0);
}
@Override
public void addChangeListener(DatasetChangeListener listener) {
// ignore - this dataset never changes
}
@Override
public void removeChangeListener(DatasetChangeListener listener) {
// ignore
}
@Override
public DatasetGroup getGroup() {
return null;
}
@Override
public void setGroup(DatasetGroup group) {
// ignore
}
@Override
public Comparable getSeriesKey(int series) {
return "sin(sqrt(x + y))";
}
@Override
public int indexOf(Comparable seriesKey) {
return 0;
}
@Override
public DomainOrder getDomainOrder() {
return DomainOrder.ASCENDING;
}
};
}
public void show() {
frame.setVisible(true);
}
public static void main(String[] args) {
GridBlockPlotFrameExample example = new GridBlockPlotFrameExample();
example.show();
}
}
我相信,要使StackedXYPlot正常工作,我唯一要做的另一件事就是将组合域XYPlot.subplotAreas
的可见性更改为受保护的
我注意到在这个例子中,域轴的鼠标缩放是关闭的,但它确实会传播到列中的其他绘图
谢谢
伊戈尔
另一方面,我之所以要删除绘图下方的绘图,是因为最终我需要绘制至少6x7的绘图网格,因为有这么多,标签占据了大部分空间
编辑:我接受了Eric的回答,认为它是功能性的,但我正在研究一种不那么粗俗的方法-。如果我能让它完全正常运行,我会在那里进行更新。这真是个难题 从你的代码开始,我已经接近了:
ValueAxis a = phiDPlots[i].getDomainAxis();
a.setVisible(false);
tempPlot.setDomainAxis((NumberAxis) phiDPlots[i].getDomainAxis());
// draw all the subplots
for (int i = 0; i < this.getSubplots().size(); i++) {
CombinedRangeXYPlot plot = (CombinedRangeXYPlot) this.getSubplots().get(i);
PlotRenderingInfo subplotInfo = null;
if (info != null) {
subplotInfo = new PlotRenderingInfo(info.getOwner());
info.addSubplotInfo(subplotInfo);
}
if(i==getSubplots().size()-1){ // If the last row
for(int j=0; j < plot.getSubplots().size(); j++)
((XYPlot)plot.getSubplots().get(j)).getDomainAxis().setVisible(true);
}
plot.draw(g2, this.subplotAreas[i], anchor, parentState, subplotInfo);
if(i==getSubplots().size()-1){ // If the last row
for(int j=0; j < plot.getSubplots().size(); j++)
((XYPlot)plot.getSubplots().get(j)).getDomainAxis().setVisible(false);
}
}
//绘制所有子图
for(int i=0;i
您能分享一个我们可以使用的最小运行示例吗?也许以下内容适合您:1)
在域轴上设置可见(false)
(因此,列中的绘图一起缩放,但没有标签。2)在组合域XYPLOT中绘制域轴,因此,在每列的底部都有一个轴。@EricLeibenguth-我已经为我的问题的一个运行示例添加了代码。@EricLeibenguth-如果我能想出如何实现它,那就好了。我不知道如何为每列绘制单独的域轴。另外,我认为如果我在两个绘图之间共享的轴上设置Visible(false)
,它将不会在CombinedDomainXYPlot
中绘图。我想有办法强迫它画在那里,但我不知道怎么画。正如我在帖子中所说的,我真的不明白如何在组合域xyplot
中绘制绘图,并且该信息与子绘图共享,没有它们也会绘制域轴。我无法编译堆栈域xyplot
,因为这个.subplotAreas
是一个私有字段…谢谢Eric!我要试试这个!我可以修正导致最后一行太小的权重,这是一个小问题。这在很大程度上是有效的,但存在一个隐藏的性能缺陷-图表正在不断重新绘制,可能是因为setVisible
通知它的侦听器。太糟糕了。。。也许,您还可以使用自定义的NumberAxis
覆盖setVisible()
?Eric-是的,现在我这样做了:xAxis=newnumberaxis(“Phi”){@override public void setVisible(布尔标志){if(标志!=this.visible){this.visible=flag;}代码>我需要将可见的变量更改为受保护的…我接受这个答案。我认为我已经提出了一个解决方案,该解决方案更符合此类功能的实现方式(请参阅:)
// draw all the subplots
for (int i = 0; i < this.getSubplots().size(); i++) {
CombinedRangeXYPlot plot = (CombinedRangeXYPlot) this.getSubplots().get(i);
PlotRenderingInfo subplotInfo = null;
if (info != null) {
subplotInfo = new PlotRenderingInfo(info.getOwner());
info.addSubplotInfo(subplotInfo);
}
if(i==getSubplots().size()-1){ // If the last row
for(int j=0; j < plot.getSubplots().size(); j++)
((XYPlot)plot.getSubplots().get(j)).getDomainAxis().setVisible(true);
}
plot.draw(g2, this.subplotAreas[i], anchor, parentState, subplotInfo);
if(i==getSubplots().size()-1){ // If the last row
for(int j=0; j < plot.getSubplots().size(); j++)
((XYPlot)plot.getSubplots().get(j)).getDomainAxis().setVisible(false);
}
}