Skip to content

Fix #712: guard against zero/negative plot area in Plot_AxesChart#974

Merged
timmolter merged 2 commits into
developfrom
timmolter-fix-712-plot-axes-chart-min-size-guard
Jun 19, 2026
Merged

Fix #712: guard against zero/negative plot area in Plot_AxesChart#974
timmolter merged 2 commits into
developfrom
timmolter-fix-712-plot-axes-chart-min-size-guard

Conversation

@timmolter

Copy link
Copy Markdown
Member

Problem

When a XChartPanel is resized to be very narrow — especially with multiple Y-axis groups — each axis column consumes horizontal space. Once the total axis width exceeds the chart width, the remaining plot area becomes zero or negative. Painting with that degenerate geometry caused a repeating NullPointerException deep inside PlotContent_XY.doPaint().

Fixes #712.

Root Cause

Plot_AxesChart.paint() computed width = xAxisBounds.getWidth() and height = yAxisBounds.getHeight() and passed them straight to new Rectangle2D.Double(...). When width <= 0 or height <= 0, every downstream renderer (PlotContent_XY, Legend_, etc.) received a rectangle with invalid dimensions, causing NPEs in AWT path operations.

The existing guard in PlotContent_.paint() (bounds.getWidth() < 30) handles near-zero cases but is insufficient when the bounds goes fully non-positive at the Plot_AxesChart level.

Fix

Added an early-exit guard in Plot_AxesChart.paint():

if (width <= 0 || height <= 0) {
  this.bounds = new Rectangle2D.Double(xOffset, yOffset, 0, 0);
  return;
}

A zero-size Rectangle2D is still assigned so downstream callers like Legend_.paint() (which reads chart.getPlot().getBounds()) always receive a non-null value; Legend_'s own existing width < 30 check then correctly skips painting.

Testing

  • Added paintingTinyChartDoesNotThrow() — paints a 1×1 chart
  • Added paintingTinyChartWithMultipleYAxisGroupsDoesNotThrow() — paints a 1×1 chart with 3 Y-axis groups (the original failure scenario)
  • Added TestForIssue712.java demo — run and resize the window as narrow as possible to verify no exception is thrown
  • Full xchart test suite passes (mvn test -pl xchart)

When the chart window is resized to be very narrow (especially with
multiple Y-axis groups), axis columns can consume more space than the
total chart width, leaving zero or negative dimensions for the plot area.
Painting with degenerate geometry caused a NullPointerException in AWT
path operations inside PlotContent_XY.doPaint().

Add an early-exit guard in Plot_AxesChart.paint() that assigns a
zero-size Rectangle2D and returns immediately when the computed plot
width or height is <= 0. This preserves a non-null getBounds() for
downstream components (e.g. Legend_) while skipping all rendering.

The existing guard in PlotContent_.paint() (width < 30) handles the
near-zero case for individual plot-content renderers, but is insufficient
when geometry goes fully non-positive at the Plot level.

Adds two regression tests and a TestForIssue712 demo class.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes #712 by preventing axes-based charts from attempting to paint when computed plot bounds become non-positive (e.g., extremely narrow XChartPanel with multiple Y-axis groups), which previously could trigger repeated NullPointerExceptions during rendering.

Changes:

  • Add an early-exit guard in Plot_AxesChart.paint() when plot width <= 0 or height <= 0, while still assigning a non-null bounds rectangle.
  • Add regression tests to ensure painting very small XY charts (including multiple Y-axis groups) does not throw.
  • Add a standalone demo (TestForIssue712) to reproduce/validate the narrow-resize scenario interactively.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
xchart/src/main/java/org/knowm/xchart/internal/chartpart/Plot_AxesChart.java Adds guard against zero/negative plot bounds to avoid downstream renderer failures.
xchart/src/test/java/org/knowm/xchart/XYChartTest.java Adds regression coverage for painting 1×1 charts (single and multi Y-axis groups).
xchart-demo/src/main/java/org/knowm/xchart/standalone/issues/TestForIssue712.java Adds a runnable demo to manually verify no exception when resizing extremely narrow.

…rly exit

When the plot area is zero/negative, the early return in Plot_AxesChart.paint()
now also clears the plot content's interactionData (if active) and resets its
plotBounds to the zero-size rectangle. This prevents stale tooltip/cursor
overlays from persisting after the window is shrunk too small to render.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@timmolter timmolter merged commit 911114b into develop Jun 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NullPointerException when xchart panel width is too small

2 participants